@useinsider/guido 3.9.1 → 3.10.0-beta.076d56a

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 (45) hide show
  1. package/dist/composables/useCortexBlueprintBridge.js +36 -32
  2. package/dist/composables/useCustomInterfaceAppearance.js +16 -18
  3. package/dist/composables/useEmailTemplateApplier.js +17 -15
  4. package/dist/composables/useExport.js +18 -18
  5. package/dist/composables/useHtmlValidator.js +90 -90
  6. package/dist/composables/useStripo.js +53 -51
  7. package/dist/composables/useStripoNotifications.js +26 -0
  8. package/dist/composables/useToaster.js +11 -11
  9. package/dist/composables/useVersionHistoryApi.js +2 -2
  10. package/dist/composables/validators/useLiquidValidator.js +1 -1
  11. package/dist/composables/validators/useUnsubscribeBlockValidator.js +10 -10
  12. package/dist/config/compiler/htmlCompilerRules.js +30 -7
  13. package/dist/config/compiler/utils/recommendationCompilerUtils.js +137 -119
  14. package/dist/config/i18n/en/labels.json.js +4 -1
  15. package/dist/enums/defaults.js +7 -4
  16. package/dist/enums/toaster.js +2 -2
  17. package/dist/enums/unsubscribe.js +41 -36
  18. package/dist/extensions/Blocks/Checkbox/block.js +5 -3
  19. package/dist/extensions/Blocks/Checkbox/control.js +42 -28
  20. package/dist/extensions/Blocks/Items/controls/price/currencySymbol.js +1 -1
  21. package/dist/extensions/Blocks/RadioButton/block.js +9 -7
  22. package/dist/extensions/Blocks/RadioButton/control.js +64 -50
  23. package/dist/extensions/Blocks/Recommendation/useRecommendationBlockWarning.js +7 -7
  24. package/dist/extensions/Blocks/Recommendation/utils/captureStyleTemplates.js +75 -69
  25. package/dist/extensions/Blocks/Recommendation/validation/requiredFields.js +18 -17
  26. package/dist/services/blankTemplate.js +34 -0
  27. package/dist/services/stripoApi.js +13 -18
  28. package/dist/services/templateLibraryApi.js +8 -7
  29. package/dist/src/composables/useCortexBlueprintBridge.d.ts +5 -2
  30. package/dist/src/composables/useEmailTemplateApplier.d.ts +8 -3
  31. package/dist/src/composables/useStripoNotifications.d.ts +10 -0
  32. package/dist/src/enums/defaults.d.ts +3 -0
  33. package/dist/src/enums/toaster.d.ts +2 -2
  34. package/dist/src/enums/unsubscribe.d.ts +2 -0
  35. package/dist/src/extensions/Blocks/Recommendation/utils/captureStyleTemplates.d.ts +6 -0
  36. package/dist/src/extensions/Blocks/Recommendation/validation/requiredFields.d.ts +1 -0
  37. package/dist/src/services/blankTemplate.d.ts +11 -0
  38. package/dist/src/stores/toaster.d.ts +2 -3
  39. package/dist/static/styles/components/dropdown-menu.css.js +12 -0
  40. package/dist/stores/toaster.js +10 -10
  41. package/dist/utils/pairProductVariables.js +64 -65
  42. package/package.json +2 -2
  43. package/dist/static/styles/components/notification.css.js +0 -74
  44. package/dist/static/templates/empty/index.html.js +0 -74
  45. package/dist/static/templates/empty/style.css.js +0 -779
