@useinsider/guido 3.7.2-beta.6f556cb → 3.7.2-beta.7b4f9d0

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.
@@ -2,15 +2,15 @@ import n from "./UnsubscribeTypeSelection.vue2.js";
2
2
  /* empty css */
3
3
  import o from "../../../_virtual/_plugin-vue2_normalizer.js";
4
4
  var i = function() {
5
- var t = this, s = t._self._c, e = t._self._setupProxy;
6
- return s(e.WpDrawer, { attrs: { id: "unsubscribe-modal", "description-status": "", "description-text": e.descriptionText, "footer-button-group-options": e.footerButtonGroupOptions, status: e.unsubscribeStore.typeSelectionDrawerStatus, "title-text": e.trans("unsubscription-preference.select-unsubscribe-page-title") }, on: { cancelOrBackButtonEvent: e.closeModal, onCloseEvent: e.closeModal, primaryButtonEvent: e.selectCollection } }, [s(e.InSegments, { staticClass: "w-1", attrs: { "with-icon": "", align: "vertical", disable: e.isSelecting, "segment-list": e.segmentList, selected: e.selectedCollection, "skeleton-sizing": { width: 495, height: 180 }, "skeleton-status": e.skeletonStatus }, on: { click: e.changeCollection } })], 1);
5
+ var e = this, s = e._self._c, t = e._self._setupProxy;
6
+ return s(t.WpDrawer, { attrs: { id: "unsubscribe-modal", "description-status": "", "description-text": t.descriptionText, "footer-button-group-options": t.footerButtonGroupOptions, status: t.unsubscribeStore.typeSelectionDrawerStatus, "title-text": t.trans("unsubscription-preference.select-unsubscribe-page-title") }, on: { cancelOrBackButtonEvent: t.closeModal, onCloseEvent: t.closeModal, primaryButtonEvent: t.selectCollection } }, [s(t.InSegments, { staticClass: "w-1", attrs: { "with-icon": "", align: "vertical", disable: t.isSelecting, "segment-list": t.segmentList, selected: t.selectedCollection, "skeleton-sizing": { width: 495, height: 180 }, "skeleton-status": t.skeletonStatus }, on: { click: t.changeCollection } })], 1);
7
7
  }, r = [], c = /* @__PURE__ */ o(
8
8
  n,
9
9
  i,
10
10
  r,
11
11
  !1,
12
12
  null,
13
- "18e1220a"
13
+ "43c617a7"
14
14
  );
15
15
  const _ = c.exports;
