@useinsider/guido 3.27.0-beta.ee85b86 → 3.27.1-beta.842075e

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 (41) hide show
  1. package/README.md +5 -10
  2. package/dist/components/Guido.vue.js +7 -7
  3. package/dist/components/Guido.vue2.js +83 -86
  4. package/dist/composables/useHtmlCompiler.js +8 -9
  5. package/dist/composables/useModuleRepair.js +32 -63
  6. package/dist/composables/useRecommendation.js +8 -16
  7. package/dist/composables/useStripo.js +43 -44
  8. package/dist/config/compiler/htmlCompilerRules.js +6 -16
  9. package/dist/config/compiler/recommendationCompilerRules.js +29 -41
  10. package/dist/config/migrator/unsubscribeMigrator.js +112 -100
  11. package/dist/enums/recommendation.js +4 -5
  12. package/dist/extensions/Blocks/Recommendation/controls/image/index.js +58 -40
  13. package/dist/extensions/Blocks/Unsubscribe/block.js +104 -96
  14. package/dist/extensions/Blocks/Unsubscribe/utils/constants.js +4 -3
  15. package/dist/extensions/Blocks/Unsubscribe/utils/swapMergeTagInHref.js +5 -0
  16. package/dist/guido.css +1 -1
  17. package/dist/package.json.js +4 -4
  18. package/dist/src/@types/generic.d.ts +0 -7
  19. package/dist/src/composables/useModuleRepair.d.ts +0 -6
  20. package/dist/src/composables/useRecommendation.d.ts +0 -4
  21. package/dist/src/enums/recommendation.d.ts +0 -1
  22. package/dist/src/extensions/Blocks/Recommendation/controls/image/index.d.ts +2 -0
  23. package/dist/src/extensions/Blocks/Unsubscribe/utils/constants.d.ts +1 -0
  24. package/dist/src/extensions/Blocks/Unsubscribe/utils/swapMergeTagInHref.d.ts +1 -0
  25. package/dist/src/utils/dynamicContentConverter.d.ts +18 -20
  26. package/dist/src/utils/genericUtil.d.ts +8 -4
  27. package/dist/static/stripo-runtime-manifest.json.js +2 -2
  28. package/dist/utils/dynamicContentConverter.js +27 -41
  29. package/dist/utils/genericUtil.js +39 -39
  30. package/package.json +2 -2
  31. package/dist/components/organisms/dynamic-content/AmbiguousDynamicContentModal.vue.js +0 -24
  32. package/dist/components/organisms/dynamic-content/AmbiguousDynamicContentModal.vue2.js +0 -59
  33. package/dist/composables/useAmbiguousDynamicContent.js +0 -72
  34. package/dist/enums/dynamic-content.js +0 -4
  35. package/dist/src/components/organisms/dynamic-content/AmbiguousDynamicContentModal.vue.d.ts +0 -2
  36. package/dist/src/composables/useAmbiguousDynamicContent.d.ts +0 -7
  37. package/dist/src/enums/dynamic-content.d.ts +0 -3
  38. package/dist/src/stores/module-dynamic-content.d.ts +0 -30
  39. package/dist/src/utils/dynamicContentPendingMarker.d.ts +0 -2
  40. package/dist/stores/module-dynamic-content.js +0 -20
  41. package/dist/utils/dynamicContentPendingMarker.js +0 -6
@@ -1,52 +1,51 @@
1
- import { useActionsApi as j } from "./useActionsApi.js";
2
- import { useAmbiguousDynamicContent as z } from "./useAmbiguousDynamicContent.js";
3
- import { useBlocksConfig as $ } from "./useBlocksConfig.js";
4
- import { useConfig as G } from "./useConfig.js";
1
+ import { useActionsApi as N } from "./useActionsApi.js";
2
+ import { useBlocksConfig as j } from "./useBlocksConfig.js";
3
+ import { useConfig as z } from "./useConfig.js";
5
4
  import { useCustomInterfaceAppearance as v } from "./useCustomInterfaceAppearance.js";
6
- import { useFullStoryBridge as X } from "./useFullStoryBridge.js";
7
- import { useModuleRepair as J } from "./useModuleRepair.js";
8
- import { useStripoEventHandler as K } from "./useStripoEventHandler.js";
9
- import { useStripoNotifications as Q } from "./useStripoNotifications.js";
10
- import { useToaster as W } from "./useToaster.js";
11
- import { localePatch as Y } from "../config/i18n/index.js";
5
+ import { useFullStoryBridge as $ } from "./useFullStoryBridge.js";
6
+ import { useModuleRepair as G } from "./useModuleRepair.js";
7
+ import { useStripoEventHandler as X } from "./useStripoEventHandler.js";
8
+ import { useStripoNotifications as J } from "./useStripoNotifications.js";
9
+ import { useToaster as K } from "./useToaster.js";
10
+ import { localePatch as Q } from "../config/i18n/index.js";
12
11
  import { en as B } from "../config/i18n/en/index.js";
13
- import { ToasterTypeOptions as Z } from "../enums/toaster.js";
14
- import { useStripoApi as ee } from "../services/stripoApi.js";
15
- import te from "../static/styles/customEditorStyle.css.js";
12
+ import { ToasterTypeOptions as W } from "../enums/toaster.js";
13
+ import { useStripoApi as Y } from "../services/stripoApi.js";
14
+ import Z from "../static/styles/customEditorStyle.css.js";
16
15
  import { useEditorStore as T } from "../stores/editor.js";
