@useinsider/guido 3.2.0-beta.4aabac5 → 3.2.0-beta.6d12eec

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.
package/README.md CHANGED
@@ -143,6 +143,7 @@ const config: GuidoConfigInput = {
143
143
  displayConditions?: boolean, // Default: true
144
144
  unsubscribe?: boolean, // Default: true
145
145
  modulesDisabled?: boolean, // Default: false - Disable modules panel
146
+ liquidSyntax?: boolean, // Default: false - Enable Liquid template syntax
146
147
  },
147
148
 
148
149
  // Optional: Callbacks
@@ -4,7 +4,7 @@ import d from "../../../_virtual/_plugin-vue2_normalizer.js";
4
4
  var u = function() {
5
5
  var s, i, n, a;
6
6
  var o = this, e = o._self._c, t = o._self._setupProxy;
7
- return e("div", { staticClass: "d-f editor-actions" }, [t.isVersionHistoryButtonVisible ? e(t.InButtonV2, { attrs: { id: "guido__history-button", "left-icon": "line-architect-version-history", styling: "ghost", type: "secondary", "disabled-status": t.editorStore.isVersionHistoryButtonDisabled, "label-text-status": !1, "selected-status": t.editorStore.isVersionHistoryOpen, "tooltip-options": t.getTooltipOptions("guido__history-button"), "tooltip-text": t.versionHistoryTooltipText }, on: { click: t.handleVersionHistory } }) : o._e(), e(t.InButtonV2, { attrs: { id: "guido__export-button", "left-icon": "line-export", styling: "ghost", type: "secondary", "disabled-status": t.editorStore.isExportButtonDisabled, "label-text-status": !1, "loading-status": t.isExporting, "tooltip-options": t.getTooltipOptions("guido__export-button"), "tooltip-text": t.trans("newsletter.export") }, on: { click: t.handleExport } }), (i = (s = t.config) == null ? void 0 : s.features) != null && i.saveAsTemplate ? e(t.InButtonV2, { attrs: { id: "guido__save-as-button", "left-icon": "line-newsletter-save-as-template", styling: "ghost", type: "secondary", "disabled-status": t.editorStore.isSaveAsButtonDisabled, "label-text-status": !1, "tooltip-options": t.getTooltipOptions("guido__save-as-button"), "tooltip-text": t.trans("newsletter.save-templates") }, on: { click: t.handleSaveAs } }) : o._e(), (a = (n = t.config) == null ? void 0 : n.features) != null && a.testMessage ? e(t.InButtonV2, { attrs: { id: "guido__test-button", "left-icon": "line-architect-test-journey", styling: "ghost", type: "secondary", "disabled-status": t.editorStore.isTestButtonDisabled, "label-text-status": !1, "tooltip-options": t.getTooltipOptions("guido__test-button", { staticPosition: "bottom right" }), "tooltip-text": t.trans("newsletter.test-email") }, on: { click: t.testEmailClick } }) : o._e(), t.editorStore.isPreviewModeOpen ? o._e() : e(t.InButtonV2, { staticClass: "ml-3", attrs: { id: "guido__save-button", "label-text": "Save", "disabled-status": !t.isSaving && t.editorStore.isSaveButtonDisabled, "loading-status": t.isSaving }, on: { click: function(r) {
7
+ return e("div", { staticClass: "d-f editor-actions" }, [t.isVersionHistoryButtonVisible ? e(t.InButtonV2, { attrs: { id: "guido__history-button", "left-icon": "line-architect-version-history", styling: "ghost", type: "secondary", "disabled-status": t.editorStore.isVersionHistoryButtonDisabled, "label-text-status": !1, "selected-status": t.editorStore.isVersionHistoryOpen, "tooltip-options": t.getTooltipOptions("guido__history-button"), "tooltip-text": t.versionHistoryTooltipText }, on: { click: t.handleVersionHistory } }) : o._e(), e(t.InButtonV2, { attrs: { id: "guido__export-button", "left-icon": "line-export", styling: "ghost", type: "secondary", "disabled-status": t.editorStore.isExportButtonDisabled, "label-text-status": !1, "loading-status": t.isExporting, "tooltip-options": t.getTooltipOptions("guido__export-button"), "tooltip-text": t.trans("newsletter.export") }, on: { click: t.handleExport } }), (i = (s = t.config) == null ? void 0 : s.features) != null && i.saveAsTemplate ? e(t.InButtonV2, { attrs: { id: "guido__save-as-button", "left-icon": "line-newsletter-save-as-template", styling: "ghost", type: "secondary", "disabled-status": t.editorStore.isSaveAsButtonDisabled, "label-text-status": !1, "tooltip-options": t.getTooltipOptions("guido__save-as-button"), "tooltip-text": t.trans("newsletter.save-templates") }, on: { click: t.handleSaveAs } }) : o._e(), (a = (n = t.config) == null ? void 0 : n.features) != null && a.testMessage ? e(t.InButtonV2, { attrs: { id: "guido__test-button", "left-icon": "line-architect-test-journey", styling: "ghost", type: "secondary", "disabled-status": t.editorStore.isTestButtonDisabled, "label-text-status": !1, "tooltip-options": t.getTooltipOptions("guido__test-button", { staticPosition: "bottom right" }), "tooltip-text": t.trans("newsletter.test-email") }, on: { click: t.handleTestEmail } }) : o._e(), t.editorStore.isPreviewModeOpen ? o._e() : e(t.InButtonV2, { staticClass: "ml-3", attrs: { id: "guido__save-button", "label-text": "Save", "disabled-status": !t.isSaving && t.editorStore.isSaveButtonDisabled, "loading-status": t.isSaving }, on: { click: function(r) {
8
8
  return t.handleSave(!1);
9
9
  } } }), e(t.MigrationConfirmModal, { ref: "migrationModalRef", on: { confirm: function(r) {
10
10
  return t.executeSave(!1);
@@ -15,7 +15,7 @@ var u = function() {
15
15
  p,
16
16
  !1,
17
17
  null,
18
- "acff76a8"
18
+ "4e2a4adb"
19
19
  );
20
20
  const v = c.exports;
21
21
  export {
@@ -1,51 +1,66 @@
1
- import { defineComponent as E, ref as n, computed as g } from "vue";
2
- import { useConfig as w } from "../../../composables/useConfig.js";
3
- import { useExport as C } from "../../../composables/useExport.js";
4
- import { useTestEmailClick as M } from "../../../composables/useGuidoActions.js";
5
- import { useSave as O } from "../../../composables/useSave.js";
6
- import { useTranslations as A } from "../../../composables/useTranslations.js";
7
- import { useVersionHistoryApi as k } from "../../../composables/useVersionHistoryApi.js";
8
- import { useEditorStore as B } from "../../../stores/editor.js";
9
- import { useTemplateStore as R } from "../../../stores/template.js";
10
- import { getTooltipOptions as b } from "../../../utils/tooltipUtils.js";
11
- import { InButtonV2 as D } from "@useinsider/design-system-vue";
12
- import { storeToRefs as I } from "pinia";
13
- import P from "./MigrationConfirmModal.vue.js";
14
- const Z = /* @__PURE__ */ E({
1
+ import { defineComponent as O, ref as n, computed as h } from "vue";
2
+ import { useActionsApi as q } from "../../../composables/useActionsApi.js";
3
+ import { useConfig as b } from "../../../composables/useConfig.js";
4
+ import { useExport as k } from "../../../composables/useExport.js";
5
+ import { useTestEmailClick as B } from "../../../composables/useGuidoActions.js";
6
+ import { useHtmlCompiler as D } from "../../../composables/useHtmlCompiler.js";
7
+ import { useSave as F } from "../../../composables/useSave.js";
8
+ import { useTranslations as L } from "../../../composables/useTranslations.js";
9
+ import { useVersionHistoryApi as R } from "../../../composables/useVersionHistoryApi.js";
10
+ import { useLiquidValidator as z } from "../../../composables/validators/useLiquidValidator.js";
11
+ import { useEditorStore as I } from "../../../stores/editor.js";
12
+ import { useTemplateStore as P } from "../../../stores/template.js";
13
+ import { getTooltipOptions as j } from "../../../utils/tooltipUtils.js";
14
+ import { InButtonV2 as G } from "@useinsider/design-system-vue";
15
+ import { storeToRefs as J } from "pinia";
16
+ import K from "./MigrationConfirmModal.vue.js";
17
+ const ut = /* @__PURE__ */ O({
15
18
  __name: "EditorActions",
16
- setup(j, { expose: H }) {
17
- const { config: a } = w(), { exportHtml: m } = C(), { save: p } = O(), { openVersionHistory: l, closeVersionHistory: u } = k(), e = B(), c = R(), { hasMigrations: f } = I(c), r = A(), s = n(!1), i = n(!1), v = n(), S = M(), V = () => {
19
+ setup(N, { expose: x }) {
20
+ const { config: a, isFeatureEnabled: l } = b(), { exportHtml: m } = k(), { save: u } = F(), { openVersionHistory: c, closeVersionHistory: p } = R(), { getCompiledEmail: f } = q(), { compileHtml: d } = D(), { validateLiquidSyntax: v } = z(), e = I(), y = P(), { hasMigrations: S } = J(y), s = L(), i = n(!1), r = n(!1), g = n(), H = B(), T = () => {
18
21
  if (e.isVersionHistoryOpen) {
19
- u();
22
+ p();
20
23
  return;
21
24
  }
22
- l();
23
- }, T = async () => {
24
- s.value = !0, await m(), s.value = !1;
25
+ c();
26
+ }, w = async () => {
27
+ i.value = !0, await m(), i.value = !1;
25
28
  }, _ = () => {
26
29
  e.isSaveAsTemplateDrawerOpen = !0;
27
- }, h = g(() => e.isVersionHistoryOpen ? r("newsletter.close-version-history") : r("newsletter.version-history")), x = g(
30
+ }, C = h(() => e.isVersionHistoryOpen ? s("newsletter.close-version-history") : s("newsletter.version-history")), A = h(
28
31
  () => {
29
- var o, t;
30
- return ((t = (o = a.value) == null ? void 0 : o.features) == null ? void 0 : t.versionHistory) && !e.isPreviewModeOpen;
32
+ var t, o;
33
+ return ((o = (t = a.value) == null ? void 0 : t.features) == null ? void 0 : o.versionHistory) && !e.isPreviewModeOpen;
31
34
  }
32
- ), d = async (o) => {
33
- i.value = !0, e.loadingStatus = !0;
34
- const t = await p(o);
35
- return i.value = !1, (o || !t) && (e.loadingStatus = !1), t;
36
- }, y = (o) => {
37
- var t;
38
- if (!o && f.value) {
39
- (t = v.value) == null || t.open();
35
+ ), V = async (t) => {
36
+ r.value = !0, e.loadingStatus = !0;
37
+ const o = await u(t);
38
+ return r.value = !1, (t || !o) && (e.loadingStatus = !1), o;
39
+ }, E = (t) => {
40
+ var o;
41
+ if (!t && S.value) {
42
+ (o = g.value) == null || o.open();
40
43
  return;
41
44
  }
42
- return d(o);
45
+ return V(t);
46
+ }, M = async () => {
47
+ if (l("liquidSyntax")) {
48
+ e.loadingStatus = !0;
49
+ try {
50
+ const { html: t } = await f({ minimize: !0, resetDataSavedFlag: !1 }), { compiledHtml: o } = d(t);
51
+ if (!await v(o))
52
+ return;
53
+ } finally {
54
+ e.loadingStatus = !1;
55
+ }
56
+ }
57
+ H();
43
58
  };
44
- return H({
45
- handleSave: y
46
- }), { __sfc: !0, config: a, exportHtml: m, save: p, openVersionHistory: l, closeVersionHistory: u, editorStore: e, templateStore: c, hasMigrations: f, trans: r, isExporting: s, isSaving: i, migrationModalRef: v, testEmailClick: S, handleVersionHistory: V, handleExport: T, handleSaveAs: _, versionHistoryTooltipText: h, isVersionHistoryButtonVisible: x, executeSave: d, handleSave: y, getTooltipOptions: b, InButtonV2: D, MigrationConfirmModal: P };
59
+ return x({
60
+ handleSave: E
61
+ }), { __sfc: !0, config: a, isFeatureEnabled: l, exportHtml: m, save: u, openVersionHistory: c, closeVersionHistory: p, getCompiledEmail: f, compileHtml: d, validateLiquidSyntax: v, editorStore: e, templateStore: y, hasMigrations: S, trans: s, isExporting: i, isSaving: r, migrationModalRef: g, testEmailClick: H, handleVersionHistory: T, handleExport: w, handleSaveAs: _, versionHistoryTooltipText: C, isVersionHistoryButtonVisible: A, executeSave: V, handleSave: E, handleTestEmail: M, getTooltipOptions: j, InButtonV2: G, MigrationConfirmModal: K };
47
62
  }
48
63
  });
49
64
  export {
50
- Z as default
65
+ ut as default
51
66
  };
@@ -1,17 +1,17 @@
1
- import o from "./RightSlot.vue2.js";
2
- import s from "../../../_virtual/_plugin-vue2_normalizer.js";
3
- var n = function() {
4
- var r = this, t = r._self._c, e = r._self._setupProxy;
5
- return t("div", { staticClass: "d-f" }, [e.editorStore.isVersionHistoryOpen ? t(e.RestoreButton) : t(e.EditorActions, { ref: "editorActionsRef" })], 1);
6
- }, i = [], _ = /* @__PURE__ */ s(
7
- o,
8
- n,
1
+ import i from "./RightSlot.vue2.js";
2
+ import r from "../../../_virtual/_plugin-vue2_normalizer.js";
3
+ var o = function() {
4
+ var s = this, e = s._self._c, t = s._self._setupProxy;
5
+ return e("div", { staticClass: "d-f a-i-c" }, [t.isLiquidEnabled && !t.editorStore.isVersionHistoryOpen ? e(t.InChips, { staticClass: "mr-3", attrs: { id: "guido__liquid-tag-chip", styles: "stroke", type: "default", value: "liquid-tags", "close-button": !1, "disabled-status": t.editorStore.loadingStatus, interactive: !1, text: t.trans("email-editor.liquid-tags-enabled") } }) : s._e(), t.editorStore.isVersionHistoryOpen ? e(t.RestoreButton) : e(t.EditorActions, { ref: "editorActionsRef" })], 1);
6
+ }, a = [], n = /* @__PURE__ */ r(
9
7
  i,
8
+ o,
9
+ a,
10
10
  !1,
11
11
  null,
12
12
  null
13
13
  );
14
- const l = _.exports;
14
+ const u = n.exports;
15
15
  export {
16
- l as default
16
+ u as default
17
17
  };
@@ -1,19 +1,22 @@
1
- import { defineComponent as i, ref as s } from "vue";
2
- import { useEditorStore as m } from "../../../stores/editor.js";
3
- import f from "./EditorActions.vue.js";
4
- import a from "./version-history/RestoreButton.vue.js";
5
- const l = /* @__PURE__ */ i({
1
+ import { defineComponent as a, ref as f, computed as p } from "vue";
2
+ import { useConfig as u } from "../../../composables/useConfig.js";
3
+ import { useTranslations as d } from "../../../composables/useTranslations.js";
4
+ import { useEditorStore as c } from "../../../stores/editor.js";
5
+ import { InChips as l } from "@useinsider/design-system-vue";
6
+ import _ from "./EditorActions.vue.js";
7
+ import S from "./version-history/RestoreButton.vue.js";
8
+ const x = /* @__PURE__ */ a({
6
9
  __name: "RightSlot",
7
- setup(p, { expose: e }) {
8
- const r = m(), o = s(null);
9
- return e({
10
- handleSave: (n) => {
11
- var t;
12
- return (t = o.value) == null ? void 0 : t.handleSave(n);
10
+ setup(h, { expose: r }) {
11
+ const { isFeatureEnabled: o } = u(), n = d(), i = c(), t = f(null), s = p(() => o("liquidSyntax"));
12
+ return r({
13
+ handleSave: (m) => {
14
+ var e;
15
+ return (e = t.value) == null ? void 0 : e.handleSave(m);
13
16
  }
14
- }), { __sfc: !0, editorStore: r, editorActionsRef: o, EditorActions: f, RestoreButton: a };
17
+ }), { __sfc: !0, isFeatureEnabled: o, trans: n, editorStore: i, editorActionsRef: t, isLiquidEnabled: s, InChips: l, EditorActions: _, RestoreButton: S };
15
18
  }
16
19
  });
17
20
  export {
18
- l as default
21
+ x as default
19
22
  };
@@ -10,29 +10,29 @@ import { useDebounceFn as V } from "../../../node_modules/@vueuse/shared/index.j
10
10
  const H = /* @__PURE__ */ A({
11
11
  __name: "SaveAsTemplateDrawer",
12
12
  setup(E) {
13
- const s = O(), o = D(), t = k(), { createTemplate: m } = B(), a = c(!1), n = c(!1), r = c(""), f = b(() => ({
13
+ const o = O(), n = D(), t = k(), { createTemplate: m } = B(), a = c(!1), r = c(!1), l = c(""), f = b(() => ({
14
14
  primaryButton: {
15
15
  styling: "solid",
16
16
  type: "primary",
17
- labelText: s(a.value ? "newsletter.saving" : "products.save"),
17
+ labelText: o(a.value ? "newsletter.saving" : "products.save"),
18
18
  loadingStatus: a.value,
19
19
  disabledStatus: t.skeletonStatus
20
20
  },
21
21
  cancelOrBackButton: {
22
22
  styling: "ghost",
23
23
  type: "secondary",
24
- labelText: s("products.cancel"),
24
+ labelText: o("products.cancel"),
25
25
  disabledStatus: a.value
26
26
  }
27
- })), p = () => {
28
- r.value = "", o.isSaveAsTemplateDrawerOpen = !1;
29
- }, l = async () => {
30
- const e = h(t, "templateName"), { success: i, errorMessage: _ } = await x(e).validate();
31
- return r.value = _, i;
27
+ })), u = () => {
28
+ l.value = "", n.isSaveAsTemplateDrawerOpen = !1;
29
+ }, i = async () => {
30
+ const e = h(t, "templateName"), { success: s, errorMessage: _ } = await x(e).validate();
31
+ return l.value = _, s;
32
32
  }, v = V(async (e) => {
33
- t.templateName = e, await l();
33
+ t.templateName = e, await i();
34
34
  }, 500), g = async (e) => {
35
- n.value = !0, await t.addCategory(e), n.value = !1;
35
+ r.value = !0, await t.addCategory(e), r.value = !1;
36
36
  }, y = (e) => {
37
37
  t.selectedCategories = e;
38
38
  }, S = (e) => {
@@ -40,22 +40,23 @@ const H = /* @__PURE__ */ A({
40
40
  }, T = () => {
41
41
  t.selectedCategories = [];
42
42
  }, w = async () => {
43
- if (a.value = !0, !await l()) {
43
+ if (a.value = !0, !await i()) {
44
44
  a.value = !1;
45
45
  return;
46
46
  }
47
- await m(), a.value = !1, p();
48
- }, u = () => {
47
+ const s = await m();
48
+ a.value = !1, s && u();
49
+ }, p = () => {
49
50
  C(() => {
50
51
  const e = document.querySelector("input#guido__template-name-input");
51
52
  e == null || e.focus();
52
53
  });
53
54
  }, d = async () => {
54
- t.$reset(), await t.fetchCategories(), t.skeletonStatus = !1, u();
55
+ t.$reset(), await t.fetchCategories(), t.skeletonStatus = !1, p();
55
56
  };
56
- return o.$subscribe((e, { isSaveAsTemplateDrawerOpen: i }) => {
57
- i && d();
58
- }), { __sfc: !0, trans: s, editorStore: o, saveAsTemplateStore: t, createTemplate: m, isSaving: a, isAddingOption: n, templateNameError: r, footerButtonGroupOptions: f, closeModal: p, validateTemplateName: l, handleTemplateName: v, handleAddOption: g, handleCategoryChange: y, handleSelectAllOptions: S, handleResetAllOptions: T, saveTemplate: w, focusToInput: u, initializeDrawer: d, WpDrawer: N, InBasicTextInput: M, InMultiSelect: I };
57
+ return n.$subscribe((e, { isSaveAsTemplateDrawerOpen: s }) => {
58
+ s && d();
59
+ }), { __sfc: !0, trans: o, editorStore: n, saveAsTemplateStore: t, createTemplate: m, isSaving: a, isAddingOption: r, templateNameError: l, footerButtonGroupOptions: f, closeModal: u, validateTemplateName: i, handleTemplateName: v, handleAddOption: g, handleCategoryChange: y, handleSelectAllOptions: S, handleResetAllOptions: T, saveTemplate: w, focusToInput: p, initializeDrawer: d, WpDrawer: N, InBasicTextInput: M, InMultiSelect: I };
59
60
  }
60
61
  });
61
62
  export {
@@ -0,0 +1,34 @@
1
+ const f = (r, t) => {
2
+ const e = window[r];
3
+ return typeof e == "string" ? e : t;
4
+ }, m = (r) => {
5
+ const t = ((e, s, n) => {
6
+ if (t.q) {
7
+ t.q.push([e, s, n]);
8
+ return;
9
+ }
10
+ t._api(e, s, n);
11
+ });
12
+ return t.q = [], t.identify = (e, s, n) => {
13
+ t("user", { uid: e }, n), s && t("user", s, n);
14
+ }, t.setUserVars = (e, s) => t("user", e, s), t.event = (e, s, n) => t("event", { n: e, p: s }, n), t.anonymize = () => t.identify(!1), t.shutdown = () => t("rec", !1), t.restart = () => t("rec", !0), t.log = (e, s) => t("log", [e, s]), t.consent = (e) => t("consent", e ?? !0), t.identifyAccount = (e, s) => t("account", { ...s ?? {}, acctId: e }), t.clearUserCookie = () => {
15
+ }, t.setVars = (e, s) => t("setVars", [e, s]), t._w = { XMLHttpRequest: r.XMLHttpRequest, fetch: r.fetch }, t._v = "1.3.0", t;
16
+ }, F = () => ({ injectFullStory: async () => {
17
+ var d;
18
+ const t = f("_fs_org", "");
19
+ if (!t)
20
+ return;
21
+ const e = document.querySelector("ui-editor"), s = (d = e == null ? void 0 : e.shadowRoot) == null ? void 0 : d.querySelector("iframe"), n = s == null ? void 0 : s.contentWindow, i = s == null ? void 0 : s.contentDocument;
22
+ if (!n || !i)
23
+ return;
24
+ const h = f("_fs_host", "fullstory.com"), l = f("_fs_script", "edge.fullstory.com/s/fs.js"), u = f("_fs_namespace", "FS");
25
+ if (n[u])
26
+ return;
27
+ const a = window.fetch.bind(window), y = typeof n.fetch == "function" ? n.fetch.bind(n) : a, w = (o, p) => (typeof o == "string" || o instanceof URL ? String(o) : o.url).includes("fullstory.com") ? a(o, p) : y(o, p);
28
+ n.fetch = w, n._fs_run_in_iframe = !0, n._fs_host = h, n._fs_script = l, n._fs_org = t, n._fs_namespace = u, n[u] = m(n);
29
+ const g = await (await a(`https://${l}`)).text(), _ = URL.createObjectURL(new Blob([g], { type: "text/javascript" })), c = i.createElement("script");
30
+ c.src = _, c.crossOrigin = "anonymous", c.onload = () => URL.revokeObjectURL(_), i.head.appendChild(c);
31
+ } });
32
+ export {
33
+ F as useFullStoryBridge
34
+ };
@@ -1,28 +1,30 @@
1
- import { defaultHtmlCompilerRules as n } from "../config/compiler/htmlCompilerRules.js";
2
- import { itemsCompilerRules as a } from "../config/compiler/itemsCompilerRules.js";
3
- import { outlookCompilerRules as f } from "../config/compiler/outlookCompilerRules.js";
4
- import { recommendationCompilerRules as R } from "../config/compiler/recommendationCompilerRules.js";
5
- import { socialCompilerRules as C } from "../config/compiler/socialCompilerRules.js";
1
+ import { defaultHtmlCompilerRules as c } from "../config/compiler/htmlCompilerRules.js";
2
+ import { itemsCompilerRules as f } from "../config/compiler/itemsCompilerRules.js";
3
+ import { liquidCompilerRules as R } from "../config/compiler/liquidCompilerRules.js";
4
+ import { outlookCompilerRules as C } from "../config/compiler/outlookCompilerRules.js";
5
+ import { recommendationCompilerRules as d } from "../config/compiler/recommendationCompilerRules.js";
6
+ import { socialCompilerRules as b } from "../config/compiler/socialCompilerRules.js";
6
7
  import { unsubscribeCompilerRules as g } from "../config/compiler/unsubscribeCompilerRules.js";
7
8
  import { createHtmlCompiler as H } from "../utils/htmlCompiler.js";
8
- import { useConfig as b } from "./useConfig.js";
9
- const q = () => {
9
+ import { useConfig as v } from "./useConfig.js";
10
+ const w = () => {
10
11
  var l, m, r;
11
- const { compiler: e, partner: t } = b(), i = ((l = e.value) == null ? void 0 : l.customRules) || [], s = [
12
- ...!!((m = e.value) != null && m.ignoreDefaultRules) ? [] : n,
13
- ...R,
12
+ const { compiler: e, isFeatureEnabled: t, partner: i } = v(), s = ((l = e.value) == null ? void 0 : l.customRules) || [], u = [
13
+ ...!!((m = e.value) != null && m.ignoreDefaultRules) ? [] : c,
14
+ ...d,
14
15
  ...g,
15
- ...a,
16
16
  ...f,
17
17
  ...C,
18
- ...i.map((o, c) => ({
18
+ ...b,
19
+ ...t("liquidSyntax") ? R : [],
20
+ ...s.map((o, a) => ({
19
21
  ...o,
20
- priority: o.priority + 1e3 + c
22
+ priority: o.priority + 1e3 + a
21
23
  // Ensure additional rules run after default rules
22
24
  }))
23
- ], p = H(s), u = (r = t.value) == null ? void 0 : r.fallbackFont;
24
- return { compileHtml: (o) => p.compile(o, void 0, u) };
25
+ ], p = H(u), n = (r = i.value) == null ? void 0 : r.fallbackFont;
26
+ return { compileHtml: (o) => p.compile(o, void 0, n) };
25
27
  };
26
28
  export {
27
- q as useHtmlCompiler
29
+ w as useHtmlCompiler
28
30
  };
@@ -1,23 +1,29 @@
1
- import { useActionsApi as d } from "./useActionsApi.js";
2
- import { useConfig as f } from "./useConfig.js";
3
- import { useSaveStart as v, useSaveComplete as S } from "./useGuidoActions.js";
4
- import { useSyncModuleExtractor as x } from "./useSyncModuleExtractor.js";
5
- import { useStripoApi as V } from "../services/stripoApi.js";
6
- import { useTemplatePreparation as y } from "../utils/templatePreparation.js";
7
- import { useHtmlValidator as w } from "./useHtmlValidator.js";
8
- const k = () => {
9
- const o = v(), s = S(), { validateHtml: i } = w(), { callbacks: a } = f(), { extractSyncModuleData: r } = x(), { setSyncModuleUnsubscriptionPages: n } = V(), { editorSave: l } = d();
10
- return { save: async (c = !1) => {
11
- var e;
1
+ import { useActionsApi as S } from "./useActionsApi.js";
2
+ import { useConfig as V } from "./useConfig.js";
3
+ import { useSaveStart as x, useSaveComplete as y } from "./useGuidoActions.js";
4
+ import { useSyncModuleExtractor as w } from "./useSyncModuleExtractor.js";
5
+ import { useStripoApi as b } from "../services/stripoApi.js";
6
+ import { useTemplatePreparation as q } from "../utils/templatePreparation.js";
7
+ import { useHtmlValidator as H } from "./useHtmlValidator.js";
8
+ import { useLiquidValidator as L } from "./validators/useLiquidValidator.js";
9
+ const F = () => {
10
+ const o = x(), s = y(), { validateHtml: r } = H(), { validateLiquidSyntax: n } = L(), { callbacks: a, isFeatureEnabled: l } = V(), { extractSyncModuleData: d } = w(), { setSyncModuleUnsubscriptionPages: u } = b(), { editorSave: c } = S();
11
+ return { save: async (m = !1) => {
12
+ var i;
12
13
  o();
13
- const { prepareTemplateDetails: m } = y(), t = await m();
14
- if (!await i(t.compiledHtml, t.dynamicContentList, !0) || (e = a.value) != null && e.externalValidation && !await a.value.externalValidation(t))
14
+ const { prepareTemplateDetails: p } = q(), t = await p();
15
+ if (l("liquidSyntax")) {
16
+ if (!await n(t.compiledHtml))
17
+ return;
18
+ } else if (!await r(t.compiledHtml, t.dynamicContentList, !0))
15
19
  return;
16
- l();
17
- const { unsubscribePayload: u, stripoModules: p } = r(t.rawHtml);
18
- return await n(u), t.modules = p, c || s(t), t;
20
+ if ((i = a.value) != null && i.externalValidation && !await a.value.externalValidation(t))
21
+ return;
22
+ c();
23
+ const { unsubscribePayload: f, stripoModules: v } = d(t.rawHtml);
24
+ return await u(f), t.modules = v, m || s(t), t;
19
25
  } };
20
26
  };
21
27
  export {
22
- k as useSave
28
+ F as useSave
23
29
  };
@@ -1,42 +1,43 @@
1
- import { useActionsApi as A } from "./useActionsApi.js";
2
- import { useBlocksConfig as F } from "./useBlocksConfig.js";
3
- import { useConfig as D } from "./useConfig.js";
4
- import { useCustomInterfaceAppearance as I } from "./useCustomInterfaceAppearance.js";
5
- import { useStripoEventHandler as P } from "./useStripoEventHandler.js";
6
- import { useToaster as U } from "./useToaster.js";
7
- import { localePatch as R } from "../config/i18n/index.js";
8
- import { displayConditions as H } from "../enums/displayConditions.js";
9
- import { useStripoApi as O } from "../services/stripoApi.js";
10
- import q from "../static/styles/customEditorStyle.css.js";
11
- import { useEditorStore as S } from "../stores/editor.js";
12
- import { dynamicContentToMergeTags as x } from "../utils/genericUtil.js";
13
- import L from "../package.json.js";
14
- const oe = (C, c) => {
15
- const { features: l, template: E } = D(), { handleError: u } = U(), { getToken: h, getCustomFonts: w, getSyncModulesStatus: b } = O(), { handleEvent: k } = P(), { getStripoBlocksConfig: T } = F(), V = async (i, n = [], r = !1) => {
16
- var f, g, y;
17
- const e = S(), { html: m, css: a } = i, { baseBlocks: o, extensions: d } = await T(), p = ((f = l.value) == null ? void 0 : f.displayConditions) ?? !0, B = ((g = l.value) == null ? void 0 : g.modulesDisabled) ?? !1, v = ((y = E.value) == null ? void 0 : y.forceRecreate) ?? !1;
1
+ import { useActionsApi as D } from "./useActionsApi.js";
2
+ import { useBlocksConfig as I } from "./useBlocksConfig.js";
3
+ import { useConfig as P } from "./useConfig.js";
4
+ import { useCustomInterfaceAppearance as U } from "./useCustomInterfaceAppearance.js";
5
+ import { useFullStoryBridge as R } from "./useFullStoryBridge.js";
6
+ import { useStripoEventHandler as q } from "./useStripoEventHandler.js";
7
+ import { useToaster as x } from "./useToaster.js";
8
+ import { localePatch as H } from "../config/i18n/index.js";
9
+ import { displayConditions as O } from "../enums/displayConditions.js";
10
+ import { useStripoApi as j } from "../services/stripoApi.js";
11
+ import L from "../static/styles/customEditorStyle.css.js";
12
+ import { useEditorStore as C } from "../stores/editor.js";
13
+ import { dynamicContentToMergeTags as $ } from "../utils/genericUtil.js";
14
+ import z from "../package.json.js";
15
+ const se = (E, l) => {
16
+ const { features: c, template: h, isFeatureEnabled: u } = P(), { handleError: m } = x(), { getToken: b, getCustomFonts: w, getSyncModulesStatus: k } = j(), { handleEvent: B } = q(), { getStripoBlocksConfig: T } = I(), V = async (i, n = [], r = !1) => {
17
+ var g, y, S;
18
+ const e = C(), { html: p, css: a } = i, { baseBlocks: o, extensions: d } = await T(), f = ((g = c.value) == null ? void 0 : g.displayConditions) ?? !0, v = ((y = c.value) == null ? void 0 : y.modulesDisabled) ?? !1, F = ((S = h.value) == null ? void 0 : S.forceRecreate) ?? !1;
18
19
  window.UIEditor.initEditor(
19
20
  document.querySelector("#guido-editor"),
20
21
  {
21
- metadata: C,
22
- html: m,
22
+ metadata: E,
23
+ html: p,
23
24
  css: a,
24
- forceRecreate: v,
25
+ forceRecreate: F,
25
26
  locale: "en",
26
27
  undoButtonSelector: "#guido__undo-button",
27
28
  redoButtonSelector: "#guido__redo-button",
28
29
  mobileViewButtonSelector: ".guido__view-option-selection-mobile",
29
30
  desktopViewButtonSelector: ".guido__view-option-selection-desktop",
30
31
  codeEditorButtonSelector: "#guido__code-button",
31
- customAppearanceMergetags: !0,
32
+ customAppearanceMergetags: !u("liquidSyntax"),
32
33
  customAppearanceMergetagsBorderColor: "#f1f3fe",
33
34
  customAppearanceMergetagsBackgroundColor: "#f1f3fe",
34
- customViewStyles: q,
35
- conditionsEnabled: p,
36
- customConditionsEnabled: p,
37
- conditionCategories: H,
35
+ customViewStyles: L,
36
+ conditionsEnabled: f,
37
+ customConditionsEnabled: f,
38
+ conditionCategories: O,
38
39
  enableXSSSecurity: !0,
39
- modulesDisabled: B,
40
+ modulesDisabled: v,
40
41
  syncModulesEnabled: r,
41
42
  messageSettingsEnabled: !0,
42
43
  displayGmailAnnotations: !0,
@@ -52,25 +53,28 @@ const oe = (C, c) => {
52
53
  },
53
54
  mergeTags: [
54
55
  {
55
- entries: x(c.preselectedDynamicContentList)
56
+ entries: $(
57
+ l.preselectedDynamicContentList,
58
+ u("liquidSyntax")
59
+ )
56
60
  }
57
61
  ],
58
62
  async onTokenRefreshRequest(t) {
59
63
  try {
60
- const s = await h();
64
+ const s = await b();
61
65
  t(s);
62
66
  } catch (s) {
63
- u(s, "Failed to refresh token");
67
+ m(s, "Failed to refresh token");
64
68
  }
65
69
  },
66
70
  onTemplateLoaded() {
67
71
  try {
68
- const { importCss: t } = I(), { activateCustomViewStyles: s, updateTimerInClonedTemplate: M } = A();
69
- t(), s(), M(), c.onReady(), e.isStripoInitialized = !0, e.loadingStatus = !1, setTimeout(() => {
72
+ const { importCss: t } = U(), { activateCustomViewStyles: s, updateTimerInClonedTemplate: M } = D(), { injectFullStory: A } = R();
73
+ t(), s(), A(), M(), l.onReady(), e.isStripoInitialized = !0, e.loadingStatus = !1, setTimeout(() => {
70
74
  e.hasChanges = !1;
71
75
  }, 1e3);
72
76
  } catch (t) {
73
- u(t, "Failed to load custom interface appearance");
77
+ m(t, "Failed to load custom interface appearance");
74
78
  }
75
79
  },
76
80
  onCodeEditorVisibilityChanged(t) {
@@ -85,14 +89,14 @@ const oe = (C, c) => {
85
89
  onDataChanged() {
86
90
  e.hasChanges = !0;
87
91
  },
88
- onEvent: k,
92
+ onEvent: B,
89
93
  ignoreClickOutsideSelectors: [
90
94
  "#guido-dynamic-content-modal",
91
95
  ".in-on-board-wrapper",
92
96
  ".in-drawer__container"
93
97
  ],
94
98
  extensions: d,
95
- localePatch: R
99
+ localePatch: H
96
100
  }
97
101
  );
98
102
  }, _ = (i) => new Promise((n, r) => {
@@ -101,7 +105,7 @@ const oe = (C, c) => {
101
105
  i(), n();
102
106
  return;
103
107
  }
104
- const e = L.guido, a = `https://email-static.useinsider.com/guido/${(d = e == null ? void 0 : e.stripo) == null ? void 0 : d.version}/UIEditor.js`, o = document.createElement("script");
108
+ const e = z.guido, a = `https://email-static.useinsider.com/guido/${(d = e == null ? void 0 : e.stripo) == null ? void 0 : d.version}/UIEditor.js`, o = document.createElement("script");
105
109
  o.id = "UiEditorScript", o.type = "module", o.src = a, o.onload = () => {
106
110
  i(), n();
107
111
  }, o.onerror = () => {
@@ -110,14 +114,14 @@ const oe = (C, c) => {
110
114
  });
111
115
  return { initPlugin: async (i) => {
112
116
  await _(async () => {
113
- const n = S(), [r, e] = await Promise.all([
117
+ const n = C(), [r, e] = await Promise.all([
114
118
  w(),
115
- b()
119
+ k()
116
120
  ]);
117
121
  n.syncModulesEnabled = e, await V(i, r, e);
118
122
  });
119
123
  } };
120
124
  };
121
125
  export {
122
- oe as useStripo
126
+ se as useStripo
123
127
  };
@@ -0,0 +1,42 @@
1
+ import { ToasterTypeOptions as a } from "../../enums/toaster.js";
2
+ import { base64EncodeWithSpecialChars as u } from "../../utils/base64.js";
3
+ import { useHttp as d } from "../useHttp.js";
4
+ import { useToaster as c } from "../useToaster.js";
5
+ import { useTranslations as p } from "../useTranslations.js";
6
+ const v = () => {
7
+ const { post: i } = d(), { showToaster: e } = c(), s = p();
8
+ return { validateLiquidSyntax: async (o) => {
9
+ try {
10
+ const t = await i("/newsletter/contents/validate-syntax", [{
11
+ identifier: "default",
12
+ syntax: "liquid",
13
+ contents: {
14
+ subject: null,
15
+ preheader: null,
16
+ html: u(o),
17
+ ampHtml: null
18
+ }
19
+ }]);
20
+ if (!Array.isArray(t.data)) {
21
+ const l = t.data;
22
+ return e({
23
+ type: a.Warning,
24
+ message: l.message ?? s("journey-builder.liquid-validation-failed")
25
+ }), !1;
26
+ }
27
+ const [r] = t.data, n = Object.values((r == null ? void 0 : r.errors) ?? {});
28
+ return n.length ? (e({
29
+ type: a.Warning,
30
+ message: n[0].replace(/^line \d+:\s*/, "")
31
+ }), !1) : !0;
32
+ } catch {
33
+ return e({
34
+ type: a.Alert,
35
+ message: s("journey-builder.liquid-validation-failed")
36
+ }), !1;
37
+ }
38
+ } };
39
+ };
40
+ export {
41
+ v as useLiquidValidator
42
+ };
@@ -0,0 +1,15 @@
1
+ import { COUPON_PLACEHOLDER_LIQUID as e, COUPON_PLACEHOLDER_DEFAULT as i } from "../../extensions/Blocks/CouponBlock/template.js";
2
+ const o = [
3
+ {
4
+ id: "liquid-coupon-code",
5
+ description: "Replace legacy coupon placeholder with liquid syntax",
6
+ type: "replace",
7
+ search: i,
8
+ replacement: e,
9
+ replaceAll: !0,
10
+ priority: 50
11
+ }
12
+ ];
13
+ export {
14
+ o as liquidCompilerRules
15
+ };
@@ -1,29 +1,40 @@
1
- import { BlockType as o } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
2
- import { COUPON_BLOCK_ID as e } from "./block.js";
3
- const t = `
4
- <${o.BLOCK_TEXT}
1
+ import { useConfig as n } from "../../../composables/useConfig.js";
2
+ import { BlockType as e } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
3
+ import { COUPON_BLOCK_ID as t } from "./block.js";
4
+ const c = "{@COUPON_CODE}", s = "{{ins_coupon_code}}";
5
+ function l() {
6
+ const { isFeatureEnabled: o } = n();
7
+ return o("liquidSyntax") ? s : c;
8
+ }
9
+ function i(o) {
10
+ return `
11
+ <${e.BLOCK_TEXT}
5
12
  class="coupon-block ins-coupon-code coupon-block-v2 es-p10"
6
13
  align="center"
7
- esd-extension-block-id="${e}">
14
+ esd-extension-block-id="${t}">
8
15
  <p
9
16
  path="1"
10
17
  contenteditable="false"
11
18
  style="font-size: 16px; color: #333333;">
12
- <strong path="1,0">{@COUPON_CODE}</strong>
19
+ <strong path="1,0">${o}</strong>
13
20
  </p>
14
- </${o.BLOCK_TEXT}>
15
- `, l = `
21
+ </${e.BLOCK_TEXT}>
22
+ `;
23
+ }
24
+ const u = `
16
25
  <td
17
26
  class="coupon-block coupon-block-v2 ins-coupon-code esd-block-text esd-extension-block"
18
- esd-extension-block-id="${e}"
27
+ esd-extension-block-id="${t}"
19
28
  >
20
29
  <p class="ins-title" contenteditable="false">{@COUPON_CODE}</p>
21
30
  </td>
22
31
  `;
23
- function s() {
24
- return t;
32
+ function d() {
33
+ return i(l());
25
34
  }
26
35
  export {
27
- l as default,
28
- s as getDefaultTemplate
36
+ c as COUPON_PLACEHOLDER_DEFAULT,
37
+ s as COUPON_PLACEHOLDER_LIQUID,
38
+ u as default,
39
+ d as getDefaultTemplate
29
40
  };
@@ -1,16 +1,17 @@
1
1
  var c = Object.defineProperty;
2
2
  var g = (o, s, t) => s in o ? c(o, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : o[s] = t;
3
3
  var r = (o, s, t) => g(o, typeof s != "symbol" ? s + "" : s, t);
4
- import { mergeTagToDynamicContent as d, dynamicContentToMergeTags as m } from "../../utils/genericUtil.js";
5
- import { UIElement as u, UIElementType as a, UEAttr as h, UIElementTagRegistry as T } from "../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
6
- import { ExternalMergeTagsLibrary as y } from "./dynamic-content-modal.js";
7
- const l = "external-dynamic-content-ui-element", C = "button-add-dynamic-content";
8
- class p extends T {
4
+ import { useConfig as d } from "../../composables/useConfig.js";
5
+ import { mergeTagToDynamicContent as m, dynamicContentToMergeTags as u } from "../../utils/genericUtil.js";
6
+ import { UIElement as h, UIElementType as a, UEAttr as T, UIElementTagRegistry as y } from "../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
7
+ import { ExternalMergeTagsLibrary as C } from "./dynamic-content-modal.js";
8
+ const l = "external-dynamic-content-ui-element", L = "button-add-dynamic-content";
9
+ class w extends y {
9
10
  registerUiElements(s) {
10
11
  s[a.MERGETAGS] = l;
11
12
  }
12
13
  }
13
- class b extends u {
14
+ class f extends h {
14
15
  constructor() {
15
16
  super(...arguments);
16
17
  r(this, "mergeTagsButton", null);
@@ -43,7 +44,7 @@ class b extends u {
43
44
  onAttributeUpdated(t, e) {
44
45
  if (t !== "mergeTag" || !(e != null && e.value))
45
46
  return;
46
- const n = d(e), i = this._getLastClickedPosition();
47
+ const n = m(e), i = this._getLastClickedPosition();
47
48
  this.lastClickedElement = null, this.lastClickedFrame = null, this._openDynamicContentLibrary(n, i);
48
49
  }
49
50
  openMergeTagLibrary() {
@@ -55,10 +56,14 @@ class b extends u {
55
56
  * Dispatches event with dynamic content data and position
56
57
  */
57
58
  _openDynamicContentLibrary(t, e) {
58
- this.mergeTagsLibrary || (this.mergeTagsLibrary = new y()), this.mergeTagsLibrary.openMergeTagsLibrary(
59
+ this.mergeTagsLibrary || (this.mergeTagsLibrary = new C()), this.mergeTagsLibrary.openMergeTagsLibrary(
59
60
  t,
60
61
  (n) => {
61
- n.text && n.value ? this.api.triggerValueChange(m([n])[0]) : this.api.triggerValueChange(null);
62
+ if (n.text && n.value) {
63
+ const { isFeatureEnabled: i } = d();
64
+ this.api.triggerValueChange(u([n], i("liquidSyntax"))[0]);
65
+ } else
66
+ this.api.triggerValueChange(null);
62
67
  },
63
68
  e
64
69
  );
@@ -142,7 +147,7 @@ class b extends u {
142
147
  <${a.BUTTON}
143
148
  id="guido__btn-add-dynamic-content"
144
149
  class="btn btn-primary"
145
- ${h.BUTTON.name}="${C}">
150
+ ${T.BUTTON.name}="${L}">
146
151
  <${a.ICON} src="plus" class="icon icon-button color-primary">
147
152
  </${a.ICON}>
148
153
  ${this.api.translate("Add Dynamic Content")}
@@ -151,6 +156,6 @@ class b extends u {
151
156
  }
152
157
  }
153
158
  export {
154
- p as DynamicContentTagRegistry,
155
- b as DynamicContentUiElementExtension
159
+ w as DynamicContentTagRegistry,
160
+ f as DynamicContentUiElementExtension
156
161
  };
package/dist/guido.css CHANGED
@@ -1 +1 @@
1
- .gap-16[data-v-3b53a736],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-cd76c125] .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}.editor-actions[data-v-acff76a8]{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-25780af6]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-25780af6]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-25780af6]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-df672485]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-df672485]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-df672485]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-df672485]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-df672485]{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-29b9af29] .vueperslides__bullets,[data-v-dd1a237a] .vueperslides__bullets{pointer-events:none!important}[data-v-dd1a237a] .vueperslides__parallax-wrapper{height:110px!important}[data-v-d073b1dc] .vueperslides__bullets{pointer-events:none!important}[data-v-d073b1dc] .vueperslides__parallax-wrapper{height:110px!important}
1
+ .gap-16[data-v-3b53a736],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-cd76c125] .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}.editor-actions[data-v-4e2a4adb]{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-25780af6]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-25780af6]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-25780af6]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-df672485]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-df672485]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-df672485]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-df672485]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-df672485]{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-29b9af29] .vueperslides__bullets,[data-v-dd1a237a] .vueperslides__bullets{pointer-events:none!important}[data-v-dd1a237a] .vueperslides__parallax-wrapper{height:110px!important}[data-v-d073b1dc] .vueperslides__bullets{pointer-events:none!important}[data-v-d073b1dc] .vueperslides__parallax-wrapper{height:110px!important}
@@ -1,15 +1,15 @@
1
1
  import { useHttp as d } from "../composables/useHttp.js";
2
2
  import { useToaster as m } from "../composables/useToaster.js";
3
3
  import { MAX_DEFAULT_TEMPLATE_ID as y } from "../enums/defaults.js";
4
- import g from "../static/templates/empty/index.html.js";
5
- import f from "../static/templates/empty/style.css.js";
4
+ import f from "../static/templates/empty/index.html.js";
5
+ import g from "../static/templates/empty/style.css.js";
6
6
  const E = () => {
7
7
  const { get: s, post: c } = d(), { handleError: r } = m();
8
8
  return {
9
9
  getToken: async () => {
10
10
  try {
11
- const t = Number(localStorage.getItem("ins-guido-test-instance")), { data: e } = await s(`/stripo/get-user-token?test=${t}`);
12
- return e.body.token;
11
+ const { data: t } = await s("/stripo/get-user-token");
12
+ return t.body.token;
13
13
  } catch (t) {
14
14
  return r(t, "Failed to fetch token"), "";
15
15
  }
@@ -27,14 +27,14 @@ const E = () => {
27
27
  },
28
28
  getDefaultTemplate: async () => {
29
29
  const t = {
30
- html: g,
31
- css: f
30
+ html: f,
31
+ css: g
32
32
  };
33
33
  try {
34
- const e = new URLSearchParams(window.location.search), u = e.get("default-template"), l = e.get("master"), a = u ? parseInt(u) : 0, i = a >= 1 && a <= y ? a : 0;
35
- if (!i && !l)
34
+ const e = new URLSearchParams(window.location.search), u = e.get("default-template"), p = e.get("master"), a = u ? parseInt(u) : 0, i = a >= 1 && a <= y ? a : 0;
35
+ if (!i && !p)
36
36
  return t;
37
- const p = `/stripo/default-template/${i}`, { data: n } = await s(p), o = typeof n == "string" ? JSON.parse(n) : n;
37
+ const l = `/stripo/default-template/${i}`, { data: n } = await s(l), o = typeof n == "string" ? JSON.parse(n) : n;
38
38
  return !o || typeof o != "object" || !("html" in o) || !("css" in o) ? t : o;
39
39
  } catch (e) {
40
40
  return r(e, "Failed to fetch default template"), t;
@@ -1,14 +1,15 @@
1
- import { useConfig as T } from "../composables/useConfig.js";
2
- import { useHttp as f } from "../composables/useHttp.js";
3
- import { useToaster as w } from "../composables/useToaster.js";
4
- import { useTranslations as b } from "../composables/useTranslations.js";
5
- import { EditorType as h } from "../enums/defaults.js";
6
- import { useRecommendationExtensionStore as C } from "../extensions/Blocks/Recommendation/store/recommendation.js";
7
- import { useSaveAsTemplateStore as v } from "../stores/save-as-template.js";
8
- import { base64EncodeWithSpecialChars as a } from "../utils/base64.js";
9
- import { useTemplatePreparation as S } from "../utils/templatePreparation.js";
10
- const R = () => {
11
- const { get: n, post: c } = f(), { handleError: o, showToaster: i } = w(), { config: l } = T(), p = b();
1
+ import { useConfig as w } from "../composables/useConfig.js";
2
+ import { useHttp as b } from "../composables/useHttp.js";
3
+ import { useToaster as h } from "../composables/useToaster.js";
4
+ import { useTranslations as C } from "../composables/useTranslations.js";
5
+ import { useLiquidValidator as S } from "../composables/validators/useLiquidValidator.js";
6
+ import { EditorType as v } from "../enums/defaults.js";
7
+ import { useRecommendationExtensionStore as N } from "../extensions/Blocks/Recommendation/store/recommendation.js";
8
+ import { useSaveAsTemplateStore as x } from "../stores/save-as-template.js";
9
+ import { base64EncodeWithSpecialChars as r } from "../utils/base64.js";
10
+ import { useTemplatePreparation as A } from "../utils/templatePreparation.js";
11
+ const $ = () => {
12
+ const { get: n, post: m } = b(), { handleError: o, showToaster: l } = h(), { config: c, isFeatureEnabled: p } = w(), { validateLiquidSyntax: g } = S(), u = C();
12
13
  return {
13
14
  getCategories: async () => {
14
15
  try {
@@ -26,7 +27,7 @@ const R = () => {
26
27
  },
27
28
  createCategory: async (e) => {
28
29
  try {
29
- const { data: { id: t } } = await c(
30
+ const { data: { id: t } } = await m(
30
31
  "/newsletter/template-library/create-category",
31
32
  { name: e }
32
33
  );
@@ -36,55 +37,56 @@ const R = () => {
36
37
  }
37
38
  },
38
39
  createTemplate: async () => {
39
- var e, t, g, y;
40
+ var e, t, d, y;
40
41
  try {
41
- const { prepareTemplateDetails: m } = S(), r = v(), s = await m(), u = {
42
- name: r.getTemplateName,
43
- categories: r.getSelectedCategoryIds,
44
- productId: ((t = (e = l.value) == null ? void 0 : e.partner) == null ? void 0 : t.productType) || 0,
45
- editorType: h,
46
- messageType: ((y = (g = l.value) == null ? void 0 : g.partner) == null ? void 0 : y.messageType) || 0,
47
- content: a(s.compiledHtml),
48
- css: a(s.css),
42
+ const { prepareTemplateDetails: i } = A(), s = x(), a = await i();
43
+ if (p("liquidSyntax") && !await g(a.compiledHtml))
44
+ return !1;
45
+ const f = {
46
+ name: s.getTemplateName,
47
+ categories: s.getSelectedCategoryIds,
48
+ productId: ((t = (e = c.value) == null ? void 0 : e.partner) == null ? void 0 : t.productType) || 0,
49
+ editorType: v,
50
+ messageType: ((y = (d = c.value) == null ? void 0 : d.partner) == null ? void 0 : y.messageType) || 0,
51
+ content: r(a.compiledHtml),
52
+ css: r(a.css),
49
53
  unsubscriptionPreferencePageStatus: !1,
50
54
  unsubscriptionPreferencePages: [],
51
- recommendationCampaignUrls: a(
52
- C().recommendationCampaignUrls
55
+ recommendationCampaignUrls: r(
56
+ N().recommendationCampaignUrls
53
57
  ),
54
- recommendationConfigs: a({}),
58
+ recommendationConfigs: r({}),
55
59
  isGuido: !0,
56
- stripoConfig: a({
60
+ // eslint-disable-next-line camelcase
61
+ template_engine: p("liquidSyntax") ? 1 : 0,
62
+ stripoConfig: r({
57
63
  editor: "stripo",
58
- html: s.rawHtml,
59
- css: s.css
64
+ html: a.rawHtml,
65
+ css: a.css
60
66
  })
61
- }, { data: { type: d } } = await c(
67
+ }, { data: { type: T } } = await m(
62
68
  "/newsletter/template-library/create-template",
63
- u
69
+ f
64
70
  );
65
- if (d === "alert") {
66
- i({
67
- message: p(
68
- "newsletter.template-library-save-alert",
69
- { templateName: r.getTemplateName }
70
- ),
71
- type: "alert"
72
- });
73
- return;
74
- }
75
- i({
76
- message: p(
71
+ return T === "alert" ? (l({
72
+ message: u(
73
+ "newsletter.template-library-save-alert",
74
+ { templateName: s.getTemplateName }
75
+ ),
76
+ type: "alert"
77
+ }), !1) : (l({
78
+ message: u(
77
79
  "newsletter.template-library-save-success",
78
- { templateName: r.getTemplateName }
80
+ { templateName: s.getTemplateName }
79
81
  ),
80
82
  type: "success"
81
- });
82
- } catch (m) {
83
- o(m, "Failed to create template");
83
+ }), !0);
84
+ } catch (i) {
85
+ return o(i, "Failed to create template"), !1;
84
86
  }
85
87
  }
86
88
  };
87
89
  };
88
90
  export {
89
- R as useTemplateLibraryApi
91
+ $ as useTemplateLibraryApi
90
92
  };
@@ -26,4 +26,5 @@ export interface CreateTemplateRequest {
26
26
  unsubscriptionPreferencePages: number[];
27
27
  unsubscriptionPreferencePageStatus: boolean;
28
28
  isGuido: boolean;
29
+ template_engine: number;
29
30
  }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Bridges FullStory from the parent window into the Stripo editor iframe.
3
+ *
4
+ * Stripo's iframe CSP allowlists neither inline FS snippets nor the
5
+ * edge.fullstory.com origin, so we: fetch fs.js in the parent context,
6
+ * hand the iframe a blob: URL (blob: is in script-src), and proxy the
7
+ * iframe's fetch through the parent so beacons bypass connect-src.
8
+ */
9
+ export declare const useFullStoryBridge: () => {
10
+ injectFullStory: () => Promise<void>;
11
+ };
@@ -0,0 +1,3 @@
1
+ export declare const useLiquidValidator: () => {
2
+ validateLiquidSyntax: (compiledHtml: string) => Promise<boolean>;
3
+ };
@@ -0,0 +1,2 @@
1
+ import type { CompilerRule } from '@@/Types/html-compiler';
2
+ export declare const liquidCompilerRules: CompilerRule[];
@@ -1,3 +1,5 @@
1
+ export declare const COUPON_PLACEHOLDER_DEFAULT = "{@COUPON_CODE}";
2
+ export declare const COUPON_PLACEHOLDER_LIQUID = "{{ins_coupon_code}}";
1
3
  declare const migrationTemplate = "\n <td\n class=\"coupon-block coupon-block-v2 ins-coupon-code esd-block-text esd-extension-block\"\n esd-extension-block-id=\"coupon-block\"\n >\n <p class=\"ins-title\" contenteditable=\"false\">{@COUPON_CODE}</p>\n </td>\n";
2
4
  export declare function getDefaultTemplate(): string;
3
5
  export default migrationTemplate;
@@ -3,5 +3,5 @@ export declare const useTemplateLibraryApi: () => {
3
3
  getCategories: () => Promise<Category[]>;
4
4
  checkTemplateNameAvailability: (value: string) => Promise<boolean>;
5
5
  createCategory: (category: string) => Promise<string>;
6
- createTemplate: () => Promise<void>;
6
+ createTemplate: () => Promise<boolean>;
7
7
  };
@@ -1,6 +1,6 @@
1
1
  import type { DynamicContent, MergeTag } from '@@/Types/generic';
2
2
  export declare const mergeTagToDynamicContent: (mergeTag: MergeTag) => DynamicContent;
3
- export declare const dynamicContentToMergeTags: (dynamicContentList: DynamicContent[]) => MergeTag[];
3
+ export declare const dynamicContentToMergeTags: (dynamicContentList: DynamicContent[], liquidSyntax?: boolean) => MergeTag[];
4
4
  export declare const getCsrfToken: () => string;
5
5
  /**
6
6
  * URL Parameter utilities
@@ -1,25 +1,47 @@
1
- const f = (t) => {
2
- const n = t.value.match(/\{\{([^}]+)\}\}/)[1].split("|").map((l) => l.trim()), [r] = n, e = {
3
- text: t.label,
4
- value: r || ""
1
+ const s = (e) => {
2
+ const a = e.value.match(/\{\{([^}]+)\}\}/)[1].split("|").map((l) => l.trim()), [n] = a, c = {
3
+ text: e.label,
4
+ value: n || ""
5
5
  };
6
- if (n.length >= 2) {
7
- const [, l, o] = n, c = l.includes("=") ? { key: l.split("=")[0].trim(), value: l.split("=")[1].trim() } : null;
8
- c ? e.format = c : o || (e.fallback = l), o && (e.fallback = o);
6
+ if (a.length >= 2) {
7
+ const [, l, r] = a;
8
+ if (l.startsWith("default:")) {
9
+ let t = l.slice(8).trim();
10
+ t.startsWith('"') && t.endsWith('"') && (t = t.slice(1, -1)), c.fallback = t;
11
+ } else {
12
+ const t = l.includes("=") ? { key: l.split("=")[0].trim(), value: l.split("=")[1].trim() } : null;
13
+ t ? c.format = t : r || (c.fallback = l), r && (c.fallback = r);
14
+ }
9
15
  }
10
- return e;
11
- }, s = (t) => t.map((a) => a.format ? {
12
- label: `${a.text} | ${a.format.key}=${a.format.value}`,
13
- value: `{{${a.value}|${a.format.key}=${a.format.value}}}`
14
- } : {
15
- label: a.fallback ? `${a.text} | ${a.fallback}` : a.text,
16
- value: a.fallback ? `{{${a.value}|${a.fallback}}}` : `{{${a.value}}}`
17
- }), u = () => {
18
- var t;
19
- return ((t = document.head.querySelector('meta[name="csrf-token"]')) == null ? void 0 : t.getAttribute("content")) ?? "";
16
+ return c;
17
+ }, u = (e, f = !1) => e.map((a) => {
18
+ if (a.format)
19
+ return {
20
+ label: `${a.text} | ${a.format.key}=${a.format.value}`,
21
+ value: `{{${a.value}|${a.format.key}=${a.format.value}}}`
22
+ };
23
+ if (f) {
24
+ if (!a.fallback)
25
+ return {
26
+ label: a.text,
27
+ value: `{{ ${a.value} }}`
28
+ };
29
+ const c = !Number.isNaN(Number(a.fallback)) && a.fallback.trim() !== "" ? a.fallback : `"${a.fallback}"`;
30
+ return {
31
+ label: `${a.text} | ${a.fallback}`,
32
+ value: `{{ ${a.value} | default: ${c} }}`
33
+ };
34
+ }
35
+ return {
36
+ label: a.fallback ? `${a.text} | ${a.fallback}` : a.text,
37
+ value: a.fallback ? `{{${a.value}|${a.fallback}}}` : `{{${a.value}}}`
38
+ };
39
+ }), o = () => {
40
+ var e;
41
+ return ((e = document.head.querySelector('meta[name="csrf-token"]')) == null ? void 0 : e.getAttribute("content")) ?? "";
20
42
  };
21
43
  export {
22
- s as dynamicContentToMergeTags,
23
- u as getCsrfToken,
24
- f as mergeTagToDynamicContent
44
+ u as dynamicContentToMergeTags,
45
+ o as getCsrfToken,
46
+ s as mergeTagToDynamicContent
25
47
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useinsider/guido",
3
- "version": "3.2.0-beta.4aabac5",
3
+ "version": "3.2.0-beta.6d12eec",
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",