16
16
  export {
@@ -1,110 +1,108 @@
1
- import { defineComponent as v, ref as b, computed as f, watch as _ } from "vue";
2
- import U from "../../wrappers/WpDrawer.vue.js";
3
- import { useToaster as N } from "../../../composables/useToaster.js";
4
- import { useTranslations as w } from "../../../composables/useTranslations.js";
5
- import { ACADEMY_LINKS as D } from "../../../enums/academy.js";
6
- import { ToasterTypeOptions as P } from "../../../enums/toaster.js";
7
- import { PAGE_TYPES as l, getTypeTranslations as R, UNSUBSCRIBE_PAGES_LINK as G } from "../../../enums/unsubscribe.js";
8
- import { useUnsubscribeStore as I } from "../../../stores/unsubscribe.js";
9
- import { InSegments as L } from "@useinsider/design-system-vue";
10
- const W = /* @__PURE__ */ v({
1
+ import { defineComponent as h, ref as b, computed as g, watch as _ } from "vue";
2
+ import v from "../../wrappers/WpDrawer.vue.js";
3
+ import { useToaster as U } from "../../../composables/useToaster.js";
4
+ import { useTranslations as N } from "../../../composables/useTranslations.js";
5
+ import { ACADEMY_LINKS as w } from "../../../enums/academy.js";
6
+ import { ToasterTypeOptions as R } from "../../../enums/toaster.js";
7
+ import { PAGE_TYPES as l, getTypeTranslations as D, UNSUBSCRIBE_PAGES_LINK as I } from "../../../enums/unsubscribe.js";
8
+ import { useUnsubscribeStore as P } from "../../../stores/unsubscribe.js";
9
+ import { InSegments as G } from "@useinsider/design-system-vue";
10
+ const V = /* @__PURE__ */ h({
11
11
  __name: "UnsubscribeTypeSelection",
12
- setup(O) {
13
- const t = w(), { showToaster: d } = N(), e = I(), n = b(!1), i = b(!0), o = b(l.GLOBAL_UNSUBSCRIBE), T = t(
12
+ setup(L) {
13
+ const e = N(), { showToaster: f } = U(), t = P(), n = b(!1), i = b(!0), o = b(l.GLOBAL_UNSUBSCRIBE), S = e(
14
14
  "unsubscription-preference.select-unsubscribe-page-description",
15
- { action: `<a href="${D.GLOBAL_UNSUBSCRIBE}" target="_blank">${t("ds-rules.visit-academy")}</a>` }
16
- ), y = f(() => [
15
+ { action: `<a href="${w.GLOBAL_UNSUBSCRIBE}" target="_blank">${e("ds-rules.visit-academy")}</a>` }
16
+ ), T = g(() => [
17
17
  {
18
- description: t("unsubscription-preference.type-global-unsubscribe-description"),
18
+ description: e("unsubscription-preference.type-global-unsubscribe-description"),
19
19
  icon: "line-contact-global-unsub-page",
20
- text: t("unsubscription-preference.type-global-unsubscribe"),
20
+ text: e("unsubscription-preference.type-global-unsubscribe"),
21
21
  value: l.GLOBAL_UNSUBSCRIBE,
22
- disable: e.isGlobalUnsubscribeDisabled,
22
+ disable: t.isGlobalUnsubscribeDisabled,
23
23
  position: "bottom",
24
- tooltipText: e.isGlobalUnsubscribeDisabled ? t("unsubscription-preference.global-unsub-added") : ""
24
+ tooltipText: t.isGlobalUnsubscribeDisabled ? e("unsubscription-preference.global-unsub-added") : ""
25
25
  },
26
26
  {
27
- description: t("unsubscription-preference.type-subscription-preferences-center-description"),
27
+ description: e("unsubscription-preference.type-subscription-preferences-center-description"),
28
28
  icon: "line-contact-sub-pref-center-page",
29
- text: t("unsubscription-preference.type-subscription-preferences-center"),
29
+ text: e("unsubscription-preference.type-subscription-preferences-center"),
30
30
  value: l.SUBSCRIPTION_PREFERENCE_CENTER,
31
- disable: e.isSubscriptionPreferencesCenterDisabled,
32
- tooltipText: e.isSubscriptionPreferencesCenterDisabled ? t("unsubscription-preference.pref-center-added") : ""
31
+ disable: t.isSubscriptionPreferencesCenterDisabled,
32
+ tooltipText: t.isSubscriptionPreferencesCenterDisabled ? e("unsubscription-preference.pref-center-added") : ""
33
33
  }
34
- ]), S = f(
35
- () => e.isGlobalUnsubscribeDisabled && e.isSubscriptionPreferencesCenterDisabled
36
- ), C = f(() => ({
34
+ ]), y = g(() => ({
37
35
  primaryButton: {
38
36
  styling: "solid",
39
37
  type: "primary",
40
- labelText: t(
38
+ labelText: e(
41
39
  n.value ? "unsubscription-preference.selecting-type" : "products.select-and-continue"
42
40
  ),
43
41
  loadingStatus: n.value,
44
- disabledStatus: S.value,
42
+ disabledStatus: !1,
45
43
  skeletonStatus: i.value,
46
44
  skeletonSizing: { width: 168, height: 40 }
47
45
  },
48
46
  cancelOrBackButton: {
49
47
  styling: "ghost",
50
48
  type: "secondary",
51
- labelText: t("products.cancel"),
49
+ labelText: e("products.cancel"),
52
50
  disabledStatus: n.value,
53
51
  skeletonStatus: i.value,
54
52
  skeletonSizing: { width: 78, height: 40 }
55
53
  }
56
- })), m = (s) => {
57
- e.typeSelectionDrawerStatus = !1, document.dispatchEvent(new CustomEvent("unsubscribe:cancel")), s && setTimeout(() => {
54
+ })), d = (s) => {
55
+ t.typeSelectionDrawerStatus = !1, document.dispatchEvent(new CustomEvent("unsubscribe:cancel")), s && setTimeout(() => {
58
56
  s();
59
57
  }, 500);
60
58
  }, E = (s) => {
61
59
  o.value = s;
62
- }, g = () => {
63
- const s = e.hasTemplatesByCollectionType, r = [];
60
+ }, m = () => {
61
+ const s = t.hasTemplatesByCollectionType, r = [];
64
62
  if (Object.entries(s).forEach(([c, p]) => {
65
63
  p || r.push(Number(c));
66
64
  }), r.length === 0)
67
65
  return !0;
68
- const B = R(), a = r.map((c) => B[c]);
66
+ const B = D(), a = r.map((c) => B[c]);
69
67
  let u = "";
70
68
  if (r.length === 1)
71
- u = t("unsubscription-preference.create-page-to-continue", {
69
+ u = e("unsubscription-preference.create-page-to-continue", {
72
70
  page: a[0]
73
71
  });
74
72
  else if (r.length === 2)
75
- u = t("unsubscription-preference.create-pages-to-continue", {
73
+ u = e("unsubscription-preference.create-pages-to-continue", {
76
74
  page1: a[0],
77
75
  page2: a[1]
78
76
  });
79
77
  else {
80
78
  const c = a.pop() ?? "", p = a.join(", ");
81
- u = t("unsubscription-preference.create-multiple-pages-to-continue", {
79
+ u = e("unsubscription-preference.create-multiple-pages-to-continue", {
82
80
  pages: p,
83
81
  lastPage: c
84
82
  });
85
83
  }
86
- return d({
87
- type: P.Warning,
84
+ return f({
85
+ type: R.Warning,
88
86
  message: u,
89
87
  actionButton: {
90
88
  text: "Go to Unsubscribe Pages",
91
89
  onClick: () => {
92
- window.location.href = G;
90
+ window.location.href = I;
93
91
  }
94
92
  }
95
93
  }), !1;
96
- }, h = async () => {
97
- if (n.value = !0, await e.fetchTemplates(), e.setCollection(o.value), !g()) {
98
- n.value = !1, m();
94
+ }, C = async () => {
95
+ if (n.value = !0, await t.fetchTemplates(), t.setCollection(o.value), !m()) {
96
+ n.value = !1, d();
99
97
  return;
100
98
  }
101
- n.value = !1, e.typeSelectionDrawerStatus = !1, e.pageSelectionDrawerStatus = !0;
99
+ n.value = !1, t.typeSelectionDrawerStatus = !1, t.pageSelectionDrawerStatus = !0;
102
100
  };
103
- return _(() => e.typeSelectionDrawerStatus, (s) => {
104
- s && (i.value = !0, o.value = l.GLOBAL_UNSUBSCRIBE, e.isGlobalUnsubscribeDisabled && (o.value = e.isSubscriptionPreferencesCenterDisabled ? 0 : l.SUBSCRIPTION_PREFERENCE_CENTER), i.value = !1);
105
- }), { __sfc: !0, trans: t, showToaster: d, unsubscribeStore: e, isSelecting: n, skeletonStatus: i, selectedCollection: o, descriptionText: T, segmentList: y, hasNoSelectableType: S, footerButtonGroupOptions: C, closeModal: m, changeCollection: E, validateTemplates: g, selectCollection: h, WpDrawer: U, InSegments: L };
101
+ return _(() => t.typeSelectionDrawerStatus, (s) => {
102
+ s && (i.value = !0, o.value = l.GLOBAL_UNSUBSCRIBE, t.isGlobalUnsubscribeDisabled && (o.value = t.isSubscriptionPreferencesCenterDisabled ? 0 : l.SUBSCRIPTION_PREFERENCE_CENTER), i.value = !1);
103
+ }), { __sfc: !0, trans: e, showToaster: f, unsubscribeStore: t, isSelecting: n, skeletonStatus: i, selectedCollection: o, descriptionText: S, segmentList: T, footerButtonGroupOptions: y, closeModal: d, changeCollection: E, validateTemplates: m, selectCollection: C, WpDrawer: v, InSegments: G };
106
104
  }
107
105
  });
108
106
  export {
109
- W as default
107
+ V as default
110
108
  };
@@ -1,4 +1,4 @@
1
- const a = [
1
+ const l = [
2
2
  {
3
3
  id: "fix-url-encoding-start",
4
4
  description: "Replace {%22 with %7B%22 to fix URL encoding",
@@ -111,13 +111,13 @@ const a = [
111
111
  <w:DontUseAdvancedTypographyReadingMail></w:DontUseAdvancedTypographyReadingMail>
112
112
  </w:WordDocument>
113
113
  </xml><![endif]-->`
114
- ], s = /<head>([\S\s]*)<\/head>/, o = new RegExp(s);
114
+ ], i = /<head>([\S\s]*)<\/head>/, o = new RegExp(i);
115
115
  if (!e.match(o))
116
116
  return e;
117
- let i = e;
117
+ let s = e;
118
118
  return t.forEach((r) => {
119
- i = i.replace("</head>", `${r}</head>`);
120
- }), i;
119
+ s = s.replace("</head>", `${r}</head>`);
120
+ }), s;
121
121
  },
122
122
  priority: 30
123
123
  },
@@ -138,8 +138,36 @@ const a = [
138
138
  replacement: "email-static.useinsider.com",
139
139
  replaceAll: !0,
140
140
  priority: 41
141
+ },
142
+ {
143
+ id: "convert-rgb-to-hex",
144
+ // SD-142395: rgb()/6-digit hex are verbose; hex/3-digit shorthand is byte-identical
145
+ // to render. Shrinks the whole email to stay under Gmail's ~102KB clip threshold.
146
+ // Leaves rgba()/8-digit hex (alpha) untouched.
147
+ description: "Convert rgb() colors to hex and collapse 6-digit hex to shorthand",
148
+ type: "custom",
149
+ processor: (e) => {
150
+ const t = (i) => i.toString(16).padStart(2, "0");
151
+ return e.replace(/rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)/gi, (i, o, n, s) => {
152
+ const [r, a, c] = [Number(o), Number(n), Number(s)];
153
+ return r > 255 || a > 255 || c > 255 ? i : `#${t(r)}${t(a)}${t(c)}`;
154
+ }).replace(/#([0-9a-f])\1([0-9a-f])\2([0-9a-f])\3\b/gi, "#$1$2$3");
155
+ },
156
+ priority: 44
157
+ },
158
+ {
159
+ id: "remove-contenteditable",
160
+ // SD-142395: contenteditable is a Stripo editor flag with zero effect in a
161
+ // delivered email. Stripping it globally shaves bytes off every text block,
162
+ // helping the whole email stay under Gmail's ~102KB clip threshold.
163
+ description: "Strip editor-only contenteditable attributes from compiled output",
164
+ type: "regex",
165
+ pattern: '\\s+contenteditable="[^"]*"',
166
+ replacement: "",
167
+ flags: "g",
168
+ priority: 45
141
169
  }
142
170
  ];
143
171
  export {
144
- a as defaultHtmlCompilerRules
172
+ l as defaultHtmlCompilerRules
145
173
  };
@@ -1,16 +1,16 @@
1
- import { useRecommendation as h } from "../../composables/useRecommendation.js";
2
- import { DUMMY_IMAGE_MAPPINGS as N, REGEX as T, VerticalOrientation as M, CSS as E, ATTRIBUTES as A, CONDITIONS as y, HTML as C } from "../../enums/recommendation.js";
3
- import { prepareRecommendationBlocks as x } from "./utils/recommendationCompilerUtils.js";
4
- const w = [
1
+ import { useRecommendation as N } from "../../composables/useRecommendation.js";
2
+ import { DUMMY_IMAGE_MAPPINGS as M, REGEX as d, VerticalOrientation as $, CSS as n, ATTRIBUTES as p, CONDITIONS as T, HTML as g } from "../../enums/recommendation.js";
3
+ import { prepareRecommendationBlocks as O } from "./utils/recommendationCompilerUtils.js";
4
+ const U = [
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: (c) => {
10
- let e = c;
11
- return Object.entries(N).forEach(([, l]) => {
12
- Object.entries(l).forEach(([n, s]) => {
13
- e = e.replaceAll(s, `{{${n}}}`);
9
+ processor: (o) => {
10
+ let e = o;
11
+ return Object.entries(M).forEach(([, r]) => {
12
+ Object.entries(r).forEach(([t, i]) => {
13
+ e = e.replaceAll(i, `{{${t}}}`);
14
14
  });
15
15
  }), e;
16
16
  },
@@ -41,21 +41,21 @@ const w = [
41
41
  id: "add-recommendation-unresponsive-css",
42
42
  description: "Adding recommendation unresponsive css",
43
43
  type: "custom",
44
- processor: (c) => {
45
- const { calculateCardWidth: e, getRecommendationCampaignData: l } = h();
46
- let n = c;
47
- const s = n.match(T.ID);
48
- if (s) {
49
- const a = [];
50
- if (s.forEach((i) => {
51
- const u = /recommendation-id="(.*?)"/i.exec(i), _ = u ? u[1].trim() : "", R = l(_);
52
- R.textTrimming && R.orientation === M && a.push(e(R));
53
- }), a.length) {
54
- const i = `width:${Math.min(...a)}px!important;`;
55
- n = n.replace(E.REGULAR_NAME_HEIGHT, `${E.TRIMMED_NAME_HEIGHT} ${i} ${E.ELLIPSIS}`).replace(E.REGULAR_NAME_CONTAINER_HEIGHT, E.TRIMMED_NAME_CONTAINER_CSS).replace(E.RESPONSIVE_NAME_SIZE, `${E.RESPONSIVE_NAME_HEIGHT} ${i} ${E.ELLIPSIS}`).replace(E.RESPONSIVE_NAME_CONTAINER_HEIGHT, E.TRIMMED_RESPONSIVE_NAME_CONTAINER_CSS);
44
+ processor: (o) => {
45
+ const { calculateCardWidth: e, getRecommendationCampaignData: r } = N();
46
+ let t = o;
47
+ const i = t.match(d.ID);
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
+ t = t.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);
56
56
  }
57
57
  }
58
- return n;
58
+ return t;
59
59
  },
60
60
  priority: 52
61
61
  },
@@ -63,34 +63,34 @@ const w = [
63
63
  id: "prepare-recommendations",
64
64
  description: "Replacing product data with template variables in recommendation blocks",
65
65
  type: "custom",
66
- processor: (c) => x(c),
66
+ processor: (o) => O(o),
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: (c) => {
74
- let e = c;
75
- const l = e.match(T.ATTRIBUTE_PARAGRAPH), { getRecommendationCampaignData: n } = h();
76
- return l !== null && l.forEach((s) => {
77
- const a = s.match(T.CUSTOM_FIELD);
78
- if (!a)
73
+ processor: (o) => {
74
+ let e = o;
75
+ const r = e.match(d.ATTRIBUTE_PARAGRAPH), { getRecommendationCampaignData: t } = N();
76
+ return r !== null && r.forEach((i) => {
77
+ const s = i.match(d.CUSTOM_FIELD);
78
+ if (!s)
79
79
  return;
80
- const [i] = a, u = i.match(T.CUSTOM_FIELD_INDEXES_PART), _ = i.match(T.CUSTOM_FIELD_NAME_PART), R = s.match(T.ATTRIBUTE_PARAGRAPH_START_TAG);
81
- if (!u || !_ || !R)
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
82
  return;
83
- const [b] = u, [I] = _, [d] = R, o = I.substring(1, I.length - 2), r = d.match(T.COMPOSITION) !== null;
84
- let t = i;
85
- if (r) {
86
- const S = b.substring(2, b.length - 3), m = n(S);
87
- o === A.OMNIBUS_PRICE && (m.priceBeforeTextValue && (t = `${m.priceBeforeTextValue}${t}`), m.priceAfterTextValue && (t = `${t}${m.priceAfterTextValue}`)), o === A.OMNIBUS_DISCOUNT && (m.discountBeforeTextValue && (t = `${m.discountBeforeTextValue}${t}`), m.discountAfterTextValue && (t = `${t}${m.discountAfterTextValue}`));
83
+ const [A] = m, [I] = E, [R] = u, b = I.substring(1, I.length - 2), S = R.match(d.COMPOSITION) !== null;
84
+ let a = c;
85
+ if (S) {
86
+ const f = A.substring(2, A.length - 3), l = t(f);
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
88
  }
89
- const p = b.substring(2);
90
- let f = "";
91
- o in y.IF && (f = y.IF[o].replaceAll(`{${A.DISCOUNT}}`, `${p}${A.DISCOUNT}`).replaceAll(`{${A.OMNIBUS_DISCOUNT}}`, `${p}${A.OMNIBUS_DISCOUNT}`).replaceAll(`{${A.OMNIBUS_PRICE}}`, `${p}${A.OMNIBUS_PRICE}`));
92
- const g = `${d}${t}${C.PARAGRAPH_END_TAG}`, $ = `${f}${r ? g : s}${y.ELSE}${d}${C.PARAGRAPH_END_TAG}${y.END_IF}`;
93
- e = e.replace(s, $);
89
+ const _ = A.substring(2);
90
+ let y = "";
91
+ b in T.IF && (y = T.IF[b].replaceAll(`{${p.DISCOUNT}}`, `${_}${p.DISCOUNT}`).replaceAll(`{${p.OMNIBUS_DISCOUNT}}`, `${_}${p.OMNIBUS_DISCOUNT}`).replaceAll(`{${p.OMNIBUS_PRICE}}`, `${_}${p.OMNIBUS_PRICE}`));
92
+ const C = `${R}${a}${g.PARAGRAPH_END_TAG}`, h = `${y}${S ? C : i}${T.ELSE}${R}${g.PARAGRAPH_END_TAG}${T.END_IF}`;
93
+ e = e.replace(i, h);
94
94
  }), e;
95
95
  },
96
96
  priority: 53
@@ -110,11 +110,11 @@ const w = [
110
110
  type: "custom",
111
111
  // Scoped to REC_START/REC_END markers so it cannot strip `product-attr`
112
112
  // from Items block elements, which the items compiler rule depends on.
113
- processor: (c) => {
113
+ processor: (o) => {
114
114
  const e = /\s+(?:esd-extension-block-id|data-attribute-type|data-visibility|data-text-before|data-text-after|product-attr|composition)="[^"]*"/g;
115
- return c.replace(
115
+ return o.replace(
116
116
  /<!--REC_START-->([\s\S]*?)<!--REC_END-->/g,
117
- (l, n) => `<!--REC_START-->${n.replace(e, "")}<!--REC_END-->`
117
+ (r, t) => `<!--REC_START-->${t.replace(e, "")}<!--REC_END-->`
118
118
  );
119
119
  },
120
120
  priority: 55
@@ -123,8 +123,8 @@ const w = [
123
123
  id: "strip-unused-recommendation-classes",
124
124
  description: "Remove CSS classes not referenced by any style rule from recommendation elements",
125
125
  type: "custom",
126
- processor: (c) => {
127
- let e = c.replace(
126
+ processor: (o) => {
127
+ let e = o.replace(
128
128
  / 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,
129
129
  ""
130
130
  );
@@ -136,8 +136,8 @@ const w = [
136
136
  id: "remove-empty-mobile-layout-artifacts",
137
137
  description: "Remove empty mobile container rows and unused mobile layout CSS",
138
138
  type: "custom",
139
- processor: (c) => {
140
- let e = c;
139
+ processor: (o) => {
140
+ let e = o;
141
141
  return e = e.replace(
142
142
  /<tr[^>]*class="ins-recommendation-mobile-row"[^>]*><\/tr>/g,
143
143
  ""
@@ -146,75 +146,50 @@ const w = [
146
146
  ""
147
147
  ), e = e.replace(
148
148
  /@media[^{]*max-width\s*:\s*480px[^{]*\{((?:[^{}]*\{[^{}]*\})*[^{}]*)\}/g,
149
- (l, n) => {
150
- const s = n.match(/[^{}]+\{[^{}]*\}/g) || [], a = /ins-recommendation|product-image-cell|button-cell|product-info-cell/;
151
- return s.every((u) => a.test(u)) ? "" : l;
149
+ (r, t) => {
150
+ const i = t.match(/[^{}]+\{[^{}]*\}/g) || [], s = /ins-recommendation|product-image-cell|button-cell|product-info-cell/;
151
+ return i.every((m) => s.test(m)) ? "" : r;
152
152
  }
153
153
  )), e;
154
154
  },
155
155
  priority: 57
156
156
  },
157
157
  {
158
- id: "deduplicate-inline-styles",
159
- description: "Replace repeated inline styles with CSS class references within recommendation blocks",
158
+ id: "protect-gmail-button-link-color",
159
+ // Gmail overrides link colors with `.ii a[href] { color: #15c }`. Force
160
+ // `!important` on es-button anchor colors so the intended button text color
161
+ // wins. Kept INLINE (never moved into a <style> class) so it survives Gmail's
162
+ // clipping — "view entire message" strips <style> blocks but keeps inline styles.
163
+ // (SD-142395: split out of the removed deduplicate-inline-styles rule.)
164
+ description: "Force !important on es-button link color to defeat Gmail link-color override",
160
165
  type: "custom",
161
- processor: (c) => {
162
- const e = c.replace(
163
- /<a\b[^>]*\bes-button\b[^>]*>/g,
164
- (o) => o.replace(
165
- /([;"]color:)([^;"]+)/g,
166
- (r, t, p) => p.includes("!important") ? r : `${t}${p} !important`
167
- )
168
- ), l = /<!--REC_START-->([\s\S]*?)<!--REC_END-->/g, n = / style="([^"]*)"/g, s = /* @__PURE__ */ new Map();
169
- let a = l.exec(e);
170
- for (; a !== null; ) {
171
- let o = n.exec(a[1]);
172
- for (; o !== null; ) {
173
- const [, r] = o;
174
- s.set(r, (s.get(r) || 0) + 1), o = n.exec(a[1]);
175
- }
176
- n.lastIndex = 0, a = l.exec(e);
177
- }
178
- const i = /* @__PURE__ */ new Map(), u = [];
179
- let _ = 0;
180
- if (s.forEach((o, r) => {
181
- if (!r.includes("v-text-anchor") && o >= 6) {
182
- const t = `rc${_++}`, p = r.endsWith(";") ? r : `${r};`;
183
- i.set(r, t), u.push(`.${t}{${p}}`);
184
- }
185
- }), i.size === 0) {
186
- let o = e;
187
- return o = o.replaceAll("<!--REC_START-->", ""), o = o.replaceAll("<!--REC_END-->", ""), o;
188
- }
189
- const R = (o) => o.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), b = (o, r) => `${o.slice(0, -1)} ${r}"`, I = /* @__PURE__ */ new Map();
190
- i.forEach((o, r) => {
191
- const t = R(r);
192
- I.set(r, {
193
- caseA: new RegExp(`(class="[^"]*")((?:[^>]*?)) style="${t}"`, "g"),
194
- caseB: new RegExp(` style="${t}"((?:[^>]*?))(class="[^"]*")`, "g")
195
- });
196
- });
197
- let d = e.replace("</style>", `${u.join("")}</style>`);
198
- return d = d.replace(
199
- /<!--REC_START-->([\s\S]*?)<!--REC_END-->/g,
200
- (o, r) => {
201
- let t = r;
202
- return i.forEach((p, f) => {
203
- const g = I.get(f);
204
- t = t.replace(
205
- g.caseA,
206
- ($, S, m) => b(S, p) + m
207
- ), t = t.replace(
208
- g.caseB,
209
- ($, S, m) => S + b(m, p)
210
- ), t = t.replaceAll(` style="${f}"`, ` class="${p}"`);
211
- }), t;
212
- }
213
- ), d = d.replaceAll("<!--REC_START-->", ""), d = d.replaceAll("<!--REC_END-->", ""), d;
214
- },
166
+ processor: (o) => o.replace(
167
+ /<a\b[^>]*\bes-button\b[^>]*>/g,
168
+ (e) => e.replace(
169
+ /([;"]color:)([^;"]+)/g,
170
+ (r, t, i) => i.includes("!important") ? r : `${t}${i} !important`
171
+ )
172
+ ),
215
173
  priority: 58
174
+ },
175
+ {
176
+ id: "minify-recommendation-whitespace",
177
+ // SD-142395: shrink the compiled recommendation block to keep emails under
178
+ // Gmail's ~102KB clip threshold. The editor templates emit deeply-indented
179
+ // markup that the P48 DOMParser round-trip preserves, and nothing else in the
180
+ // pipeline minifies it. Scoped to REC_START/REC_END so it only touches
181
+ // recommendation markup, and strips those markers last (relocated here from the
182
+ // removed deduplicate-inline-styles rule). Render-critical styles are left inline
183
+ // rather than classed, so they survive Gmail clipping.
184
+ description: "Collapse whitespace inside recommendation blocks and strip boundary markers",
185
+ type: "custom",
186
+ processor: (o) => {
187
+ const e = (r) => r.replace(/>\s+</g, "><").replace(/<[^>]+>/g, (t) => t.replace(/\s+/g, " "));
188
+ return o.replace(/<!--REC_START-->([\s\S]*?)<!--REC_END-->/g, (r, t) => e(t)).replaceAll("<!--REC_START-->", "").replaceAll("<!--REC_END-->", "");
189
+ },
190
+ priority: 99
216
191
  }
217
192
  ];
218
193
  export {
219
- w as recommendationCompilerRules
194
+ U as recommendationCompilerRules
220
195
  };
package/dist/guido.css CHANGED
@@ -1 +1 @@
1
- .gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-73199fa4] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-195ab6d4]{position:relative;display:inline-block}.new-tag[data-v-195ab6d4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-195ab6d4] .guido__view-option-selection-desktop svg,[data-v-195ab6d4] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-195ab6d4] .in-segments-wrapper__button_selected,[data-v-195ab6d4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-195ab6d4] .in-tooltip-wrapper__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-64c52560]{gap:8px}.version-history__toolbar[data-v-64c52560]{gap:4px}.view-options-wrapper[data-v-d405ca59]{position:relative;display:inline-block}.new-tag[data-v-d405ca59]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-d405ca59] .guido__verion-history-view-option-selection-desktop svg,[data-v-d405ca59] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-d405ca59] .in-segments-wrapper__button_selected,[data-v-d405ca59] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-d405ca59] .in-tooltip-wrapper__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-82128f7d]{gap:4px}.header-wrapper[data-v-5c02dcc7]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-50dac6de]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-50dac6de]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-50dac6de]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-f6a8cb4c]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-f6a8cb4c]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-f6a8cb4c]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-f6a8cb4c]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-f6a8cb4c]{object-fit:cover;transform:scale(1)}[data-v-18e1220a] .guido__verion-history-view-option-selection-desktop svg,[data-v-18e1220a] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-18e1220a] .in-segments-wrapper__button_selected,[data-v-18e1220a] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-988f8da6]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-988f8da6]{min-height:504px}.iframe-wrapper[data-v-e0424e99]{width:258px}.iframe-scaled[data-v-e0424e99]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-7419ae06] .vueperslides__bullets,[data-v-796d193b] .vueperslides__bullets{pointer-events:none!important}[data-v-796d193b] .vueperslides__parallax-wrapper{height:110px!important}[data-v-cadfc82d] .vueperslides__bullets{pointer-events:none!important}[data-v-cadfc82d] .vueperslides__parallax-wrapper{height:110px!important}
1
+ .gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-73199fa4] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-195ab6d4]{position:relative;display:inline-block}.new-tag[data-v-195ab6d4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-195ab6d4] .guido__view-option-selection-desktop svg,[data-v-195ab6d4] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-195ab6d4] .in-segments-wrapper__button_selected,[data-v-195ab6d4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-195ab6d4] .in-tooltip-wrapper__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-64c52560]{gap:8px}.version-history__toolbar[data-v-64c52560]{gap:4px}.view-options-wrapper[data-v-d405ca59]{position:relative;display:inline-block}.new-tag[data-v-d405ca59]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-d405ca59] .guido__verion-history-view-option-selection-desktop svg,[data-v-d405ca59] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-d405ca59] .in-segments-wrapper__button_selected,[data-v-d405ca59] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-d405ca59] .in-tooltip-wrapper__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-82128f7d]{gap:4px}.header-wrapper[data-v-5c02dcc7]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-50dac6de]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-50dac6de]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-50dac6de]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-f6a8cb4c]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-f6a8cb4c]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-f6a8cb4c]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-f6a8cb4c]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-f6a8cb4c]{object-fit:cover;transform:scale(1)}[data-v-43c617a7] .guido__verion-history-view-option-selection-desktop svg,[data-v-43c617a7] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-43c617a7] .in-segments-wrapper__button_selected,[data-v-43c617a7] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-988f8da6]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-988f8da6]{min-height:504px}.iframe-wrapper[data-v-e0424e99]{width:258px}.iframe-scaled[data-v-e0424e99]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-7419ae06] .vueperslides__bullets,[data-v-796d193b] .vueperslides__bullets{pointer-events:none!important}[data-v-796d193b] .vueperslides__parallax-wrapper{height:110px!important}[data-v-cadfc82d] .vueperslides__bullets{pointer-events:none!important}[data-v-cadfc82d] .vueperslides__parallax-wrapper{height:110px!important}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useinsider/guido",
3
- "version": "3.7.2-beta.6f556cb",
3
+ "version": "3.7.2-beta.7b4f9d0",
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",