17
- import { buildMergeTagEntries as oe, flattenDynamicContentList as re } from "../utils/genericUtil.js";
18
- import { getStripoRuntimeBaseUrl as ie } from "../utils/stripoRuntime.js";
16
+ import { buildMergeTagEntries as ee, flattenDynamicContentList as te } from "../utils/genericUtil.js";
17
+ import { getStripoRuntimeBaseUrl as oe } from "../utils/stripoRuntime.js";
19
18
  let d = null, F = !1;
20
- const ve = (t) => {
21
- const { features: u, template: m, isFeatureEnabled: p } = G(), { handleError: f, showToaster: A } = W(), { getToken: P, getCustomFonts: R, getSyncModulesStatus: D } = ee(), { handleEvent: U } = K(), { handleModuleAdd: V } = J(), { restorePending: I } = z(), { getStripoBlocksConfig: L } = $(), { getStripoNotifications: q } = Q(), g = () => d || (d = new Promise((n, s) => {
19
+ const ke = (t) => {
20
+ const { features: u, template: m, isFeatureEnabled: p } = z(), { handleError: f, showToaster: A } = K(), { getToken: P, getCustomFonts: R, getSyncModulesStatus: U } = Y(), { handleEvent: V } = X(), { handleModuleAdd: D } = G(), { getStripoBlocksConfig: I } = j(), { getStripoNotifications: L } = J(), g = () => d || (d = new Promise((n, a) => {
22
21
  if (document.getElementById("UiEditorScript")) {
23
22
  n();
24
23
  return;
25
24
  }
26
- const i = ie();
25
+ const i = oe();
27
26
  if (!i) {
28
- s(
27
+ a(
29
28
  new Error("guido.stripo.version is not set in package.json. Please configure the Stripo version.")
30
29
  );
31
30
  return;
32
31
  }
33
- const a = `${i}UIEditor.js`, e = document.createElement("script");
34
- e.id = "UiEditorScript", e.type = "module", e.src = a, e.onload = () => {
32
+ const s = `${i}UIEditor.js`, e = document.createElement("script");
33
+ e.id = "UiEditorScript", e.type = "module", e.src = s, e.onload = () => {
35
34
  F = !0, n();
36
35
  }, e.onerror = () => {
37
- e.remove(), s(new Error(`Failed to load Stripo UIEditor script from S3: ${a}`));
36
+ e.remove(), a(new Error(`Failed to load Stripo UIEditor script from S3: ${s}`));
38
37
  }, document.body.appendChild(e);
39
38
  }), d.catch(() => {
40
39
  d = null;
41
- }), d), x = async (n, s, i, a = [], e = !1, c = !1) => {
40
+ }), d), q = async (n, a, i, s = [], e = !1, c = !1) => {
42
41
  var w, k, b, _;
43
- const o = T(), { html: S, css: y } = n, { baseBlocks: E, extensions: O } = await L();
42
+ const o = T(), { html: S, css: y } = n, { baseBlocks: E, extensions: x } = await I();
44
43
  t.mark("blocks_config_ready");
45
- const h = ((w = u.value) == null ? void 0 : w.displayConditions) ?? !0, H = ((k = u.value) == null ? void 0 : k.modulesDisabled) ?? !1, C = c || (((b = m.value) == null ? void 0 : b.forceRecreate) ?? !1), M = "https://email-static.useinsider.com https://edge.fullstory.com https://rs.fullstory.com";
44
+ const h = ((w = u.value) == null ? void 0 : w.displayConditions) ?? !0, O = ((k = u.value) == null ? void 0 : k.modulesDisabled) ?? !1, C = c || (((b = m.value) == null ? void 0 : b.forceRecreate) ?? !1), H = "https://email-static.useinsider.com https://edge.fullstory.com https://rs.fullstory.com";
46
45
  t.setTemplate({ html: S, css: y, forceRecreate: C }), v().importCss(), t.mark("init_editor"), await window.UIEditor.initEditor(
47
46
  document.querySelector("#guido-editor"),
48
47
  {
49
- metadata: s,
48
+ metadata: a,
50
49
  html: S,
51
50
  css: y,
52
51
  forceRecreate: C,
@@ -59,11 +58,11 @@ const ve = (t) => {
59
58
  customAppearanceMergetags: !p("liquidSyntax"),
60
59
  customAppearanceMergetagsBorderColor: "#f1f3fe",
61
60
  customAppearanceMergetagsBackgroundColor: "#f1f3fe",
62
- customViewStyles: te,
61
+ customViewStyles: Z,
63
62
  conditionsEnabled: h,
64
63
  customConditionsEnabled: h,
65
64
  enableXSSSecurity: !0,
66
- modulesDisabled: H,
65
+ modulesDisabled: O,
67
66
  syncModulesEnabled: e,
68
67
  messageSettingsEnabled: !0,
69
68
  displayGmailAnnotations: !0,
@@ -74,18 +73,18 @@ const ve = (t) => {
74
73
  copyPasteEnabled: !1,
75
74
  selectElementAfterDrop: !0,
76
75
  sameFontSizeForOutlook: !0,
77
- allowedScriptSourceDomains: M,
76
+ allowedScriptSourceDomains: H,
78
77
  ...E ? { baseBlocks: E } : {},
79
78
  editorFonts: {
80
79
  showDefaultStandardFonts: !0,
81
80
  showDefaultNotStandardFonts: !0,
82
- customFonts: a
81
+ customFonts: s
83
82
  },
84
83
  mergeTags: [
85
84
  {
86
- entries: oe(
85
+ entries: ee(
87
86
  i.preselectedDynamicContentList,
88
- re((_ = m.value) == null ? void 0 : _.dynamicContentList),
87
+ te((_ = m.value) == null ? void 0 : _.dynamicContentList),
89
88
  p("liquidSyntax")
90
89
  )
91
90
  }
@@ -101,8 +100,8 @@ const ve = (t) => {
101
100
  },
102
101
  onTemplateLoaded() {
103
102
  try {
104
- const { activateCustomViewStyles: r, updateTimerInClonedTemplate: l } = j(), { injectFullStory: N } = X();
105
- v().importCss(), r(), N(), I(), l(), i.onReady(), o.isStripoInitialized = !0, o.loadingStatus = !1, setTimeout(() => {
103
+ const { activateCustomViewStyles: r, updateTimerInClonedTemplate: l } = N(), { injectFullStory: M } = $();
104
+ v().importCss(), r(), M(), l(), i.onReady(), o.isStripoInitialized = !0, o.loadingStatus = !1, setTimeout(() => {
106
105
  o.hasChanges = !1;
107
106
  }, 1e3), t.markReady();
108
107
  } catch (r) {
@@ -121,9 +120,9 @@ const ve = (t) => {
121
120
  onDataChanged() {
122
121
  o.hasChanges = !0, o.changeSeq += 1;
123
122
  },
124
- onEvent: U,
125
- onModuleAdd: V,
126
- notifications: q(),
123
+ onEvent: V,
124
+ onModuleAdd: D,
125
+ notifications: L(),
127
126
  // Stripo deselects the block on any click outside the canvas, so every surface
128
127
  // that belongs to the block's own flow has to be listed here (SD-153273).
129
128
  ignoreClickOutsideSelectors: [
@@ -133,23 +132,23 @@ const ve = (t) => {
133
132
  ".in-modal-v2-wrapper",
134
133
  ".in-toasts-wrapper"
135
134
  ],
136
- extensions: O,
137
- localePatch: Y
135
+ extensions: x,
136
+ localePatch: Q
138
137
  }
139
138
  );
140
139
  };
141
- return { initPlugin: async (n, s, i, a = !1) => {
140
+ return { initPlugin: async (n, a, i, s = !1) => {
142
141
  const e = T();
143
142
  try {
144
143
  t.mark("plugin_start"), t.setScriptPreloaded(F), await g(), t.mark("script_ready");
145
144
  const [c, o] = await Promise.all([
146
145
  R(),
147
- D()
146
+ U()
148
147
  ]);
149
- t.mark("fonts_sync_ready"), e.syncModulesEnabled = o, await x(n, s, i, c, o, a);
148
+ t.mark("fonts_sync_ready"), e.syncModulesEnabled = o, await q(n, a, i, c, o, s);
150
149
  } catch {
151
150
  e.loadingStatus = !1, A({
152
- type: Z.Error,
151
+ type: W.Error,
153
152
  message: B["An error has occurred. Please report the error code to support."],
154
153
  actionButton: {
155
154
  text: B["Reload page"],
@@ -163,5 +162,5 @@ const ve = (t) => {
163
162
  } };
164
163
  };
165
164
  export {
166
- ve as useStripo
165
+ ke as useStripo
167
166
  };
@@ -1,7 +1,6 @@
1
- import { PENDING_MARKER_PATTERN as c } from "../../utils/dynamicContentPendingMarker.js";
2
- import { stripFontTags as l } from "../../utils/stripFontTags.js";
3
- import { trimHrefWhitespace as d } from "../../utils/trimHrefWhitespace.js";
4
- const y = [
1
+ import { stripFontTags as c } from "../../utils/stripFontTags.js";
2
+ import { trimHrefWhitespace as l } from "../../utils/trimHrefWhitespace.js";
3
+ const f = [
5
4
  {
6
5
  id: "fix-url-encoding-start",
7
6
  description: "Replace {%22 with %7B%22 to fix URL encoding",
@@ -60,14 +59,14 @@ const y = [
60
59
  id: "strip-font-tags",
61
60
  description: 'Unwrap browser-translate-injected <font dir="auto"> tags, keeping inner content; other <font> elements are left intact.',
62
61
  type: "custom",
63
- processor: (e) => l(e),
62
+ processor: (e) => c(e),
64
63
  priority: 15
65
64
  },
66
65
  {
67
66
  id: "trim-href-whitespace",
68
67
  description: "Trim leading/trailing whitespace and &nbsp; from every href value",
69
68
  type: "custom",
70
- processor: (e) => d(e),
69
+ processor: (e) => l(e),
71
70
  priority: 16
72
71
  },
73
72
  {
@@ -184,15 +183,6 @@ const y = [
184
183
  flags: "g",
185
184
  priority: 45
186
185
  },
187
- {
188
- id: "remove-dc-pending-marker",
189
- description: "Strip the editor-only pending dynamic-content choice marker from compiled output",
190
- type: "regex",
191
- pattern: c,
192
- replacement: "",
193
- flags: "g",
194
- priority: 46
195
- },
196
186
  {
197
187
  id: "remove-script-tags",
198
188
  // SD-145051: parity with HB HtmlCleaner.removeUnsafeHtmlTags — strip <script> from
@@ -218,5 +208,5 @@ const y = [
218
208
  }
219
209
  ];
220
210
  export {
221
- y as defaultHtmlCompilerRules
211
+ f as defaultHtmlCompilerRules
222
212
  };
@@ -1,14 +1,14 @@
1
- import { useRecommendation as N } from "../../composables/useRecommendation.js";
2
- import { DUMMY_IMAGE_MAPPINGS as h, REGEX as d, VerticalOrientation as $, CSS as n, ATTRIBUTES as p, CONDITIONS as A, HTML as g } from "../../enums/recommendation.js";
3
- import { prepareRecommendationBlocks as O } from "./utils/recommendationCompilerUtils.js";
4
- const H = [
1
+ import { useRecommendation as R } from "../../composables/useRecommendation.js";
2
+ import { DUMMY_IMAGE_MAPPINGS as A, REGEX as m, VerticalOrientation as y, CSS as n, CONDITIONS as u, ATTRIBUTES as l, HTML as I } from "../../enums/recommendation.js";
3
+ import { prepareRecommendationBlocks as S } from "./utils/recommendationCompilerUtils.js";
4
+ const f = [
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
9
  processor: (t) => {
10
10
  let e = t;
11
- return Object.entries(h).forEach(([, r]) => {
11
+ return Object.entries(A).forEach(([, r]) => {
12
12
  Object.entries(r).forEach(([o, i]) => {
13
13
  e = e.replaceAll(i, `{{${o}}}`);
14
14
  });
@@ -42,17 +42,17 @@ const H = [
42
42
  description: "Adding recommendation unresponsive css",
43
43
  type: "custom",
44
44
  processor: (t) => {
45
- const { calculateCardWidth: e, getRecommendationCampaignData: r } = N();
45
+ const { calculateCardWidth: e, getRecommendationCampaignData: r } = R();
46
46
  let o = t;
47
- const i = o.match(d.ID);
47
+ const i = o.match(m.ID);
48
48
  if (i) {
49
- const s = [];
50
- if (i.forEach((c) => {
51
- const m = /recommendation-id="(.*?)"/i.exec(c), E = m ? m[1].trim() : "", u = r(E);
52
- u.textTrimming && u.orientation === $ && s.push(e(u));
53
- }), s.length) {
54
- const c = `width:${Math.min(...s)}px!important;`;
55
- o = o.replace(n.REGULAR_NAME_HEIGHT, `${n.TRIMMED_NAME_HEIGHT} ${c} ${n.ELLIPSIS}`).replace(n.REGULAR_NAME_CONTAINER_HEIGHT, n.TRIMMED_NAME_CONTAINER_CSS).replace(n.RESPONSIVE_NAME_SIZE, `${n.RESPONSIVE_NAME_HEIGHT} ${c} ${n.ELLIPSIS}`).replace(n.RESPONSIVE_NAME_CONTAINER_HEIGHT, n.TRIMMED_RESPONSIVE_NAME_CONTAINER_CSS);
49
+ const c = [];
50
+ if (i.forEach((s) => {
51
+ const a = /recommendation-id="(.*?)"/i.exec(s), d = a ? a[1].trim() : "", p = r(d);
52
+ p.textTrimming && p.orientation === y && c.push(e(p));
53
+ }), c.length) {
54
+ const s = `width:${Math.min(...c)}px!important;`;
55
+ o = o.replace(n.REGULAR_NAME_HEIGHT, `${n.TRIMMED_NAME_HEIGHT} ${s} ${n.ELLIPSIS}`).replace(n.REGULAR_NAME_CONTAINER_HEIGHT, n.TRIMMED_NAME_CONTAINER_CSS).replace(n.RESPONSIVE_NAME_SIZE, `${n.RESPONSIVE_NAME_HEIGHT} ${s} ${n.ELLIPSIS}`).replace(n.RESPONSIVE_NAME_CONTAINER_HEIGHT, n.TRIMMED_RESPONSIVE_NAME_CONTAINER_CSS);
56
56
  }
57
57
  }
58
58
  return o;
@@ -63,36 +63,24 @@ const H = [
63
63
  id: "prepare-recommendations",
64
64
  description: "Replacing product data with template variables in recommendation blocks",
65
65
  type: "custom",
66
- processor: (t) => O(t),
66
+ processor: (t) => S(t),
67
67
  priority: 48
68
68
  },
69
69
  {
70
70
  id: "add-discount-conditions",
71
71
  description: "Adding discount conditions to the recommendation block",
72
72
  type: "custom",
73
- processor: (t) => {
74
- let e = t;
75
- const r = e.match(d.ATTRIBUTE_PARAGRAPH), { getRecommendationCampaignData: o } = N();
76
- return r !== null && r.forEach((i) => {
77
- const s = i.match(d.CUSTOM_FIELD);
78
- if (!s)
79
- return;
80
- const [c] = s, m = c.match(d.CUSTOM_FIELD_INDEXES_PART), E = c.match(d.CUSTOM_FIELD_NAME_PART), u = i.match(d.ATTRIBUTE_PARAGRAPH_START_TAG);
81
- if (!m || !E || !u)
82
- return;
83
- const [T] = m, [I] = E, [_] = u, b = I.substring(1, I.length - 2), S = _.match(d.COMPOSITION) !== null;
84
- let a = c;
85
- if (S) {
86
- const y = T.substring(2, T.length - 3), l = o(y);
87
- b === p.OMNIBUS_PRICE && (l.priceBeforeTextValue && (a = `${l.priceBeforeTextValue}${a}`), l.priceAfterTextValue && (a = `${a}${l.priceAfterTextValue}`)), b === p.OMNIBUS_DISCOUNT && (l.discountBeforeTextValue && (a = `${l.discountBeforeTextValue}${a}`), l.discountAfterTextValue && (a = `${a}${l.discountAfterTextValue}`));
88
- }
89
- const R = T.substring(2);
90
- let f = "";
91
- b in A.IF && (f = A.IF[b].replaceAll(`{${p.DISCOUNT}}`, `${R}${p.DISCOUNT}`).replaceAll(`{${p.OMNIBUS_DISCOUNT}}`, `${R}${p.OMNIBUS_DISCOUNT}`).replaceAll(`{${p.OMNIBUS_PRICE}}`, `${R}${p.OMNIBUS_PRICE}`));
92
- const M = `${_}${a}${g.PARAGRAPH_END_TAG}`, C = `${f}${S ? M : i}${A.ELSE}${_}${g.PARAGRAPH_END_TAG}${A.END_IF}`;
93
- e = e.replace(i, C);
94
- }), e;
95
- },
73
+ processor: (t) => t.replace(m.ATTRIBUTE_PARAGRAPH, (e) => {
74
+ const r = e.match(m.CUSTOM_FIELD);
75
+ if (!r)
76
+ return e;
77
+ const [o] = r, i = o.match(m.CUSTOM_FIELD_INDEXES_PART), c = o.match(m.CUSTOM_FIELD_NAME_PART), s = e.match(m.ATTRIBUTE_PARAGRAPH_START_TAG);
78
+ if (!i || !c || !s)
79
+ return e;
80
+ const [a] = i, [d] = c, [p] = s, b = d.substring(1, d.length - 2), E = a.substring(2);
81
+ let _ = "";
82
+ return b in u.IF && (_ = u.IF[b].replaceAll(`{${l.DISCOUNT}}`, `${E}${l.DISCOUNT}`).replaceAll(`{${l.OMNIBUS_DISCOUNT}}`, `${E}${l.OMNIBUS_DISCOUNT}`).replaceAll(`{${l.OMNIBUS_PRICE}}`, `${E}${l.OMNIBUS_PRICE}`)), `${_}${e}${u.ELSE}${p}${I.PARAGRAPH_END_TAG}${u.END_IF}`;
83
+ }),
96
84
  priority: 53
97
85
  },
98
86
  {
@@ -147,8 +135,8 @@ const H = [
147
135
  ), e = e.replace(
148
136
  /@media[^{]*max-width\s*:\s*480px[^{]*\{((?:[^{}]*\{[^{}]*\})*[^{}]*)\}/g,
149
137
  (r, o) => {
150
- const i = o.match(/[^{}]+\{[^{}]*\}/g) || [], s = /ins-recommendation|product-image-cell|button-cell|product-info-cell/;
151
- return i.every((m) => s.test(m)) ? "" : r;
138
+ const i = o.match(/[^{}]+\{[^{}]*\}/g) || [], c = /ins-recommendation|product-image-cell|button-cell|product-info-cell/;
139
+ return i.every((a) => c.test(a)) ? "" : r;
152
140
  }
153
141
  )), e;
154
142
  },
@@ -208,5 +196,5 @@ const H = [
208
196
  }
209
197
  ];
210
198
  export {
211
- H as recommendationCompilerRules
199
+ f as recommendationCompilerRules
212
200
  };
@@ -1,146 +1,158 @@
1
- var x = Object.defineProperty;
2
- var B = (c, e, r) => e in c ? x(c, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : c[e] = r;
3
- var A = (c, e, r) => B(c, typeof e != "symbol" ? e + "" : e, r);
4
- import { MERGE_TAGS as f, PAGE_TYPES as p } from "../../enums/unsubscribe.js";
5
- import { UNSUBSCRIBE_BLOCK_SELECTOR as h, DATA_ATTRIBUTES as k } from "../../extensions/Blocks/Unsubscribe/utils/constants.js";
6
- import { useUnsubscribeStore as C } from "../../stores/unsubscribe.js";
7
- class $ {
1
+ var _ = Object.defineProperty;
2
+ var $ = (f, e, t) => e in f ? _(f, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : f[e] = t;
3
+ var k = (f, e, t) => $(f, typeof e != "symbol" ? e + "" : e, t);
4
+ import { MERGE_TAGS as c, PAGE_TYPES as T } from "../../enums/unsubscribe.js";
5
+ import { UNSUBSCRIBE_BLOCK_SELECTOR as y, DATA_ATTRIBUTES as d, UNSUBSCRIBE_MERGE_TAG_REGEX as h } from "../../extensions/Blocks/Unsubscribe/utils/constants.js";
6
+ import { swapMergeTagInHref as B } from "../../extensions/Blocks/Unsubscribe/utils/swapMergeTagInHref.js";
7
+ import { parsePageList as P } from "../../extensions/Blocks/Unsubscribe/utils/utils.js";
8
+ import { useUnsubscribeStore as M } from "../../stores/unsubscribe.js";
9
+ import { escapeHtml as A } from "../../utils/htmlEscape.js";
10
+ const S = "unsubscribe", N = "You can ", R = " from our emails, if you need to.", C = "{-{-UNSUBSCRIBE-LINK-}-}";
11
+ class H {
8
12
  constructor() {
9
- A(this, "parser");
13
+ k(this, "parser");
10
14
  this.parser = new DOMParser();
11
15
  }
12
16
  async migrate(e) {
13
17
  try {
14
- const r = this.parser.parseFromString(e, "text/html"), t = r.querySelectorAll("td.unsubscribe-block");
15
- if (t.length) {
16
- const s = C();
17
- await s.fetchTemplates(), this.migrateLegacyBlocks(t, s);
18
+ const t = this.parser.parseFromString(e, "text/html"), r = t.querySelectorAll("td.unsubscribe-block");
19
+ if (r.length) {
20
+ const i = M();
21
+ await i.fetchTemplates(), this.migrateLegacyBlocks(r, i, this.collectBlockTags(t, i));
18
22
  }
19
- const n = this.repairUnsubscribeLinks(r);
20
- return !t.length && !n ? e : r.documentElement.outerHTML;
21
- } catch (r) {
22
- return console.error("UnsubscribeMigrator failed:", r), e;
23
+ const s = this.repairUnsubscribeLinks(t);
24
+ return !r.length && !s ? e : t.documentElement.outerHTML;
25
+ } catch (t) {
26
+ return console.error("UnsubscribeMigrator failed:", t), e;
23
27
  }
24
28
  }
25
- migrateLegacyBlocks(e, r) {
26
- e.forEach((t) => {
27
- const n = t.getAttribute("id"), s = this.extractPaddingClass(t), l = t.getAttribute("bgcolor") || "", a = this.extractUnsubscribeContent(t), o = this.getCollectionTypeFromMergeTag(a.linkHref), b = r.getSelectedUnsubscribePagesByCollection(o);
29
+ migrateLegacyBlocks(e, t, r) {
30
+ e.forEach((s) => {
31
+ const i = s.getAttribute("id"), n = this.extractPaddingClass(s), o = s.getAttribute("bgcolor") || "", a = this.extractUnsubscribeContent(s, r), b = this.getCollectionTypeFromMergeTag(a.linkHref), u = t.getSelectedUnsubscribePagesByCollection(b);
28
32
  console.debug("[UnsubscribeMigrator]", {
29
33
  mergeTag: a.linkHref,
30
- collectionType: o,
31
- pageIds: b,
32
- paddingClass: s,
33
- bgColor: l
34
+ collectionType: b,
35
+ pageIds: u,
36
+ paddingClass: n,
37
+ bgColor: o
34
38
  });
35
- const u = this.buildUnsubscribeBlock(
39
+ const l = this.buildUnsubscribeBlock(
36
40
  a,
37
- o,
38
41
  b,
39
- s,
40
- l
41
- ), i = this.parser.parseFromString(
42
- `<table id="tempDoc"><tbody><tr>${u}</tr></tbody></table>`,
42
+ u,
43
+ n,
44
+ o
45
+ ), g = this.parser.parseFromString(
46
+ `<table id="tempDoc"><tbody><tr>${l}</tr></tbody></table>`,
43
47
  "text/html"
44
- ).querySelector(h);
45
- i && t.parentNode && (i.setAttribute("id", n || ""), t.parentNode.replaceChild(i, t));
48
+ ).querySelector(y);
49
+ g && s.parentNode && (g.setAttribute("id", i || ""), s.parentNode.replaceChild(g, s));
46
50
  });
47
51
  }
52
+ // The compiler resolves a typed tag only through a block that lists pages, so a page-less block carries no tag.
53
+ collectBlockTags(e, t) {
54
+ const r = /* @__PURE__ */ new Set();
55
+ return e.querySelectorAll(y).forEach((s) => {
56
+ var a, b, u;
57
+ if (!P(s.getAttribute(d.PAGE_LIST) || "").length)
58
+ return;
59
+ const i = Number(s.getAttribute(d.PAGE_TYPE)), n = c[i];
60
+ if (n) {
61
+ r.add(n);
62
+ return;
63
+ }
64
+ const o = (u = (b = (a = this.findLinkCandidates(s).primary) == null ? void 0 : a.getAttribute("href")) == null ? void 0 : b.match(h)) == null ? void 0 : u[0];
65
+ o && r.add(c[this.getCollectionTypeFromMergeTag(o)]);
66
+ }), e.querySelectorAll("td.unsubscribe-block").forEach((s) => {
67
+ const i = this.getCollectionTypeFromMergeTag(this.getLegacyLinkTag(s));
68
+ t.getSelectedUnsubscribePagesByCollection(i).length && r.add(c[i]);
69
+ }), r;
70
+ }
71
+ // Mirrors extractUnsubscribeContent: without a <p> the block migrates on the default tag.
72
+ getLegacyLinkTag(e) {
73
+ var r, s;
74
+ const { primary: t } = this.findLinkCandidates(e);
75
+ return !t || !(t.closest("p") || e.querySelector("p")) ? c.default : ((s = (r = t.getAttribute("href")) == null ? void 0 : r.match(h)) == null ? void 0 : s[0]) ?? c.default;
76
+ }
48
77
  // Re-derives the typed merge tag from data-unsubscribe-page-type for any v2
49
78
  // block whose anchor href is missing or the legacy default. Returns true when
50
79
  // at least one href was rewritten. Typed tags and custom URLs are left intact.
51
80
  repairUnsubscribeLinks(e) {
52
- const r = e.querySelectorAll(`${h}[${k.PAGE_TYPE}]`);
53
- let t = !1;
54
- return r.forEach((n) => {
55
- const s = n.querySelector('a[data-unsubscribe-link="true"], a.unsubscribe-link');
56
- if (!s)
81
+ const t = e.querySelectorAll(`${y}[${d.PAGE_TYPE}]`);
82
+ let r = !1;
83
+ return t.forEach((s) => {
84
+ const i = s.querySelector('a[data-unsubscribe-link="true"], a.unsubscribe-link');
85
+ if (!i)
57
86
  return;
58
- const l = s.getAttribute("href") || "";
59
- if (l && l !== f.default)
87
+ const n = i.getAttribute("href") || "";
88
+ if (n && n !== c.default)
60
89
  return;
61
- const a = Number(n.getAttribute(k.PAGE_TYPE)), o = f[a];
62
- o && (s.setAttribute("href", o), t = !0);
63
- }), t;
90
+ const o = Number(s.getAttribute(d.PAGE_TYPE)), a = c[o];
91
+ a && (i.setAttribute("href", a), r = !0);
92
+ }), r;
64
93
  }
65
94
  extractPaddingClass(e) {
66
- const t = (e.getAttribute("class") || "").match(/\bes-p\d+\b/);
67
- return t ? t[0] : "";
95
+ const r = (e.getAttribute("class") || "").match(/\bes-p\d+\b/);
96
+ return r ? r[0] : "";
97
+ }
98
+ hasVisibleContent(e) {
99
+ var t;
100
+ return !!((t = e.textContent) != null && t.trim() || e.querySelector("img"));
101
+ }
102
+ findLinkCandidates(e) {
103
+ const t = Array.from(/* @__PURE__ */ new Set([
104
+ ...Array.from(e.querySelectorAll("a.unsubscribe-link")),
105
+ ...Array.from(e.querySelectorAll('a[href*="unsubscribe"]'))
106
+ ])), r = (n) => h.test(n.getAttribute("href") || ""), s = (n) => this.hasVisibleContent(n), i = t.find((n) => s(n) && r(n)) ?? t.find((n) => s(n) && n.classList.contains("unsubscribe-link")) ?? t.find(r) ?? t.find(s) ?? t[0];
107
+ return { candidates: t, primary: i };
68
108
  }
69
- extractUnsubscribeContent(e) {
70
- var d;
71
- const r = e.querySelector("a.unsubscribe-link") || e.querySelector('a[href*="unsubscribe"]'), t = (r == null ? void 0 : r.closest("p")) || e.querySelector("p");
72
- if (!t)
73
- return {
74
- textBefore: "You can ",
75
- linkText: "unsubscribe",
76
- linkHref: "{{ins-unsubscribe-link}}",
77
- linkStyle: "",
78
- textAfter: " from our emails, if you need to.",
79
- isBold: !1,
80
- isItalic: !1,
81
- align: "center",
82
- paragraphStyle: ""
83
- };
84
- const n = e.getAttribute("align") || t.getAttribute("align") || "center", s = t.getAttribute("style") || "";
85
- if (!r)
86
- return {
87
- textBefore: "You can ",
88
- linkText: "unsubscribe",
89
- linkHref: "{{ins-unsubscribe-link}}",
90
- linkStyle: "",
91
- textAfter: " from our emails, if you need to.",
92
- isBold: !1,
93
- isItalic: !1,
94
- align: n,
95
- paragraphStyle: s
96
- };
97
- const l = ((d = r.textContent) == null ? void 0 : d.trim()) || "unsubscribe", a = r.getAttribute("href") || "{{ins-unsubscribe-link}}", o = r.getAttribute("style") || "", b = t.textContent || "", u = b.indexOf(l), g = u >= 0 ? b.substring(0, u).trim() : "You can ", i = u >= 0 ? b.substring(u + l.length).trim() : " from our emails, if you need to.", m = !!t.querySelector("b, strong"), y = !!t.querySelector("i, em");
98
- return {
99
- textBefore: g,
100
- linkText: l,
101
- linkHref: this.normalizeUnsubscribeHref(a),
102
- linkStyle: o,
103
- textAfter: i,
104
- isBold: m,
105
- isItalic: y,
106
- align: n,
107
- paragraphStyle: s
109
+ extractUnsubscribeContent(e, t) {
110
+ const r = e.cloneNode(!0), { candidates: s, primary: i } = this.findLinkCandidates(r), n = (i == null ? void 0 : i.closest("p")) ?? null, o = n || r.querySelector("p"), a = {
111
+ footerHtml: "",
112
+ linkText: S,
113
+ linkHref: c.default,
114
+ linkStyle: "",
115
+ align: "center",
116
+ paragraphStyle: ""
108
117
  };
118
+ if (!o || (a.align = e.getAttribute("align") || o.getAttribute("align") || "center", n || (a.paragraphStyle = o.getAttribute("style") || ""), !i))
119
+ return a;
120
+ a.linkText = this.hasVisibleContent(i) ? i.innerHTML.trim() : S, a.linkHref = this.normalizeUnsubscribeHref(i.getAttribute("href") || c.default), a.linkStyle = i.getAttribute("style") || "";
121
+ const b = this.getCollectionTypeFromMergeTag(a.linkHref), u = c[b];
122
+ return r.querySelectorAll("a[href]").forEach((l) => {
123
+ var m;
124
+ const p = l.getAttribute("href") || "", g = (m = p.match(h)) == null ? void 0 : m[0];
125
+ g && l.setAttribute("href", B(p, t.has(g) ? g : u));
126
+ }), s.filter((l) => l !== i && !this.hasVisibleContent(l)).forEach((l) => l.replaceWith(...Array.from(l.childNodes))), i.replaceWith(r.ownerDocument.createTextNode(C)), a.footerHtml = r.innerHTML.trim(), a;
109
127
  }
110
- buildUnsubscribeBlock(e, r, t, n, s) {
111
- const l = e.linkStyle ? ` style="${e.linkStyle}"` : "", u = `<a ${`href="${Object.values(f).includes(e.linkHref) ? f[r] : e.linkHref}" class="unsubscribe-link" target="_blank" data-unsubscribe-link="true"`}${l}>${e.linkText}</a>`, g = [];
112
- e.textBefore && g.push(e.textBefore), g.push(u), e.textAfter && g.push(e.textAfter);
113
- let i = g.join(" ");
114
- e.isBold && e.isItalic ? i = `<strong path="1,0"><em path="1,0,0">${i}</em></strong>` : e.isBold ? i = `<strong path="1,0">${i}</strong>` : e.isItalic && (i = `<em path="1,0">${i}</em>`);
115
- const m = e.align ? ` align="${e.align}"` : "", y = s ? ` bgcolor="${s}"` : "", d = e.paragraphStyle ? ` style="${e.paragraphStyle}"` : "", T = t.length > 0 ? ` ${k.PAGE_LIST}="${t.join(",")}"` : "", E = ` ${k.PAGE_TYPE}="${r}"`, S = "esd-block-text unsubscribe-block-v2 esd-block-unsubscribe esd-unsubscribe-block esd-extension-block";
128
+ buildUnsubscribeBlock(e, t, r, s, i) {
129
+ const n = e.linkStyle ? ` style="${A(e.linkStyle)}"` : "", a = Object.values(c).includes(e.linkHref) ? c[t] : e.linkHref, u = `<a ${`href="${A(a)}" class="unsubscribe-link" target="_blank" data-unsubscribe-link="true"`}${n}>${e.linkText}</a>`, l = e.paragraphStyle ? ` style="${A(e.paragraphStyle)}"` : "", p = e.footerHtml ? e.footerHtml.replace(C, () => u) : `<p path="1"${l}>${N}${u}${R}</p>`, g = e.align ? ` align="${e.align}"` : "", m = i ? ` bgcolor="${i}"` : "", L = r.length > 0 ? ` ${d.PAGE_LIST}="${r.join(",")}"` : "", U = ` ${d.PAGE_TYPE}="${t}"`, E = "esd-block-text unsubscribe-block-v2 esd-block-unsubscribe esd-unsubscribe-block esd-extension-block";
116
130
  return `
117
131
  <td
118
132
  data-migration="true"
119
133
  esd-extension-block-id="unsubscribe-block"
120
- class="${n ? `${S} ${n}` : S}"
121
- ${m}${y}${E}${T}
134
+ class="${s ? `${E} ${s}` : E}"
135
+ ${g}${m}${U}${L}
122
136
  >
123
- <p path="1"${d}>
124
- ${i}
125
- </p>
137
+ ${p}
126
138
  </td>
127
139
  `;
128
140
  }
129
141
  getCollectionTypeFromMergeTag(e) {
130
- return e === f[p.SUBSCRIPTION_PREFERENCE_CENTER] ? p.SUBSCRIPTION_PREFERENCE_CENTER : e === f[p.GLOBAL_UNSUBSCRIBE] ? p.GLOBAL_UNSUBSCRIBE : p.GLOBAL_UNSUBSCRIBE;
142
+ return e === c[T.SUBSCRIPTION_PREFERENCE_CENTER] ? T.SUBSCRIPTION_PREFERENCE_CENTER : e === c[T.GLOBAL_UNSUBSCRIBE] ? T.GLOBAL_UNSUBSCRIBE : T.GLOBAL_UNSUBSCRIBE;
131
143
  }
132
144
  normalizeUnsubscribeHref(e) {
133
- if (Object.values(f).includes(e))
145
+ if (Object.values(c).includes(e))
134
146
  return e;
135
- const t = e.match(/{{ins-(?:global-)?(?:preferences-)?unsubscribe-link}}/);
136
- return t ? t[0] : e.includes("unsubscribe") || e.includes("unsub") ? (console.warn(
147
+ const r = e.match(/{{ins-(?:global-)?(?:preferences-)?unsubscribe-link}}/);
148
+ return r ? r[0] : e.includes("unsubscribe") || e.includes("unsub") ? (console.warn(
137
149
  `[UnsubscribeMigrator] Unrecognized unsubscribe href format: "${e}". Defaulting to {{ins-unsubscribe-link}}`
138
150
  ), "{{ins-unsubscribe-link}}") : e;
139
151
  }
140
152
  }
141
- async function M(c) {
142
- return new $().migrate(c);
153
+ async function Y(f) {
154
+ return new H().migrate(f);
143
155
  }
144
156
  export {
145
- M as migrateUnsubscribe
157
+ Y as migrateUnsubscribe
146
158
  };
@@ -27,13 +27,12 @@ const e = 20, t = 320, s = "vertical", m = {
27
27
  ID: /recommendation-id="(.*?)"/gi,
28
28
  ATTRIBUTE_PARAGRAPH: /<p[^>]*?product-attr="(discount|omnibus_discount|omnibus_price)"[^>]*>[\S\s]*?<\/p>/gm,
29
29
  ATTRIBUTE_PARAGRAPH_START_TAG: /<p[^>]*?product-attr="(discount|omnibus_discount|omnibus_price)"[^>]*>/gm,
30
- COMPOSITION: /composition="true"/gm,
31
30
  CUSTOM_FIELD: /{{(?:reco_)?[0-9]+_[0-8]_(discount|omnibus_discount|omnibus_price)}}/gm,
32
31
  CUSTOM_FIELD_INDEXES_PART: /{{(?:reco_)?[0-9]+_[0-8]_/gm,
33
32
  CUSTOM_FIELD_NAME_PART: /_(discount|omnibus_discount|omnibus_price)}}/gm
34
- }, o = {
35
- PARAGRAPH_END_TAG: "</p>"
36
33
  }, a = {
34
+ PARAGRAPH_END_TAG: "</p>"
35
+ }, o = {
37
36
  REGULAR_NAME_HEIGHT: ".ext-product-name.ins-vertical p { height:90px!important;",
38
37
  TRIMMED_NAME_HEIGHT: ".ext-product-name.ins-vertical p { height:18px!important;",
39
38
  ELLIPSIS: "text-overflow:ellipsis!important; white-space:nowrap!important;",
@@ -47,10 +46,10 @@ const e = 20, t = 320, s = "vertical", m = {
47
46
  export {
48
47
  i as ATTRIBUTES,
49
48
  _ as CONDITIONS,
50
- a as CSS,
49
+ o as CSS,
51
50
  m as DUMMY_IMAGE_MAPPINGS,
52
51
  e as DefaultPadding,
53
- o as HTML,
52
+ a as HTML,
54
53
  t as MinDeviceViewport,
55
54
  n as REGEX,
56
55
  s as VerticalOrientation