@useinsider/guido 3.21.2-beta.b6f3ef8 → 3.21.2-beta.d9d48aa

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 (36) hide show
  1. package/README.md +13 -34
  2. package/dist/@types/config/schemas.js +35 -33
  3. package/dist/components/Guido.vue.js +6 -6
  4. package/dist/components/Guido.vue2.js +115 -121
  5. package/dist/components/organisms/unsubscribe/LegacyUnsubscribeConvertedModal.vue.js +17 -0
  6. package/dist/components/organisms/unsubscribe/LegacyUnsubscribeConvertedModal.vue2.js +30 -0
  7. package/dist/composables/useModuleRepair.js +32 -23
  8. package/dist/composables/useStripo.js +82 -94
  9. package/dist/config/migrator/index.js +10 -9
  10. package/dist/config/migrator/legacyUnsubscribeTextMigrator.js +16 -0
  11. package/dist/enums/academy.js +2 -1
  12. package/dist/guido.css +1 -1
  13. package/dist/library.js +10 -12
  14. package/dist/package.json.js +4 -6
  15. package/dist/src/@types/config/schemas.d.ts +4 -0
  16. package/dist/src/components/organisms/unsubscribe/LegacyUnsubscribeConvertedModal.vue.d.ts +2 -0
  17. package/dist/src/composables/useConfig.d.ts +2 -0
  18. package/dist/src/composables/useModuleRepair.d.ts +2 -11
  19. package/dist/src/config/migrator/legacyUnsubscribeTextMigrator.d.ts +1 -0
  20. package/dist/src/enums/academy.d.ts +1 -0
  21. package/dist/src/library.d.ts +0 -1
  22. package/dist/src/stores/config.d.ts +20 -0
  23. package/dist/src/stores/editor.d.ts +25 -0
  24. package/dist/src/utils/legacyUnsubscribeConversion.d.ts +10 -0
  25. package/dist/stores/editor.js +15 -14
  26. package/dist/utils/legacyUnsubscribeConversion.js +49 -0
  27. package/package.json +1 -6
  28. package/dist/composables/useEditorOpenMetrics.js +0 -164
  29. package/dist/public/prefetchRuntime.js +0 -4
  30. package/dist/src/composables/useEditorOpenMetrics.d.ts +0 -27
  31. package/dist/src/public/prefetchRuntime.d.ts +0 -1
  32. package/dist/src/utils/runtimePrefetch.d.ts +0 -4
  33. package/dist/src/utils/stripoRuntime.d.ts +0 -2
  34. package/dist/static/stripo-runtime-manifest.json.js +0 -9
  35. package/dist/utils/runtimePrefetch.js +0 -26
  36. package/dist/utils/stripoRuntime.js +0 -9
@@ -0,0 +1,17 @@
1
+ import s from "./LegacyUnsubscribeConvertedModal.vue2.js";
2
+ import n from "../../../_virtual/_plugin-vue2_normalizer.js";
3
+ var r = function() {
4
+ var o = this, t = o._self._c, e = o._self._setupProxy;
5
+ return e.isVisible ? t(e.WpModal, { attrs: { id: "guido__legacy-unsubscribe-converted-modal", state: "warning", "close-on-outside-click": !1, "footer-button-options": e.footerButtonOptions, title: e.trans("email-editor.legacy-unsubscribe-converted-modal-title") }, on: { close: e.close, "primary-action": e.close, "secondary-action": e.openAcademy } }, [t("p", [o._v(o._s(e.trans("email-editor.legacy-unsubscribe-converted-modal-message")))])]) : o._e();
6
+ }, a = [], c = /* @__PURE__ */ n(
7
+ s,
8
+ r,
9
+ a,
10
+ !1,
11
+ null,
12
+ null
13
+ );
14
+ const d = c.exports;
15
+ export {
16
+ d as default
17
+ };
@@ -0,0 +1,30 @@
1
+ import { defineComponent as n, computed as t } from "vue";
2
+ import i from "../../wrappers/WpModal.vue.js";
3
+ import { useTranslations as a } from "../../../composables/useTranslations.js";
4
+ import { ACADEMY_LINKS as c } from "../../../enums/academy.js";
5
+ import { useEditorStore as p } from "../../../stores/editor.js";
6
+ const L = /* @__PURE__ */ n({
7
+ __name: "LegacyUnsubscribeConvertedModal",
8
+ setup(d) {
9
+ const o = a(), e = p(), r = t(
10
+ () => e.isLegacyUnsubscribeModalRequested && e.isStripoInitialized
11
+ ), s = t(() => ({
12
+ secondaryButton: {
13
+ type: "subtle-primary",
14
+ labelText: o("email-editor.legacy-unsubscribe-converted-modal-visit-academy")
15
+ },
16
+ primaryButton: {
17
+ type: "primary",
18
+ labelText: o("action-builder.ok")
19
+ }
20
+ }));
21
+ return { __sfc: !0, trans: o, editorStore: e, isVisible: r, footerButtonOptions: s, close: () => {
22
+ e.isLegacyUnsubscribeModalRequested = !1;
23
+ }, openAcademy: () => {
24
+ window.open(c.LEGACY_UNSUBSCRIBE_MODULE, "_blank", "noopener,noreferrer");
25
+ }, WpModal: i };
26
+ }
27
+ });
28
+ export {
29
+ L as default
30
+ };
@@ -1,33 +1,42 @@
1
- import { useConfig as C } from "./useConfig.js";
2
- import { useToaster as T } from "./useToaster.js";
3
- import { useTranslations as g } from "./useTranslations.js";
4
- import { ToasterTypeOptions as D } from "../enums/toaster.js";
5
- import { buildDynamicContentLookup as f, convertModuleDynamicContent as h } from "../utils/dynamicContentConverter.js";
6
- import { flattenDynamicContentList as O } from "../utils/genericUtil.js";
1
+ import { useConfig as f } from "./useConfig.js";
2
+ import { useToaster as d } from "./useToaster.js";
3
+ import { useTranslations as C } from "./useTranslations.js";
4
+ import { ToasterTypeOptions as h } from "../enums/toaster.js";
5
+ import { useEditorStore as T } from "../stores/editor.js";
6
+ import { buildDynamicContentLookup as v, convertModuleDynamicContent as D } from "../utils/dynamicContentConverter.js";
7
+ import { flattenDynamicContentList as L } from "../utils/genericUtil.js";
7
8
  import { repairItemsCurrencyAttributes as M } from "../utils/itemsCurrencyRepair.js";