@@ -1,29 +1,30 @@
1
- import { useActionsApi as I } from "./useActionsApi.js";
2
- import { useBlocksConfig as U } from "./useBlocksConfig.js";
3
- import { useConfig as R } from "./useConfig.js";
4
- import { useCustomInterfaceAppearance as x } from "./useCustomInterfaceAppearance.js";
5
- import { useFullStoryBridge as O } from "./useFullStoryBridge.js";
6
- import { useStripoEventHandler as q } from "./useStripoEventHandler.js";
7
- import { useToaster as H } from "./useToaster.js";
8
- import { localePatch as z } from "../config/i18n/index.js";
1
+ import { useActionsApi as U } from "./useActionsApi.js";
2
+ import { useBlocksConfig as R } from "./useBlocksConfig.js";
3
+ import { useConfig as x } from "./useConfig.js";
4
+ import { useCustomInterfaceAppearance as O } from "./useCustomInterfaceAppearance.js";
5
+ import { useFullStoryBridge as q } from "./useFullStoryBridge.js";
6
+ import { useStripoEventHandler as H } from "./useStripoEventHandler.js";
7
+ import { useStripoNotifications as N } from "./useStripoNotifications.js";
8
+ import { useToaster as z } from "./useToaster.js";
9
+ import { localePatch as L } from "../config/i18n/index.js";
9
10
  import { en as h } from "../config/i18n/en/index.js";