8
- const N = "dynamic-content.unresolved-attributes-on-drop", R = () => {
9
- const { template: p, isFeatureEnabled: m } = C(), { showToaster: a } = T(), y = g();
10
- return { handleModuleAdd: (e, o) => {
11
- var s, l, u;
9
+ import { convertLegacyUnsubscribeInModuleHtml as O } from "../utils/legacyUnsubscribeConversion.js";
10
+ const E = "dynamic-content.unresolved-attributes-on-drop", Y = () => {
11
+ const { template: p, isFeatureEnabled: s } = f(), { showToaster: y } = d(), b = C();
12
+ return { handleModuleAdd: (t, r) => {
13
+ var c, l, u;
12
14
  try {
13
- if ((e == null ? void 0 : e.action) !== "ADD" && (e == null ? void 0 : e.action) !== "COPY")
15
+ if ((t == null ? void 0 : t.action) !== "ADD" && (t == null ? void 0 : t.action) !== "COPY")
14
16
  return;
15
- const t = (s = o == null ? void 0 : o.getTargetNode) == null ? void 0 : s.call(o), r = (l = t == null ? void 0 : t.getOuterHTML) == null ? void 0 : l.call(t);
16
- if (!t || typeof r != "string")
17
+ const e = (c = r == null ? void 0 : r.getTargetNode) == null ? void 0 : c.call(r), n = (l = e == null ? void 0 : e.getOuterHTML) == null ? void 0 : l.call(e);
18
+ if (!e || typeof n != "string")
17
19
  return;
18
- let n = M(r);
19
- const c = f(O((u = p.value) == null ? void 0 : u.dynamicContentList));
20
- let i = [];
21
- c.size > 0 && ({ html: n, unresolved: i } = h(n, c, m("liquidSyntax"))), n !== r && o.modifyHtml(t).replaceWith(n), i.length > 0 && a({
22
- type: D.Warning,
23
- message: y(N)
20
+ let o = M(n), i = !1;
21
+ s("legacyUnsubscribeConversion") && ({ html: o, converted: i } = O(o));
22
+ const a = v(L((u = p.value) == null ? void 0 : u.dynamicContentList));
23
+ let m = [];
24
+ if (a.size > 0 && ({ html: o, unresolved: m } = D(o, a, s("liquidSyntax"))), o !== n && r.modifyHtml(e).replaceWith(o), i)
25
+ try {
26
+ T().isLegacyUnsubscribeModalRequested = !0;
27
+ } catch (g) {
28
+ console.error("Failed to request the legacy unsubscribe modal:", g);
29
+ }
30
+ m.length > 0 && y({
31
+ type: h.Warning,
32
+ message: b(E)
24
33
  });
25
- } catch (t) {
26
- console.error("Failed to repair module on add:", t);
34
+ } catch (e) {
35
+ console.error("Failed to repair module on add:", e);
27
36
  }
28
37
  } };
29
38
  };
30
39
  export {
31
- N as UNRESOLVED_DYNAMIC_CONTENT_ON_DROP_KEY,
32
- R as useModuleRepair
40
+ E as UNRESOLVED_DYNAMIC_CONTENT_ON_DROP_KEY,
41
+ Y as useModuleRepair
33
42
  };
@@ -1,55 +1,44 @@
1
- import { useActionsApi as H } from "./useActionsApi.js";
2
- import { useBlocksConfig as N } from "./useBlocksConfig.js";
3
- import { useConfig as j } from "./useConfig.js";
4
- import { useCustomInterfaceAppearance as _ } from "./useCustomInterfaceAppearance.js";
5
- import { useEditorOpenMetrics as z } from "./useEditorOpenMetrics.js";
6
- import { useFullStoryBridge as $ } from "./useFullStoryBridge.js";
7
- import { useModuleRepair as G } from "./useModuleRepair.js";
8
- import { useStripoEventHandler as X } from "./useStripoEventHandler.js";
9
- import { useStripoNotifications as J } from "./useStripoNotifications.js";
10
- import { useToaster as K } from "./useToaster.js";
11
- import { localePatch as Q } from "../config/i18n/index.js";
12
- import { en as B } from "../config/i18n/en/index.js";
13
- import { ToasterTypeOptions as W } from "../enums/toaster.js";
14
- import { useStripoApi as Y } from "../services/stripoApi.js";
15
- import Z from "../static/styles/customEditorStyle.css.js";
16
- import { useEditorStore as M } from "../stores/editor.js";
17
- import { buildMergeTagEntries as ee, flattenDynamicContentList as te } from "../utils/genericUtil.js";
18
- import { getStripoRuntimeBaseUrl as oe } from "../utils/stripoRuntime.js";
19
- let d = null, v = !1;
20
- const be = () => {
21
- const { features: u, template: m, isFeatureEnabled: p } = j(), { handleError: f, showToaster: T } = K(), { getToken: F, getCustomFonts: A, getSyncModulesStatus: P } = Y(), { handleEvent: R } = X(), { handleModuleAdd: U } = G(), { getStripoBlocksConfig: V } = N(), { getStripoNotifications: D } = J(), e = z(), g = () => d || (d = new Promise((s, a) => {
1
+ import { useActionsApi as L } from "./useActionsApi.js";
2
+ import { useBlocksConfig as O } from "./useBlocksConfig.js";
3
+ import { useConfig as H } from "./useConfig.js";
4
+ import { useCustomInterfaceAppearance as w } from "./useCustomInterfaceAppearance.js";
5
+ import { useFullStoryBridge as N } from "./useFullStoryBridge.js";
6
+ import { useModuleRepair as j } from "./useModuleRepair.js";
7
+ import { useStripoEventHandler as z } from "./useStripoEventHandler.js";
8
+ import { useStripoNotifications as $ } from "./useStripoNotifications.js";
9
+ import { useToaster as G } from "./useToaster.js";
10
+ import { localePatch as J } from "../config/i18n/index.js";
11
+ import { en as b } from "../config/i18n/en/index.js";
12
+ import { ToasterTypeOptions as X } from "../enums/toaster.js";
13
+ import { useStripoApi as K } from "../services/stripoApi.js";
14
+ import Q from "../static/styles/customEditorStyle.css.js";
15
+ import { useEditorStore as k } from "../stores/editor.js";
16
+ import { buildMergeTagEntries as W, flattenDynamicContentList as Y } from "../utils/genericUtil.js";
17
+ import Z from "../package.json.js";
18
+ let n = null;
19
+ const he = () => {
20
+ const { features: c, template: u, isFeatureEnabled: p } = H(), { handleError: m, showToaster: v } = G(), { getToken: B, getCustomFonts: M, getSyncModulesStatus: T } = K(), { handleEvent: F } = z(), { handleModuleAdd: A } = j(), { getStripoBlocksConfig: V } = O(), { getStripoNotifications: _ } = $(), f = () => n || (n = new Promise((r, s) => {
21
+ var d;
22
22
  if (document.getElementById("UiEditorScript")) {
23
- s();
23
+ r();
24
24
  return;
25
25
  }
26
- const i = oe();
27
- if (!i) {
28
- a(
29
- new Error("guido.stripo.version is not set in package.json. Please configure the Stripo version.")
30
- );
31
- return;
32
- }
33
- const n = `${i}UIEditor.js`, t = document.createElement("script");
34
- t.id = "UiEditorScript", t.type = "module", t.src = n, t.onload = () => {
35
- v = !0, s();
36
- }, t.onerror = () => {
37
- t.remove(), a(new Error(`Failed to load Stripo UIEditor script from S3: ${n}`));
38
- }, document.body.appendChild(t);
39
- }), d.catch(() => {
40
- d = null;
41
- }), d), I = async (s, a, i, n = [], t = !1) => {
42
- var C, w, k, b;
43
- const o = M(), { html: c, css: S } = s, { baseBlocks: y, extensions: L } = await V();
44
- e.mark("blocks_config_ready");
45
- const E = ((C = u.value) == null ? void 0 : C.displayConditions) ?? !0, O = ((w = u.value) == null ? void 0 : w.modulesDisabled) ?? !1, h = !!c || (((k = m.value) == null ? void 0 : k.forceRecreate) ?? !1), q = "https://email-static.useinsider.com https://edge.fullstory.com https://rs.fullstory.com";
46
- e.setTemplate({ html: c, css: S, forceRecreate: h }), _().importCss(), e.mark("init_editor"), await window.UIEditor.initEditor(
26
+ const o = Z.guido, i = `https://email-static.useinsider.com/guido/${(d = o == null ? void 0 : o.stripo) == null ? void 0 : d.version}/UIEditor.js`, e = document.createElement("script");
27
+ e.id = "UiEditorScript", e.type = "module", e.src = i, e.onload = () => r(), e.onerror = () => {
28
+ e.remove(), s(new Error(`Failed to load Stripo UIEditor script from S3: ${i}`));
29
+ }, document.body.appendChild(e);
30
+ }), n.catch(() => {
31
+ n = null;
32
+ }), n), D = async (r, s, o, a = [], i = !1) => {
33
+ var y, E, h, C;
34
+ const e = k(), { html: d, css: P } = r, { baseBlocks: g, extensions: R } = await V(), S = ((y = c.value) == null ? void 0 : y.displayConditions) ?? !0, U = ((E = c.value) == null ? void 0 : E.modulesDisabled) ?? !1, I = !!d || (((h = u.value) == null ? void 0 : h.forceRecreate) ?? !1), q = "https://email-static.useinsider.com https://edge.fullstory.com https://rs.fullstory.com";
35
+ w().importCss(), await window.UIEditor.initEditor(
47
36
  document.querySelector("#guido-editor"),
48
37
  {
49
- metadata: a,
50
- html: c,
51
- css: S,
52
- forceRecreate: h,
38
+ metadata: s,
39
+ html: d,
40
+ css: P,
41
+ forceRecreate: I,
53
42
  locale: "en",
54
43
  undoButtonSelector: "#guido__undo-button",
55
44
  redoButtonSelector: "#guido__redo-button",
@@ -59,12 +48,12 @@ const be = () => {
59
48
  customAppearanceMergetags: !p("liquidSyntax"),
60
49
  customAppearanceMergetagsBorderColor: "#f1f3fe",
61
50
  customAppearanceMergetagsBackgroundColor: "#f1f3fe",
62
- customViewStyles: Z,
63
- conditionsEnabled: E,
64
- customConditionsEnabled: E,
51
+ customViewStyles: Q,
52
+ conditionsEnabled: S,
53
+ customConditionsEnabled: S,
65
54
  enableXSSSecurity: !0,
66
- modulesDisabled: O,
67
- syncModulesEnabled: t,
55
+ modulesDisabled: U,
56
+ syncModulesEnabled: i,
68
57
  messageSettingsEnabled: !0,
69
58
  displayGmailAnnotations: !0,
70
59
  displayHiddenPreheader: !1,
@@ -75,55 +64,54 @@ const be = () => {
75
64
  selectElementAfterDrop: !0,
76
65
  sameFontSizeForOutlook: !0,
77
66
  allowedScriptSourceDomains: q,
78
- ...y ? { baseBlocks: y } : {},
67
+ ...g ? { baseBlocks: g } : {},
79
68
  editorFonts: {
80
69
  showDefaultStandardFonts: !0,
81
70
  showDefaultNotStandardFonts: !0,
82
- customFonts: n
71
+ customFonts: a
83
72
  },
84
73
  mergeTags: [
85
74
  {
86
- entries: ee(
87
- i.preselectedDynamicContentList,
88
- te((b = m.value) == null ? void 0 : b.dynamicContentList),
75
+ entries: W(
76
+ o.preselectedDynamicContentList,
77
+ Y((C = u.value) == null ? void 0 : C.dynamicContentList),
89
78
  p("liquidSyntax")
90
79
  )
91
80
  }
92
81
  ],
93
- async onTokenRefreshRequest(r) {
82
+ async onTokenRefreshRequest(t) {
94
83
  try {
95
- e.mark("token_start");
96
- const l = await F();
97
- e.mark("token_end"), r(l);
84
+ const l = await B();
85
+ t(l);
98
86
  } catch (l) {
99
- f(l, "Failed to refresh token");
87
+ m(l, "Failed to refresh token");
100
88
  }
101
89
  },
102
90
  onTemplateLoaded() {
103
91
  try {
104
- const { activateCustomViewStyles: r, updateTimerInClonedTemplate: l } = H(), { injectFullStory: x } = $();
105
- _().importCss(), r(), x(), l(), i.onReady(), o.isStripoInitialized = !0, o.loadingStatus = !1, setTimeout(() => {
106
- o.hasChanges = !1;
107
- }, 1e3), e.markReady();
108
- } catch (r) {
109
- f(r, "Failed to load custom interface appearance");
92
+ const { activateCustomViewStyles: t, updateTimerInClonedTemplate: l } = L(), { injectFullStory: x } = N();
93
+ w().importCss(), t(), x(), l(), o.onReady(), e.isStripoInitialized = !0, e.loadingStatus = !1, setTimeout(() => {
94
+ e.hasChanges = !1;
95
+ }, 1e3);
96
+ } catch (t) {
97
+ m(t, "Failed to load custom interface appearance");
110
98
  }
111
99
  },
112
- onCodeEditorVisibilityChanged(r) {
113
- o.isCodeEditorOpen = r;
100
+ onCodeEditorVisibilityChanged(t) {
101
+ e.isCodeEditorOpen = t;
114
102
  },
115
- onEditorVisualModeChanged(r) {
116
- o.editorVisualMode = r.toLowerCase();
103
+ onEditorVisualModeChanged(t) {
104
+ e.editorVisualMode = t.toLowerCase();
117
105
  },
118
- onVersionHistoryVisibilityChanged(r) {
119
- o.isVersionHistoryOpen = r;
106
+ onVersionHistoryVisibilityChanged(t) {
107
+ e.isVersionHistoryOpen = t;
120
108
  },
121
109
  onDataChanged() {
122
- o.hasChanges = !0, o.changeSeq += 1;
110
+ e.hasChanges = !0, e.changeSeq += 1;
123
111
  },
124
- onEvent: R,
125
- onModuleAdd: U,
126
- notifications: D(),
112
+ onEvent: F,
113
+ onModuleAdd: A,
114
+ notifications: _(),
127
115
  // Stripo deselects the block on any click outside the canvas, so every surface
128
116
  // that belongs to the block's own flow has to be listed here (SD-153273).
129
117
  ignoreClickOutsideSelectors: [
@@ -133,35 +121,35 @@ const be = () => {
133
121
  ".in-modal-v2-wrapper",
134
122
  ".in-toasts-wrapper"
135
123
  ],
136
- extensions: L,
137
- localePatch: Q
124
+ extensions: R,
125
+ localePatch: J
138
126
  }
139
127
  );
140
128
  };
141
- return { initPlugin: async (s, a, i) => {
142
- const n = M();
129
+ return { initPlugin: async (r, s, o) => {
130
+ const a = k();
143
131
  try {
144
- e.mark("plugin_start"), e.setScriptPreloaded(v), await g(), e.mark("script_ready");
145
- const [t, o] = await Promise.all([
146
- A(),
147
- P()
132
+ await f();
133
+ const [i, e] = await Promise.all([
134
+ M(),
135
+ T()
148
136
  ]);
149
- e.mark("fonts_sync_ready"), n.syncModulesEnabled = o, await I(s, a, i, t, o);
137
+ a.syncModulesEnabled = e, await D(r, s, o, i, e);
150
138
  } catch {
151
- n.loadingStatus = !1, T({
152
- type: W.Error,
153
- message: B["An error has occurred. Please report the error code to support."],
139
+ a.loadingStatus = !1, v({
140
+ type: X.Error,
141
+ message: b["An error has occurred. Please report the error code to support."],
154
142
  actionButton: {
155
- text: B["Reload page"],
143
+ text: b["Reload page"],
156
144
  onClick: () => window.location.reload()
157
145
  }
158
- }), e.markFailed();
146
+ });
159
147
  }
160
148
  }, preloadRuntime: () => {
161
- g().catch(() => {
149
+ f().catch(() => {
162
150
  });
163
151
  } };
164
152
  };
165
153
  export {
166
- be as useStripo
154
+ he as useStripo
167
155
  };
@@ -1,17 +1,18 @@
1
1
  import { migrateCheckbox as i } from "./checkboxMigrator.js";
2
2
  import { migrateCouponBlock as e } from "./couponBlockMigrator.js";
3
3
  import { migrateItemsBlock as a } from "./itemsBlockMigrator.js";
4
- import { migrateProductNameLink as n } from "./productNameLinkMigrator.js";
5
- import { migrateRadioButton as c } from "./radioButtonMigrator.js";
6
- import { migrateRecommendation as g } from "./recommendationMigrator.js";
7
- import { migrateRecommendationPartnerScope as f } from "./recommendationPartnerMigrator.js";
8
- import { migrateRecommendationTitle as p } from "./recommendationTitleMigrator.js";
4
+ import { migrateLegacyUnsubscribeText as n } from "./legacyUnsubscribeTextMigrator.js";
5
+ import { migrateProductNameLink as c } from "./productNameLinkMigrator.js";
6
+ import { migrateRadioButton as g } from "./radioButtonMigrator.js";
7
+ import { migrateRecommendation as f } from "./recommendationMigrator.js";
8
+ import { migrateRecommendationPartnerScope as p } from "./recommendationPartnerMigrator.js";
9
+ import { migrateRecommendationTitle as s } from "./recommendationTitleMigrator.js";
9
10
  import { migrateSocialIcons as d } from "./socialIconMigrator.js";
10
11
  import { migrateUnsubscribe as l } from "./unsubscribeMigrator.js";
11
- const h = async (r, t = {}, o) => {
12
- let m = r;
13
- return m = i(m), m = c(m), m = await l(m), m = e(m), m = g(m, t), o && (m = f(m, o)), m = p(m), m = a(m), m = n(m), m = d(m), m;
12
+ const T = async (o, t = {}, r) => {
13
+ let m = o;
14
+ return m = i(m), m = g(m), m = n(m), m = await l(m), m = e(m), m = f(m, t), r && (m = p(m, r)), m = s(m), m = a(m), m = c(m), m = d(m), m;
14
15
  };
15
16
  export {
16
- h as migrate
17
+ T as migrate
17
18
  };
@@ -0,0 +1,16 @@
1
+ import { useConfigStore as o } from "../../stores/config.js";
2
+ import { useEditorStore as s } from "../../stores/editor.js";
3
+ import { hasLegacyUnsubscribeClass as c, convertLegacyUnsubscribeInDocumentHtml as i } from "../../utils/legacyUnsubscribeConversion.js";
4
+ const b = (e) => {
5
+ try {
6
+ if (!c(e) || !o().isFeatureEnabled("legacyUnsubscribeConversion"))
7
+ return e;
8
+ const { html: r, converted: t } = i(e);
9
+ return t && (s().isLegacyUnsubscribeModalRequested = !0), r;
10
+ } catch (r) {
11
+ return console.error("LegacyUnsubscribeTextMigrator failed:", r), e;
12
+ }
13
+ };
14
+ export {
15
+ b as migrateLegacyUnsubscribeText
16
+ };
@@ -2,7 +2,8 @@ const e = "https://academy.insiderone.com", o = {
2
2
  EMAIL_EDITOR: `${e}/docs/email-drag-and-drop-editor`,
3
3
  GLOBAL_UNSUBSCRIBE: `${e}/docs/global-unsubscribe-preference-center`,
4
4
  AMP_FOR_EMAILS: `${e}/docs/amp-for-emails`,
5
- EMAIL_RECOMMENDATION_BLOCK: `${e}/docs/new-editor-email-recommendation-block`
5
+ EMAIL_RECOMMENDATION_BLOCK: `${e}/docs/new-editor-email-recommendation-block`,
6
+ LEGACY_UNSUBSCRIBE_MODULE: `${e}/docs/new-editor-add-unsubscribe-pages-into-emails`
6
7
  };
7
8
  export {
8
9
  o as ACADEMY_LINKS
package/dist/guido.css CHANGED
@@ -1 +1 @@
1
- @charset "UTF-8";.auth-error-modal[data-v-b4d7ae51]{position:relative;z-index:145}.gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-b8f24f34] .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-87033101]{position:relative;display:inline-block}.new-tag[data-v-87033101]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-87033101] .guido__view-option-selection-desktop svg,[data-v-87033101] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-87033101] .in-segments-wrapper__button_selected,[data-v-87033101] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-87033101] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-6ebabfe4]{position:relative;display:inline-block}.new-tag[data-v-6ebabfe4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-6ebabfe4] .guido__verion-history-view-option-selection-desktop svg,[data-v-6ebabfe4] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-6ebabfe4] .in-segments-wrapper__button_selected,[data-v-6ebabfe4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-6ebabfe4] .in-tooltip-wrapper-v2__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-baf7a5dd]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.validation-error-list[data-v-e48cebe9]{gap:16px}.validation-error-row[data-v-e48cebe9]{gap:8px;padding:24px;border:1px solid #E1E1E1;border-radius:8px}.validation-error-row__icon[data-v-e48cebe9]{flex-shrink:0;font-size:24px;line-height:0}.validation-error-row__text[data-v-e48cebe9]{font-size:13px;line-height:16px;color:#292929;word-break:break-word}.guido-editor__wrapper[data-v-1a3ddd48]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-1a3ddd48]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-1a3ddd48]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-91a26acd]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-91a26acd]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-91a26acd]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-91a26acd]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-91a26acd]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .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-cf946232]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-cf946232]{min-height:504px}.iframe-wrapper[data-v-f255b2bb]{width:258px}.iframe-scaled[data-v-f255b2bb]{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-6bcaca8a] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-f16f20f8] .vueperslides__bullets{pointer-events:none!important}[data-v-f16f20f8] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-bb3cca55] .vueperslides__bullets{pointer-events:none!important}[data-v-bb3cca55] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-19d8cb42] .vueperslides__bullets,[data-v-ec2027ff] .vueperslides__bullets,[data-v-b09e80c4] .vueperslides__bullets{pointer-events:none!important}[data-v-b09e80c4] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-9bdef600] .vueperslides__parallax-wrapper{padding-bottom:110px!important}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd]{width:100%;max-width:none}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd] .in-skeleton{width:100%!important}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd] .in-dropdown-box__container{width:413px}.assign-strategy-drawer .spaced-dot-sep{background-image:linear-gradient(90deg,#91949f 20%,#fff0 0);background-position:center bottom;background-repeat:repeat-x;background-size:5px 1px}.assign-strategy-drawer .spaced-dot-sep--top{background-position:center top}.assign-strategy-drawer .spaced-dot-sep--fc-n:first-child{background:none}.legacy-strategy-updated-modal[data-v-da2225a1]{position:relative;z-index:145}
1
+ @charset "UTF-8";.auth-error-modal[data-v-b4d7ae51]{position:relative;z-index:145}.gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-b8f24f34] .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-87033101]{position:relative;display:inline-block}.new-tag[data-v-87033101]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-87033101] .guido__view-option-selection-desktop svg,[data-v-87033101] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-87033101] .in-segments-wrapper__button_selected,[data-v-87033101] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-87033101] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-6ebabfe4]{position:relative;display:inline-block}.new-tag[data-v-6ebabfe4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-6ebabfe4] .guido__verion-history-view-option-selection-desktop svg,[data-v-6ebabfe4] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-6ebabfe4] .in-segments-wrapper__button_selected,[data-v-6ebabfe4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-6ebabfe4] .in-tooltip-wrapper-v2__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-baf7a5dd]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.validation-error-list[data-v-e48cebe9]{gap:16px}.validation-error-row[data-v-e48cebe9]{gap:8px;padding:24px;border:1px solid #E1E1E1;border-radius:8px}.validation-error-row__icon[data-v-e48cebe9]{flex-shrink:0;font-size:24px;line-height:0}.validation-error-row__text[data-v-e48cebe9]{font-size:13px;line-height:16px;color:#292929;word-break:break-word}.guido-editor__wrapper[data-v-6cdd5182]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-6cdd5182]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-6cdd5182]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-91a26acd]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-91a26acd]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-91a26acd]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-91a26acd]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-91a26acd]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .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-cf946232]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-cf946232]{min-height:504px}.iframe-wrapper[data-v-f255b2bb]{width:258px}.iframe-scaled[data-v-f255b2bb]{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-6bcaca8a] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-f16f20f8] .vueperslides__bullets{pointer-events:none!important}[data-v-f16f20f8] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-bb3cca55] .vueperslides__bullets{pointer-events:none!important}[data-v-bb3cca55] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-19d8cb42] .vueperslides__bullets,[data-v-ec2027ff] .vueperslides__bullets,[data-v-b09e80c4] .vueperslides__bullets{pointer-events:none!important}[data-v-b09e80c4] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-9bdef600] .vueperslides__parallax-wrapper{padding-bottom:110px!important}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd]{width:100%;max-width:none}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd] .in-skeleton{width:100%!important}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd] .in-dropdown-box__container{width:413px}.assign-strategy-drawer .spaced-dot-sep{background-image:linear-gradient(90deg,#91949f 20%,#fff0 0);background-position:center bottom;background-repeat:repeat-x;background-size:5px 1px}.assign-strategy-drawer .spaced-dot-sep--top{background-position:center top}.assign-strategy-drawer .spaced-dot-sep--fc-n:first-child{background:none}.legacy-strategy-updated-modal[data-v-da2225a1]{position:relative;z-index:145}
package/dist/library.js CHANGED
@@ -1,22 +1,20 @@
1
1
  import { default as a } from "./components/Guido.vue.js";
2
- import { MessageType as t, ProductType as f } from "./@types/config/schemas.js";
2
+ import { MessageType as t, ProductType as d } from "./@types/config/schemas.js";
3
3
  import "./@types/config/defaults.js";
4
- import { getValidationErrors as p, isValidConfig as s, parseConfig as m, parseConfigSafe as g, validateConfig as n } from "./@types/config/validator.js";
5
- import { assignTrackingIds as l, readTrackFloor as x, readTrackSeq as c } from "./utils/linkTrackingIds.js";
4
+ import { getValidationErrors as s, isValidConfig as p, parseConfig as g, parseConfigSafe as m, validateConfig as n } from "./@types/config/validator.js";
5
+ import { assignTrackingIds as u, readTrackFloor as x, readTrackSeq as T } from "./utils/linkTrackingIds.js";
6
6
  import { useGuidoEmailEditorStore as C } from "./stores/guido-email-editor.js";
7
- import { prefetchGuidoRuntime as E } from "./utils/runtimePrefetch.js";
8
7
  export {
9
8
  a as Guido,
10
9
  t as MessageType,
11
- f as ProductType,
12
- l as assignTrackingIds,
13
- p as getValidationErrors,
14
- s as isValidConfig,
15
- m as parseConfig,
16
- g as parseConfigSafe,
17
- E as prefetchGuidoRuntime,
10
+ d as ProductType,
11
+ u as assignTrackingIds,
12
+ s as getValidationErrors,
13
+ p as isValidConfig,
14
+ g as parseConfig,
15
+ m as parseConfigSafe,
18
16
  x as readTrackFloor,
19
- c as readTrackSeq,
17
+ T as readTrackSeq,
20
18
  C as useGuidoEmailEditorStore,
21
19
  n as validateConfig
22
20
  };
@@ -1,9 +1,7 @@
1
- const o = "3.21.2-beta.b6f3ef8", s = { stripo: { version: "2.81.1" } }, e = {
2
- version: o,
3
- guido: s
1
+ const o = { stripo: { version: "2.81.1" } }, s = {
2
+ guido: o
4
3
  };
5
4
  export {
6
- e as default,
7
- s as guido,
8
- o as version
5
+ s as default,
6
+ o as guido
9
7
  };
@@ -414,6 +414,8 @@ export declare const FeaturesSchema: v.ObjectSchema<{
414
414
  /** Allow persisting a template that still has validation errors (drawer "Save and Continue" soft-save). Host sets false for transactional + unsubscribe. */
415
415
  readonly allowSaveWithErrors: v.OptionalSchema<v.BooleanSchema<undefined>, true>;
416
416
  readonly reusableRecommendationStrategy: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
417
+ /** Convert linkless legacy unsubscribe blocks into text blocks and warn with a modal (opt-in) */
418
+ readonly legacyUnsubscribeConversion: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
417
419
  }, undefined>;
418
420
  /**
419
421
  * Default block types available in Stripo
@@ -832,6 +834,8 @@ export declare const GuidoConfigSchema: v.ObjectSchema<{
832
834
  /** Allow persisting a template that still has validation errors (drawer "Save and Continue" soft-save). Host sets false for transactional + unsubscribe. */
833
835
  readonly allowSaveWithErrors: v.OptionalSchema<v.BooleanSchema<undefined>, true>;
834
836
  readonly reusableRecommendationStrategy: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
837
+ /** Convert linkless legacy unsubscribe blocks into text blocks and warn with a modal (opt-in) */
838
+ readonly legacyUnsubscribeConversion: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
835
839
  }, undefined>, {}>;
836
840
  /** Block configuration */
837
841
  readonly blocks: v.OptionalSchema<v.ObjectSchema<{
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
2
+ export default _default;
@@ -104,6 +104,7 @@ export declare const useConfig: () => {
104
104
  linkTrackingIds: boolean;
105
105
  allowSaveWithErrors: boolean;
106
106
  reusableRecommendationStrategy: boolean;
107
+ legacyUnsubscribeConversion: boolean;
107
108
  };
108
109
  blocks: {
109
110
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -243,6 +244,7 @@ export declare const useConfig: () => {
243
244
  linkTrackingIds: boolean;
244
245
  allowSaveWithErrors: boolean;
245
246
  reusableRecommendationStrategy: boolean;
247
+ legacyUnsubscribeConversion: boolean;
246
248
  } | null>;
247
249
  blocks: import("vue").ComputedRef<{
248
250
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1,17 +1,8 @@
1
1
  import type { ModuleAddData, ModuleModifier } from '@@/Types/stripo';
2
2
  export declare const UNRESOLVED_DYNAMIC_CONTENT_ON_DROP_KEY = "dynamic-content.unresolved-attributes-on-drop";
3
3
  /**
4
- * Repairs saved modules as they are dropped or copied into the editor, in one pass
5
- * over the module HTML. Two independent repairs run through a single write-back:
6
- *
7
- * - Dynamic content: saved modules serialize merge-tag chips by their display label
8
- * (`{{ Phone Number }}`); this maps them back to their canonical token
9
- * (`{{phone_number}}`) using the account's dynamic-content list.
10
- * - Items currency: v2 Items blocks can carry price `data-curency` /
11
- * `data-currency_symbol` attrs that drifted from their `esd-ext-config`; these are
12
- * healed from config (the export contract reads those exact attrs).
13
- *
14
- * Wired into Stripo via the `onModuleAdd` init callback (see `useStripo`).
4
+ * Repairs dropped/copied saved modules (items currency, linkless legacy unsubscribe → text block,
5
+ * dynamic-content labels → tokens) in one write-back; wired via Stripo's `onModuleAdd` (see `useStripo`).
15
6
  */
16
7
  export declare const useModuleRepair: () => {
17
8
  handleModuleAdd: (data: ModuleAddData, modifier: ModuleModifier) => void;
@@ -0,0 +1 @@
1
+ export declare const migrateLegacyUnsubscribeText: (html: string) => string;
@@ -9,5 +9,6 @@ export declare const ACADEMY_LINKS: {
9
9
  readonly GLOBAL_UNSUBSCRIBE: "https://academy.insiderone.com/docs/global-unsubscribe-preference-center";
10
10
  readonly AMP_FOR_EMAILS: "https://academy.insiderone.com/docs/amp-for-emails";
11
11
  readonly EMAIL_RECOMMENDATION_BLOCK: "https://academy.insiderone.com/docs/new-editor-email-recommendation-block";
12
+ readonly LEGACY_UNSUBSCRIBE_MODULE: "https://academy.insiderone.com/docs/new-editor-add-unsubscribe-pages-into-emails";
12
13
  };
13
14
  export type AcademyLinkKey = keyof typeof ACADEMY_LINKS;
@@ -4,6 +4,5 @@ export { validateConfig, parseConfig, parseConfigSafe, isValidConfig, getValidat
4
4
  export { assignTrackingIds, readTrackFloor, readTrackSeq } from './public/trackingIds';
5
5
  export { useGuidoEmailEditorStore } from './public/editorState';
6
6
  export type { GuidoEmailEditorState } from './public/editorState';
7
- export { prefetchGuidoRuntime } from './public/prefetchRuntime';
8
7
  export type { StripoEventType } from './@types/events';
9
8
  export type { PositionData, DynamicContentEvent, MergeTagClickEvent, MergeTag, BaseDynamicContent, DynamicContentNode, DynamicContentList, TooltipOptions, TextValueObject, L10n, } from './@types/generic';