10
- import { ToasterTypeOptions as L } from "../enums/toaster.js";
11
- import { useStripoApi as $ } from "../services/stripoApi.js";
12
- import G from "../static/styles/customEditorStyle.css.js";
13
- import { useEditorStore as C } from "../stores/editor.js";
14
- import { dynamicContentToMergeTags as J } from "../utils/genericUtil.js";
15
- import N from "../package.json.js";
16
- const ce = (E, l) => {
17
- const { features: c, template: w, isFeatureEnabled: u } = R(), { handleError: m, showToaster: b } = H(), { getToken: T, getCustomFonts: k, getSyncModulesStatus: B } = $(), { handleEvent: F } = q(), { getStripoBlocksConfig: v } = U(), V = async (s, r = [], i = !1) => {
11
+ import { ToasterTypeOptions as $ } from "../enums/toaster.js";
12
+ import { useStripoApi as G } from "../services/stripoApi.js";
13
+ import J from "../static/styles/customEditorStyle.css.js";
14
+ import { useEditorStore as E } from "../stores/editor.js";
15
+ import { dynamicContentToMergeTags as X } from "../utils/genericUtil.js";
16
+ import j from "../package.json.js";
17
+ const fo = (C, l) => {
18
+ const { features: c, template: w, isFeatureEnabled: u } = x(), { handleError: m, showToaster: b } = z(), { getToken: T, getCustomFonts: k, getSyncModulesStatus: B } = G(), { handleEvent: F } = H(), { getStripoBlocksConfig: v } = R(), { getStripoNotifications: V } = N(), _ = async (s, i = [], r = !1) => {
18
19
  var g, S, y;
19
- const e = C(), { html: p, css: a } = s, { baseBlocks: t, extensions: d } = await v(), f = ((g = c.value) == null ? void 0 : g.displayConditions) ?? !0, A = ((S = c.value) == null ? void 0 : S.modulesDisabled) ?? !1, M = ((y = w.value) == null ? void 0 : y.forceRecreate) ?? !1;
20
+ const o = E(), { html: p, css: a } = s, { baseBlocks: t, extensions: d } = await v(), f = ((g = c.value) == null ? void 0 : g.displayConditions) ?? !0, M = ((S = c.value) == null ? void 0 : S.modulesDisabled) ?? !1, P = ((y = w.value) == null ? void 0 : y.forceRecreate) ?? !1;
20
21
  await window.UIEditor.initEditor(
21
22
  document.querySelector("#guido-editor"),
22
23
  {
23
- metadata: E,
24
+ metadata: C,
24
25
  html: p,
25
26
  css: a,
26
- forceRecreate: M,
27
+ forceRecreate: P,
27
28
  locale: "en",
28
29
  undoButtonSelector: "#guido__undo-button",
29
30
  redoButtonSelector: "#guido__redo-button",
@@ -33,12 +34,12 @@ const ce = (E, l) => {
33
34
  customAppearanceMergetags: !u("liquidSyntax"),
34
35
  customAppearanceMergetagsBorderColor: "#f1f3fe",
35
36
  customAppearanceMergetagsBackgroundColor: "#f1f3fe",
36
- customViewStyles: G,
37
+ customViewStyles: J,
37
38
  conditionsEnabled: f,
38
39
  customConditionsEnabled: f,
39
40
  enableXSSSecurity: !0,
40
- modulesDisabled: A,
41
- syncModulesEnabled: i,
41
+ modulesDisabled: M,
42
+ syncModulesEnabled: r,
42
43
  messageSettingsEnabled: !0,
43
44
  displayGmailAnnotations: !0,
44
45
  displayHiddenPreheader: !1,
@@ -51,82 +52,83 @@ const ce = (E, l) => {
51
52
  editorFonts: {
52
53
  showDefaultStandardFonts: !0,
53
54
  showDefaultNotStandardFonts: !0,
54
- customFonts: r
55
+ customFonts: i
55
56
  },
56
57
  mergeTags: [
57
58
  {
58
- entries: J(
59
+ entries: X(
59
60
  l.preselectedDynamicContentList,
60
61
  u("liquidSyntax")
61
62
  )
62
63
  }
63
64
  ],
64
- async onTokenRefreshRequest(o) {
65
+ async onTokenRefreshRequest(e) {
65
66
  try {
66
67
  const n = await T();
67
- o(n);
68
+ e(n);
68
69
  } catch (n) {
69
70
  m(n, "Failed to refresh token");
70
71
  }
71
72
  },
72
73
  onTemplateLoaded() {
73
74
  try {
74
- const { importCss: o } = x(), { activateCustomViewStyles: n, updateTimerInClonedTemplate: P } = I(), { injectFullStory: D } = O();
75
- o(), n(), D(), P(), l.onReady(), e.isStripoInitialized = !0, e.loadingStatus = !1, setTimeout(() => {
76
- e.hasChanges = !1;
75
+ const { importCss: e } = O(), { activateCustomViewStyles: n, updateTimerInClonedTemplate: D } = U(), { injectFullStory: I } = q();
76
+ e(), n(), I(), D(), l.onReady(), o.isStripoInitialized = !0, o.loadingStatus = !1, setTimeout(() => {
77
+ o.hasChanges = !1;
77
78
  }, 1e3);
78
- } catch (o) {
79
- m(o, "Failed to load custom interface appearance");
79
+ } catch (e) {
80
+ m(e, "Failed to load custom interface appearance");
80
81
  }
81
82
  },
82
- onCodeEditorVisibilityChanged(o) {
83
- e.isCodeEditorOpen = o;
83
+ onCodeEditorVisibilityChanged(e) {
84
+ o.isCodeEditorOpen = e;
84
85
  },
85
- onEditorVisualModeChanged(o) {
86
- e.editorVisualMode = o.toLowerCase();
86
+ onEditorVisualModeChanged(e) {
87
+ o.editorVisualMode = e.toLowerCase();
87
88
  },
88
- onVersionHistoryVisibilityChanged(o) {
89
- e.isVersionHistoryOpen = o;
89
+ onVersionHistoryVisibilityChanged(e) {
90
+ o.isVersionHistoryOpen = e;
90
91
  },
91
92
  onDataChanged() {
92
- e.hasChanges = !0;
93
+ o.hasChanges = !0;
93
94
  },
94
95
  onEvent: F,
96
+ notifications: V(),
95
97
  ignoreClickOutsideSelectors: [
96
98
  "#guido-dynamic-content-modal",
97
99
  ".in-on-board-wrapper",
98
100
  ".in-drawer__container"
99
101
  ],
100
102
  extensions: d,
101
- localePatch: z
103
+ localePatch: L
102
104
  }
103
105
  );
104
- }, _ = (s) => new Promise((r, i) => {
106
+ }, A = (s) => new Promise((i, r) => {
105
107
  var d;
106
108
  if (document.getElementById("UiEditorScript")) {
107
- Promise.resolve(s()).then(r, i);
109
+ Promise.resolve(s()).then(i, r);
108
110
  return;
109
111
  }
110
- const e = N.guido, a = `https://email-static.useinsider.com/guido/${(d = e == null ? void 0 : e.stripo) == null ? void 0 : d.version}/UIEditor.js`, t = document.createElement("script");
112
+ const o = j.guido, a = `https://email-static.useinsider.com/guido/${(d = o == null ? void 0 : o.stripo) == null ? void 0 : d.version}/UIEditor.js`, t = document.createElement("script");
111
113
  t.id = "UiEditorScript", t.type = "module", t.src = a, t.onload = () => {
112
- Promise.resolve(s()).then(r, i);
114
+ Promise.resolve(s()).then(i, r);
113
115
  }, t.onerror = () => {
114
- i(new Error(`Failed to load Stripo UIEditor script from S3: ${a}`));
116
+ r(new Error(`Failed to load Stripo UIEditor script from S3: ${a}`));
115
117
  }, document.body.appendChild(t);
116
118
  });
117
119
  return { initPlugin: async (s) => {
118
- const r = C();
120
+ const i = E();
119
121
  try {
120
- await _(async () => {
121
- const [i, e] = await Promise.all([
122
+ await A(async () => {
123
+ const [r, o] = await Promise.all([
122
124
  k(),
123
125
  B()
124
126
  ]);
125
- r.syncModulesEnabled = e, await V(s, i, e);
127
+ i.syncModulesEnabled = o, await _(s, r, o);
126
128
  });
127
129
  } catch {
128
- r.loadingStatus = !1, b({
129
- type: L.Alert,
130
+ i.loadingStatus = !1, b({
131
+ type: $.Error,
130
132
  message: h["An error has occurred. Please report the error code to support."],
131
133
  actionButton: {
132
134
  text: h["Reload page"],
@@ -137,5 +139,5 @@ const ce = (E, l) => {
137
139
  } };
138
140
  };
139
141
  export {
140
- ce as useStripo
142
+ fo as useStripo
141
143
  };
@@ -0,0 +1,26 @@
1
+ import { useToaster as d } from "./useToaster.js";
2
+ import { ToasterTypeOptions as c } from "../enums/toaster.js";
3
+ const g = () => {
4
+ const { showToaster: s, hideToaster: u } = d();
5
+ let r = null;
6
+ const n = (o, t, i, e, f = !0) => {
7
+ r = i;
8
+ const l = e != null && e.action ? { text: e.action.label, onClick: e.action.func } : void 0;
9
+ s({ type: o, message: t, actionButton: l, autoHide: (e == null ? void 0 : e.autoClose) ?? f });
10
+ };
11
+ return { getStripoNotifications: () => ({
12
+ info: (o, t, i) => n(c.Info, o, t, i),
13
+ success: (o, t, i) => n(c.Success, o, t, i),
14
+ warn: (o, t, i) => n(c.Warning, o, t, i),
15
+ error: (o, t, i) => n(c.Error, o, t, i),
16
+ // A loader marks an in-progress operation; Stripo dismisses it via hide(id)
17
+ // when finished, so it must not auto-hide.
18
+ loader: (o, t, i) => n(c.Info, o, t, i, !1),
19
+ hide: (o) => {
20
+ r === o && (u(), r = null);
21
+ }
22
+ }) };
23
+ };
24
+ export {
25
+ g as useStripoNotifications
26
+ };
@@ -1,29 +1,29 @@
1
1
  import { ToasterTypeOptions as T } from "../enums/toaster.js";
2
2
  import { useToasterStore as c } from "../stores/toaster.js";
3
- import { watch as u, nextTick as l } from "vue";
3
+ import { watch as u, nextTick as f } from "vue";
4
4
  const p = () => {
5
- const t = c();
6
- let o = null;
5
+ const o = c();
6
+ let t = null;
7
7
  const s = () => {
8
- o && (clearTimeout(o), o = null);
8
+ t && (clearTimeout(t), t = null);
9
9
  };
10
10
  function r(e = { message: "" }) {
11
- s(), t.hideToaster(), l(() => {
12
- t.showToaster(e);
11
+ s(), o.hideToaster(), f(() => {
12
+ o.showToaster(e);
13
13
  });
14
14
  }
15
15
  function i() {
16
- s(), t.hideToaster();
16
+ s(), o.hideToaster();
17
17
  }
18
18
  function n(e, a) {
19
19
  const m = e instanceof Error ? e.message : String(e);
20
- r({ type: T.Alert, message: `${a}: ${m}` });
20
+ r({ type: T.Error, message: `${a}: ${m}` });
21
21
  }
22
22
  return u(
23
- () => t.shouldAutoHide,
23
+ () => o.shouldAutoHide,
24
24
  (e) => {
25
- s(), e && (o = setTimeout(() => {
26
- t.hideToaster(), s();
25
+ s(), e && (t = setTimeout(() => {
26
+ o.hideToaster(), s();
27
27
  }, 6e3));
28
28
  }
29
29
  ), { showToaster: r, hideToaster: i, handleError: n };
@@ -24,7 +24,7 @@ const S = () => {
24
24
  window.StripoEditorApi.versionHistoryApi.previewVersion(e, (o) => {
25
25
  const r = o instanceof Error ? o.message : String(o);
26
26
  s({
27
- type: t.Alert,
27
+ type: t.Error,
28
28
  message: `Error compiling email: ${r}`
29
29
  });
30
30
  });
@@ -41,7 +41,7 @@ const S = () => {
41
41
  (o) => {
42
42
  const r = o instanceof Error ? o.message : String(o);
43
43
  s({
44
- type: t.Alert,
44
+ type: t.Error,
45
45
  message: `Error compiling email: ${r}`
46
46
  });
47
47
  }
@@ -31,7 +31,7 @@ const v = () => {
31
31
  }), !1) : !0;
32
32
  } catch {
33
33
  return e({
34
- type: a.Alert,
34
+ type: a.Error,
35
35
  message: s("journey-builder.liquid-validation-failed")
36
36
  }), !1;
37
37
  }
@@ -1,8 +1,8 @@
1
1
  import { ToasterTypeOptions as i } from "../../enums/toaster.js";
2
2
  import { PAGE_TYPES as u } from "../../enums/unsubscribe.js";
3
3
  import { UNSUBSCRIBE_BLOCK_SELECTOR as l, DATA_ATTRIBUTES as a } from "../../extensions/Blocks/Unsubscribe/utils/constants.js";
4
- import { useToaster as m } from "../useToaster.js";
5
- import { useTranslations as E } from "../useTranslations.js";
4
+ import { useToaster as E } from "../useToaster.js";
5
+ import { useTranslations as m } from "../useTranslations.js";
6
6
  const T = [
7
7
  {
8
8
  pageType: u.GLOBAL_UNSUBSCRIBE,
@@ -13,23 +13,23 @@ const T = [
13
13
  messageKey: "unsubscription-preference.duplicate-pref-center"
14
14
  }
15
15
  ], g = "unsubscription-preference.duplicate-both", b = "unsubscription-preference.select-page-to-continue", P = () => {
16
- const { showToaster: c } = m(), p = E();
16
+ const { showToaster: c } = E(), p = m();
17
17
  return { validateUnsubscribeBlockUniqueness: (n) => {
18
- const o = new DOMParser().parseFromString(n, "text/html"), s = /* @__PURE__ */ new Map();
18
+ const o = new DOMParser().parseFromString(n, "text/html"), r = /* @__PURE__ */ new Map();
19
19
  o.querySelectorAll(l).forEach((e) => {
20
- const r = Number(e.getAttribute(a.PAGE_TYPE));
21
- s.set(r, (s.get(r) ?? 0) + 1);
20
+ const s = Number(e.getAttribute(a.PAGE_TYPE));
21
+ r.set(s, (r.get(s) ?? 0) + 1);
22
22
  });
23
- const t = T.filter((e) => (s.get(e.pageType) ?? 0) > 1).map((e) => e.messageKey);
23
+ const t = T.filter((e) => (r.get(e.pageType) ?? 0) > 1).map((e) => e.messageKey);
24
24
  return t.length ? (c({
25
- type: i.Alert,
25
+ type: i.Error,
26
26
  message: p(t.length > 1 ? g : t[0])
27
27
  }), !1) : !0;
28
28
  }, validateUnsubscribeBlockHasTemplate: (n) => {
29
29
  const o = new DOMParser().parseFromString(n, "text/html");
30
30
  return Array.from(o.querySelectorAll(l)).some((t) => {
31
- const e = t.getAttribute(a.PAGE_TYPE), r = t.getAttribute(a.PAGE_LIST);
32
- return !e || !r;
31
+ const e = t.getAttribute(a.PAGE_TYPE), s = t.getAttribute(a.PAGE_LIST);
32
+ return !e || !s;
33
33
  }) ? (c({
34
34
  type: i.Warning,
35
35
  message: p(b)
@@ -122,10 +122,10 @@ const d = [
122
122
  ], i = /<head>([\S\s]*)<\/head>/, o = new RegExp(i);
123
123
  if (!e.match(o))
124
124
  return e;
125
- let s = e;
126
- return t.forEach((r) => {
127
- s = s.replace("</head>", `${r}</head>`);
128
- }), s;
125
+ let r = e;
126
+ return t.forEach((s) => {
127
+ r = r.replace("</head>", `${s}</head>`);
128
+ }), r;
129
129
  },
130
130
  priority: 30
131
131
  },
@@ -156,9 +156,9 @@ const d = [
156
156
  type: "custom",
157
157
  processor: (e) => {
158
158
  const t = (i) => i.toString(16).padStart(2, "0");
159
- return e.replace(/rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)/gi, (i, o, n, s) => {
160
- const [r, a, c] = [Number(o), Number(n), Number(s)];
161
- return r > 255 || a > 255 || c > 255 ? i : `#${t(r)}${t(a)}${t(c)}`;
159
+ return e.replace(/rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)/gi, (i, o, n, r) => {
160
+ const [s, a, c] = [Number(o), Number(n), Number(r)];
161
+ return s > 255 || a > 255 || c > 255 ? i : `#${t(s)}${t(a)}${t(c)}`;
162
162
  }).replace(/#([0-9a-f])\1([0-9a-f])\2([0-9a-f])\3\b/gi, "#$1$2$3");
163
163
  },
164
164
  priority: 44
@@ -174,6 +174,29 @@ const d = [
174
174
  replacement: "",
175
175
  flags: "g",
176
176
  priority: 45
177
+ },
178
+ {
179
+ id: "remove-script-tags",
180
+ // SD-145051: parity with HB HtmlCleaner.removeUnsafeHtmlTags — strip <script> from
181
+ // compiled email. Priority 50 runs after the &lt;/&gt; unescape rules (13/14) so
182
+ // post-unescape tags are still caught. Do NOT add to AMP_SAFE_RULE_IDS (AMP needs <script>).
183
+ description: "Strip <script>…<\/script> tags from compiled email",
184
+ type: "regex",
185
+ pattern: "<script[^>]*>.*?<\/script>",
186
+ replacement: "",
187
+ flags: "gis",
188
+ priority: 50
189
+ },
190
+ {
191
+ id: "remove-iframe-tags",
192
+ // SD-145051: parity with HB HtmlCleaner.removeUnsafeHtmlTags — strip <iframe>.
193
+ // Do NOT add this id to AMP_SAFE_RULE_IDS.
194
+ description: "Strip <iframe>…</iframe> tags from compiled email",
195
+ type: "regex",
196
+ pattern: "<iframe[^>]*>.*?</iframe>",
197
+ replacement: "",
198
+ flags: "gis",
199
+ priority: 51
177
200
  }
178
201
  ];
179
202
  export {