@useinsider/guido 3.16.0-beta.0faee0c → 3.16.0-beta.1fe8cea

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 (43) hide show
  1. package/dist/components/Guido.vue.js +8 -8
  2. package/dist/components/Guido.vue2.js +78 -76
  3. package/dist/components/organisms/AutoSaveController.vue2.js +9 -8
  4. package/dist/components/organisms/header/EditorActions.vue.js +2 -2
  5. package/dist/components/organisms/header/EditorActions.vue2.js +74 -43
  6. package/dist/components/organisms/header/LeftSlot.vue.js +5 -5
  7. package/dist/components/organisms/header/LeftSlot.vue2.js +46 -23
  8. package/dist/components/organisms/validation/ValidationErrorDrawer.vue.js +20 -0
  9. package/dist/components/organisms/validation/ValidationErrorDrawer.vue2.js +48 -0
  10. package/dist/components/wrappers/WpDrawer.vue.js +9 -7
  11. package/dist/components/wrappers/WpDrawer.vue2.js +1 -1
  12. package/dist/composables/useHtmlValidator.js +1 -0
  13. package/dist/composables/useSave.js +84 -41
  14. package/dist/composables/useSaveValidation.js +276 -0
  15. package/dist/composables/useSaveValidationRollout.js +9 -0
  16. package/dist/composables/useStripo.js +29 -30
  17. package/dist/composables/validators/useCouponBlockValidator.js +24 -21
  18. package/dist/composables/validators/useUnsubscribeBlockValidator.js +34 -27
  19. package/dist/enums/save-validation.js +4 -0
  20. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +31 -24
  21. package/dist/guido.css +1 -1
  22. package/dist/src/@types/save-validation.d.ts +19 -0
  23. package/dist/src/components/Guido.vue.d.ts +17 -1
  24. package/dist/src/components/organisms/header/EditorActions.vue.d.ts +17 -1
  25. package/dist/src/components/organisms/header/HeaderWrapper.vue.d.ts +17 -1
  26. package/dist/src/components/organisms/header/RightSlot.vue.d.ts +17 -1
  27. package/dist/src/components/organisms/validation/ValidationErrorDrawer.vue.d.ts +2 -0
  28. package/dist/src/components/wrappers/WpDrawer.vue.d.ts +4 -3
  29. package/dist/src/composables/useHtmlValidator.d.ts +14 -0
  30. package/dist/src/composables/useSave.d.ts +6 -1
  31. package/dist/src/composables/useSaveValidation.d.ts +6 -0
  32. package/dist/src/composables/useSaveValidationRollout.d.ts +3 -0
  33. package/dist/src/composables/validators/useCouponBlockValidator.d.ts +3 -0
  34. package/dist/src/composables/validators/useUnsubscribeBlockValidator.d.ts +10 -0
  35. package/dist/src/enums/save-validation.d.ts +27 -0
  36. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +5 -0
  37. package/dist/src/stores/config.d.ts +5 -0
  38. package/dist/src/stores/save-validation.d.ts +22 -0
  39. package/dist/src/utils/templatePreparation.d.ts +30 -0
  40. package/dist/stores/config.js +13 -6
  41. package/dist/stores/save-validation.js +30 -0
  42. package/dist/utils/templatePreparation.js +28 -25
  43. package/package.json +1 -1
@@ -0,0 +1,48 @@
1
+ import { defineComponent as m, ref as p, computed as s } from "vue";
2
+ import f from "../../wrappers/WpDrawer.vue.js";
3
+ import { useSave as S } from "../../../composables/useSave.js";
4
+ import { useTranslations as v } from "../../../composables/useTranslations.js";
5
+ import { useConfigStore as g } from "../../../stores/config.js";
6
+ import { useEditorStore as y } from "../../../stores/editor.js";
7
+ import { useSaveValidationStore as _ } from "../../../stores/save-validation.js";
8
+ import { InIcons as C } from "@useinsider/design-system-vue";
9
+ const O = /* @__PURE__ */ m({
10
+ __name: "ValidationErrorDrawer",
11
+ setup(h) {
12
+ const r = v(), t = _(), n = y(), a = g(), { saveWithErrors: i } = S(), o = p(!1), l = s(() => `${r("email-editor.validation-errors")} (${t.errorCount})`), u = s(() => {
13
+ const e = {
14
+ primaryButton: {
15
+ styling: "solid",
16
+ type: "primary",
17
+ labelText: r("email-editor.update-design")
18
+ }
19
+ };
20
+ return !a.isTransactional && t.intent !== "test" && (e.secondaryButton = {
21
+ styling: "solid",
22
+ type: "subtle-primary",
23
+ labelText: r("email-editor.save-and-continue"),
24
+ loadingStatus: o.value
25
+ }), e;
26
+ }), d = s(() => t.errors.map((e) => {
27
+ const c = e.detail ? ` (${e.detail})` : "";
28
+ return `${e.message}${c}`;
29
+ }));
30
+ return { __sfc: !0, trans: r, store: t, editorStore: n, configStore: a, saveWithErrors: i, isSaving: o, titleText: l, footerButtonGroupOptions: u, rows: d, handleClose: () => {
31
+ t.isDrawerOpen && t.close();
32
+ }, handleSaveAndContinue: async () => {
33
+ if (!o.value) {
34
+ o.value = !0, n.loadingStatus = !0;
35
+ try {
36
+ await i() ? t.close() : n.loadingStatus = !1;
37
+ } catch {
38
+ n.loadingStatus = !1;
39
+ } finally {
40
+ o.value = !1;
41
+ }
42
+ }
43
+ }, WpDrawer: f, InIcons: C };
44
+ }
45
+ });
46
+ export {
47
+ O as default
48
+ };
@@ -1,17 +1,19 @@
1
1
  import r from "./WpDrawer.vue2.js";
2
2
  import s from "../../_virtual/_plugin-vue2_normalizer.js";
3
3
  var u = function() {
4
- var t = this, n = t._self._c, e = t._self._setupProxy;
5
- return n(e.InDrawer, { class: t.className, attrs: { id: t.id, "footer-status": "", "close-on-outside-click": t.closeOnOutsideClick, "description-status": t.descriptionStatus, "description-text": t.descriptionText, "footer-button-group-options": t.footerButtonGroupOptions, size: t.size, status: t.status, "title-text": t.titleText }, on: { cancelOrBackButtonEvent: function(o) {
4
+ var t = this, o = t._self._c, e = t._self._setupProxy;
5
+ return o(e.InDrawer, { class: t.className, attrs: { id: t.id, "footer-status": "", "close-on-outside-click": t.closeOnOutsideClick, "description-status": t.descriptionStatus, "description-text": t.descriptionText, "footer-button-group-options": t.footerButtonGroupOptions, size: t.size, status: t.status, "title-text": t.titleText }, on: { cancelOrBackButtonEvent: function(n) {
6
6
  return e.emit("cancelOrBackButtonEvent");
7
- }, onCloseEvent: function(o) {
7
+ }, onCloseEvent: function(n) {
8
8
  return e.emit("onCloseEvent");
9
- }, primaryButtonEvent: function(o) {
9
+ }, primaryButtonEvent: function(n) {
10
10
  return e.emit("primaryButtonEvent");
11
+ }, secondaryButtonEvent: function(n) {
12
+ return e.emit("secondaryButtonEvent");
11
13
  } }, scopedSlots: t._u([t.$slots.headerBottomSlot ? { key: "headerBottomSlot", fn: function() {
12
14
  return [t._t("headerBottomSlot")];
13
15
  }, proxy: !0 } : null, { key: "contentSlot", fn: function() {
14
- return [n("div", [t._t("default")], 2)];
16
+ return [o("div", [t._t("default")], 2)];
15
17
  }, proxy: !0 }], null, !0) });
16
18
  }, i = [], c = /* @__PURE__ */ s(
17
19
  r,
@@ -21,7 +23,7 @@ var u = function() {
21
23
  null,
22
24
  null
23
25
  );
24
- const f = c.exports;
26
+ const p = c.exports;
25
27
  export {
26
- f as default
28
+ p as default
27
29
  };
@@ -13,7 +13,7 @@ const r = /* @__PURE__ */ e({
13
13
  status: { type: Boolean },
14
14
  titleText: null
15
15
  },
16
- emits: ["cancelOrBackButtonEvent", "onCloseEvent", "primaryButtonEvent"],
16
+ emits: ["cancelOrBackButtonEvent", "onCloseEvent", "primaryButtonEvent", "secondaryButtonEvent"],
17
17
  setup(n, { emit: t }) {
18
18
  return { __sfc: !0, emit: t, InDrawer: o };
19
19
  }
@@ -221,6 +221,7 @@ const De = () => {
221
221
  export {
222
222
  de as buildPartnerAttributeNameSet,
223
223
  fe as findInvalidCustomFields,
224
+ pe as getInvalidDynamicContentTags,
224
225
  ue as parseRecommendationVariable,
225
226
  De as useHtmlValidator
226
227
  };
@@ -1,51 +1,94 @@
1
- import { useActionsApi as T } from "./useActionsApi.js";
2
- import { useConfig as k } from "./useConfig.js";
3
- import { useSaveStart as B, useSaveComplete as E } from "./useGuidoActions.js";
4
- import { useSyncModuleExtractor as q } from "./useSyncModuleExtractor.js";
5
- import { ToasterTypeOptions as C } from "../enums/toaster.js";
1
+ import { useActionsApi as h } from "./useActionsApi.js";
2
+ import { useConfig as L } from "./useConfig.js";
3
+ import { useSaveStart as A, useSaveComplete as q } from "./useGuidoActions.js";
4
+ import { useSaveValidation as M } from "./useSaveValidation.js";
5
+ import { useSaveValidationRollout as R } from "./useSaveValidationRollout.js";
6
+ import { useSyncModuleExtractor as O } from "./useSyncModuleExtractor.js";
7
+ import { ToasterTypeOptions as W } from "../enums/toaster.js";
6
8
  import { useStripoApi as D } from "../services/stripoApi.js";
7
- import { useTemplatePreparation as L } from "../utils/templatePreparation.js";
8
- import { useAllowlist as P } from "./useAllowlist.js";
9
- import { useHtmlValidator as U } from "./useHtmlValidator.js";
10
- import { useToaster as A } from "./useToaster.js";
11
- import { useCouponBlockValidator as M } from "./validators/useCouponBlockValidator.js";
12
- import { useLiquidValidator as h } from "./validators/useLiquidValidator.js";
13
- import { useUnsubscribeBlockValidator as F } from "./validators/useUnsubscribeBlockValidator.js";
14
- const $ = () => {
15
- const n = B(), l = E(), { validateHtml: c } = U(), { validateLiquidSyntax: d } = h(), { validateCouponBlockTags: m } = M(), { validateUnsubscribeBlockUniqueness: u, validateUnsubscribeBlockHasTemplate: p } = F(), { callbacks: e, isFeatureEnabled: a } = k(), { extractSyncModuleData: f } = q(), { setSyncModuleUnsubscriptionPages: v } = D(), { editorSave: S } = T(), { showToaster: b } = A(), { getBlockedDomains: w, resolveToast: V } = P();
16
- return { save: async (y = !1, s = !1) => {
17
- var r;
18
- n();
19
- const { prepareTemplateDetails: H } = L(), t = await H();
20
- if (!m(t.compiledHtml) || !u(t.compiledHtml) || !p(t.compiledHtml))
9
+ import { useConfigStore as F } from "../stores/config.js";
10
+ import { useDynamicContentStore as j } from "../stores/dynamic-content.js";
11
+ import { useSaveValidationStore as z } from "../stores/save-validation.js";
12
+ import { useTemplatePreparation as G, getHtmlReferencedUnsubscribePages as I } from "../utils/templatePreparation.js";
13
+ import { useAllowlist as J } from "./useAllowlist.js";
14
+ import { useHtmlValidator as K } from "./useHtmlValidator.js";
15
+ import { useToaster as N } from "./useToaster.js";
16
+ import { useCouponBlockValidator as Q } from "./validators/useCouponBlockValidator.js";
17
+ import { useLiquidValidator as X } from "./validators/useLiquidValidator.js";
18
+ import { useUnsubscribeBlockValidator as Y } from "./validators/useUnsubscribeBlockValidator.js";
19
+ const bt = () => {
20
+ const n = A(), d = q(), { validateHtml: u } = K(), { validateLiquidSyntax: f } = X(), { validateCouponBlockTags: p } = Q(), { validateUnsubscribeBlockUniqueness: v, validateUnsubscribeBlockHasTemplate: y } = Y(), { callbacks: a, isFeatureEnabled: c } = L(), { extractSyncModuleData: S } = O(), { setSyncModuleUnsubscriptionPages: b } = D(), { editorSave: g, getTemplateData: w } = h(), { showToaster: H } = N(), { getBlockedDomains: V, resolveToast: C } = J(), { prepareTemplateDetails: m } = G(), { collectSaveValidationErrors: E } = M(), { isEnabled: x } = R(), k = z(), T = j(), B = F(), r = async (t, e, o) => {
21
+ if (!c("allowlistEnabled"))
22
+ return !1;
23
+ const i = await V(t, e);
24
+ if (!i.length)
25
+ return !1;
26
+ if (!o) {
27
+ const s = await C(i);
28
+ s != null && s.message && H({
29
+ type: W.Warning,
30
+ message: s.message,
31
+ actionButton: s.actionButton
32
+ });
33
+ }
34
+ return !0;
35
+ }, P = async (t) => !p(t.compiledHtml) || !v(t.compiledHtml) || !y(t.compiledHtml) ? !1 : c("liquidSyntax") ? f(t.compiledHtml) : u(t.compiledHtml, t.dynamicContentList, !0), l = async (t, e) => {
36
+ if (!await g())
21
37
  return;
22
- if (a("liquidSyntax")) {
23
- if (!await d(t.compiledHtml))
38
+ const { unsubscribePayload: i, stripoModules: s } = S(t.rawHtml);
39
+ if (await b(i), t.modules = s, !e.suppress) {
40
+ const U = e.blankCompiled ? { compiledHtml: "", ampHtml: "" } : {};
41
+ d({ ...t, ...U, silent: e.silent });
42
+ }
43
+ return t;
44
+ };
45
+ return { save: async (t = !1, e = !1) => {
46
+ var i;
47
+ n();
48
+ const o = await m();
49
+ if (x.value && !t && !e) {
50
+ const s = await E(
51
+ o.compiledHtml,
52
+ o.dynamicContentList
53
+ );
54
+ if (s.length) {
55
+ k.open(s, "save");
24
56
  return;
25
- } else if (!await c(t.compiledHtml, t.dynamicContentList, !0))
57
+ }
58
+ } else if (!await P(o))
26
59
  return;
27
- if ((r = e.value) != null && r.externalValidation && !await e.value.externalValidation(t))
60
+ if (!((i = a.value) != null && i.externalValidation && !await a.value.externalValidation(o)) && !await r(o.compiledHtml, o.css, e))
61
+ return l(o, { silent: e, suppress: t });
62
+ }, saveWithErrors: async () => {
63
+ var e;
64
+ if (B.isTransactional)
28
65
  return;
29
- if (a("allowlistEnabled")) {
30
- const i = await w(t.compiledHtml, t.css);
31
- if (i.length) {
32
- if (!s) {
33
- const o = await V(i);
34
- o != null && o.message && b({
35
- type: C.Warning,
36
- message: o.message,
37
- actionButton: o.actionButton
38
- });
39
- }
40
- return;
41
- }
42
- }
43
- if (!await S())
66
+ n();
67
+ const t = await m();
68
+ if (!((e = a.value) != null && e.externalValidation && !await a.value.externalValidation(t)) && !await r(t.compiledHtml, t.css, !1))
69
+ return l(t, { silent: !1, blankCompiled: !0 });
70
+ }, saveRawOnly: async () => {
71
+ n();
72
+ const { html: t, css: e } = await w();
73
+ if (await r(t, e, !0))
44
74
  return;
45
- const { unsubscribePayload: g, stripoModules: x } = f(t.rawHtml);
46
- return await v(g), t.modules = x, y || l({ ...t, silent: s }), t;
75
+ const o = I(t), i = {
76
+ dynamicContentList: T.getSelectedDynamicContentList,
77
+ compiledHtml: "",
78
+ rawHtml: t,
79
+ css: e,
80
+ ampHtml: "",
81
+ ampErrors: [],
82
+ modules: [],
83
+ recommendation: { campaignUrls: {}, configs: {} },
84
+ unsubscribe: {
85
+ status: o.length > 0,
86
+ config: o
87
+ }
88
+ };
89
+ return l(i, { silent: !0 });
47
90
  } };
48
91
  };
49
92
  export {
50
- $ as useSave
93
+ bt as useSave
51
94
  };
@@ -0,0 +1,276 @@
1
+ import { getIgnoredRecommendationBlockIds as B } from "../config/compiler/utils/recommendationIgnoreUtils.js";
2
+ import { CanNotMakeAnyChangesForRunningKey as k, DISPLAY_CONDITIONS_REGEX as Y, DISPLAY_CONDITIONS_EXCEPTIONS_REGEX as x } from "../enums/html-validator.js";
3
+ import { SaveValidationRule as o } from "../enums/save-validation.js";
4
+ import { ToasterTypeOptions as r } from "../enums/toaster.js";
5
+ import { BLOCK_ROOT_SELECTOR as U } from "../extensions/Blocks/Checkbox/constants/selectors.js";
6
+ import { itemsBlockDynamicVariables as M } from "../extensions/Blocks/Items/enums/productEnums.js";
7
+ import { BLOCK_ROOT_SELECTOR as P } from "../extensions/Blocks/RadioButton/constants/selectors.js";
8
+ import { useRecommendationExtensionStore as W } from "../extensions/Blocks/Recommendation/store/recommendation.js";
9
+ import { RecommendationRequiredFieldsKey as G } from "../extensions/Blocks/Recommendation/validation/requiredFields.js";
10
+ import { useConfigStore as q } from "../stores/config.js";
11
+ import { useDynamicContentStore as H } from "../stores/dynamic-content.js";
12
+ import { useRecommendationStore as V } from "../stores/recommendation.js";
13
+ import { base64EncodeWithSpecialChars as T } from "../utils/base64.js";
14
+ import { useTemplatePreparation as X } from "../utils/templatePreparation.js";
15
+ import { useActionsApi as j } from "./useActionsApi.js";
16
+ import { useConfig as z } from "./useConfig.js";
17
+ import { useHtmlCompiler as $ } from "./useHtmlCompiler.js";
18
+ import { buildPartnerAttributeNameSet as Q, getInvalidDynamicContentTags as Z, findInvalidCustomFields as J } from "./useHtmlValidator.js";
19
+ import { useHttp as tt } from "./useHttp.js";
20
+ import { useTranslations as et } from "./useTranslations.js";
21
+ import { findInvalidCouponBlocks as nt, COUPON_TAG_MODIFIED_KEY as it } from "./validators/useCouponBlockValidator.js";
22
+ import { findDuplicateUnsubPageTypes as ot, countUnsubBlocksWithoutPage as rt, EMPTY_BLOCK_KEY as st } from "./validators/useUnsubscribeBlockValidator.js";
23
+ const at = "newsletter.html-content-is-empty", ct = "custom-fields.missing-closing-braces", lt = "custom-fields.missing-opening-braces", I = "custom-fields.invalid-custom-fields", ut = "newsletter.display-conditions-invalid-syntax", mt = "custom-conditions.wrong-equality-operators", dt = "custom-conditions.missing-if-endif-tag", pt = "custom-conditions.no-space-after-braces", gt = "custom-conditions.no-braces-inside-if-tag", ft = "newsletter.fill-all-necessary-fields", yt = "newsletter.invalid-image-type", Et = "unsubscribe-templates.select-checkbox-groups", It = "unsubscribe-templates.select-radio-button-groups", St = "newsletter.invalid-url-link-for-toaster", F = "journey-builder.liquid-validation-failed", Ct = "/newsletter/template-library/check-template-html-body", _t = /src="[^"]*\.(svg|pst)"/gm, L = /({%(.*?)%})/g, ht = ["if", "endif", "else", "elif", "now"], kt = (e) => !ht.includes(e.toLowerCase()), Tt = (e) => ["if", "endif"].includes(e.toLowerCase());
24
+ function Ft(e) {
25
+ return nt(e).map((i) => ({
26
+ rule: o.CouponTagModified,
27
+ type: r.Warning,
28
+ key: it,
29
+ detail: i
30
+ }));
31
+ }
32
+ function Ot(e) {
33
+ return ot(e).map((i) => ({
34
+ rule: o.DuplicateUnsubBlock,
35
+ type: r.Error,
36
+ key: i.messageKey
37
+ }));
38
+ }
39
+ function Lt(e) {
40
+ return Array.from({ length: rt(e) }, () => ({
41
+ rule: o.UnsubBlockMissingTemplate,
42
+ type: r.Warning,
43
+ key: st
44
+ }));
45
+ }
46
+ function Nt(e, i) {
47
+ const n = e.match(L);
48
+ if (!n)
49
+ return [];
50
+ const a = [];
51
+ return n.forEach((u) => {
52
+ const s = u.slice(2, -2).trim().match(/(".*?"|[^"\s]+)(?=\s*|\s*$)/g);
53
+ if (s && s.length > 0) {
54
+ const [m] = s;
55
+ kt(m) && !i.includes(m) && a.push({
56
+ rule: o.CustomFieldScript,
57
+ type: r.Warning,
58
+ key: I,
59
+ detail: m
60
+ });
61
+ }
62
+ }), a;
63
+ }
64
+ function Rt(e) {
65
+ return e.length > 0 ? [] : [{ rule: o.EmptyHtml, type: r.Warning, key: at }];
66
+ }
67
+ function At(e) {
68
+ const i = (e.match(/{/gm) || []).length, n = (e.match(/}/gm) || []).length;
69
+ return i > n ? [{
70
+ rule: o.MismatchedBraces,
71
+ type: r.Warning,
72
+ key: ct
73
+ }] : i < n ? [{
74
+ rule: o.MismatchedBraces,
75
+ type: r.Warning,
76
+ key: lt
77
+ }] : [];
78
+ }
79
+ function bt(e) {
80
+ return Z(e).map((i) => ({
81
+ rule: o.InvalidDynamicTag,
82
+ type: r.Warning,
83
+ key: I,
84
+ detail: i
85
+ }));
86
+ }
87
+ function Dt(e, i, n, a) {
88
+ const u = [...e.matchAll(/recommendation-id="(\d+)"/g)].map((s) => s[1]);
89
+ return J(e, i, u, n, a).map((s) => ({
90
+ rule: o.InvalidCustomField,
91
+ type: r.Error,
92
+ key: I,
93
+ detail: s
94
+ }));
95
+ }
96
+ function vt(e) {
97
+ const i = e.match(/{%(.*?)%}/g), n = [], a = [];
98
+ if (i && i.forEach((u) => {
99
+ const s = u.match(Y), m = u.match(x), y = (s == null ? void 0 : s.join("")) || "";
100
+ (!s || u !== y) && !m && a.push({
101
+ rule: o.ConditionsSyntax,
102
+ type: r.Error,
103
+ key: ut,
104
+ detail: u
105
+ }), s && s.forEach((g) => {
106
+ g.trim() === "=" && a.push({
107
+ rule: o.WrongEqualityOperator,
108
+ type: r.Error,
109
+ key: mt
110
+ }), (g.match(/^[a-zA-Z]*$/g) ?? []).forEach((f) => {
111
+ Tt(f) && n.push(f);
112
+ });
113
+ });
114
+ }), n.length) {
115
+ const u = n.filter((m) => m === "if").length, s = n.filter((m) => m === "endif").length;
116
+ u !== s && a.push({
117
+ rule: o.MissingIfEndif,
118
+ type: r.Error,
119
+ key: dt
120
+ });
121
+ }
122
+ return a;
123
+ }
124
+ function Kt(e) {
125
+ const i = (e.match(/{% /gm) || []).length, n = (e.match(/ %}/gm) || []).length;
126
+ return i === n ? [] : [{
127
+ rule: o.ConditionTagSpacing,
128
+ type: r.Warning,
129
+ key: pt
130
+ }];
131
+ }
132
+ function wt(e) {
133
+ return (e.match(L) || []).filter((n) => n.includes("if")).map((n) => (n.match(/{{.*}}/gm) || []).length).reduce((n, a) => n + a, 0) === 0 ? [] : [{
134
+ rule: o.BracesInsideIfTag,
135
+ type: r.Warning,
136
+ key: gt
137
+ }];
138
+ }
139
+ function Bt(e) {
140
+ return (e.match(_t) ?? []).map((i) => ({
141
+ rule: o.InvalidImageType,
142
+ type: r.Error,
143
+ key: yt,
144
+ detail: i
145
+ }));
146
+ }
147
+ function O(e, i, n, a) {
148
+ const u = new DOMParser().parseFromString(e, "text/html");
149
+ return Array.from(u.querySelectorAll(i)).filter((s) => {
150
+ var m;
151
+ return !((m = s.id) != null && m.trim());
152
+ }).map(() => ({ rule: n, type: r.Error, key: a }));
153
+ }
154
+ const se = () => {
155
+ const { config: e, isFeatureEnabled: i } = z(), n = et(), { post: a } = tt(), { getCompiledEmail: u, getTemplateData: s } = j(), { compileHtml: m } = $(), { hydrateRecommendationStore: y } = X(), g = H(), f = V(), E = W(), N = q(), R = (t) => ({
156
+ rule: t.rule,
157
+ type: t.type,
158
+ detail: t.detail,
159
+ message: "key" in t ? n(t.key) : t.message
160
+ }), A = async (t) => {
161
+ if (t.size === 0)
162
+ return /* @__PURE__ */ new Set();
163
+ try {
164
+ await E.fetchRecommendationFilters();
165
+ } catch {
166
+ return null;
167
+ }
168
+ return Q(E.filterList);
169
+ }, b = async (t) => {
170
+ try {
171
+ const l = await a(Ct, { html: T(t) }), { status: c, message: d } = l.data, p = [];
172
+ return c || p.push({
173
+ rule: o.InvalidLinks,
174
+ type: r.Error,
175
+ ...c === void 0 ? { message: d } : { key: St }
176
+ }), d === n(k) && p.push({
177
+ rule: o.LinkCheckInProgress,
178
+ type: r.Error,
179
+ key: k
180
+ }), p;
181
+ } catch (l) {
182
+ return console.warn("Link-check collector failed; skipping the link rule.", l), [];
183
+ }
184
+ }, D = async (t) => {
185
+ try {
186
+ const l = await a("/newsletter/contents/validate-syntax", [{
187
+ identifier: "default",
188
+ syntax: "liquid",
189
+ contents: {
190
+ subject: null,
191
+ preheader: null,
192
+ html: T(t),
193
+ ampHtml: null
194
+ }
195
+ }]);
196
+ if (!Array.isArray(l.data)) {
197
+ const d = l.data;
198
+ return [{
199
+ rule: o.LiquidSyntax,
200
+ type: r.Warning,
201
+ message: d.message ?? n(F)
202
+ }];
203
+ }
204
+ const [c] = l.data;
205
+ return Object.values((c == null ? void 0 : c.errors) ?? {}).map((d) => ({
206
+ rule: o.LiquidSyntax,
207
+ type: r.Warning,
208
+ message: d.replace(/^line \d+:\s*/, "")
209
+ }));
210
+ } catch {
211
+ return [{
212
+ rule: o.LiquidSyntax,
213
+ type: r.Error,
214
+ message: n(F)
215
+ }];
216
+ }
217
+ }, v = () => {
218
+ const t = E.invalidBlockIds().map((c) => ({
219
+ rule: o.RecommendationRequiredFields,
220
+ type: r.Error,
221
+ key: G,
222
+ detail: c
223
+ })), l = (f.recommendationConfigs ?? []).filter((c) => c.filters.some((d) => d.value === "")).map(() => ({
224
+ rule: o.RecommendationFilters,
225
+ type: r.Error,
226
+ key: ft
227
+ }));
228
+ return [...t, ...l];
229
+ }, K = async (t, l) => {
230
+ var _, h;
231
+ const c = [
232
+ ...l.map((w) => w.value),
233
+ ...M,
234
+ ...((h = (_ = e.value) == null ? void 0 : _.template) == null ? void 0 : h.customFieldAttributes) ?? []
235
+ ], d = B(t), p = await A(d), { isTransactional: C } = N;
236
+ return [
237
+ ...await b(t),
238
+ ...C ? [] : Nt(t, c),
239
+ ...Rt(t),
240
+ ...At(t),
241
+ ...bt(t),
242
+ ...C ? [] : Dt(t, c, d, p),
243
+ ...vt(t),
244
+ ...Kt(t),
245
+ ...wt(t),
246
+ ...v(),
247
+ ...Bt(t),
248
+ ...O(
249
+ t,
250
+ U,
251
+ o.CheckboxUnsubGroup,
252
+ Et
253
+ ),
254
+ ...O(
255
+ t,
256
+ P,
257
+ o.RadioButtonUnsubGroup,
258
+ It
259
+ )
260
+ ];
261
+ }, S = async (t, l) => [
262
+ ...Ft(t),
263
+ ...Ot(t),
264
+ ...Lt(t),
265
+ ...i("liquidSyntax") ? await D(t) : await K(t, l)
266
+ ].map(R);
267
+ return { collectSaveValidationErrors: S, validateCurrentTemplate: async () => {
268
+ const { html: t } = await s();
269
+ await y(t);
270
+ const { html: l } = await u({ minimize: !0, resetDataSavedFlag: !1 }), { compiledHtml: c } = m(l);
271
+ return S(c, g.getSelectedDynamicContentList);
272
+ } };
273
+ };
274
+ export {
275
+ se as useSaveValidation
276
+ };
@@ -0,0 +1,9 @@
1
+ import { useConfigStore as t } from "../stores/config.js";
2
+ import { computed as o } from "vue";
3
+ const n = ["newsletteruatcamp", "newsletterqacamp"], c = () => {
4
+ const e = t();
5
+ return { isEnabled: o(() => n.includes(e.partnerName)) };
6
+ };
7
+ export {
8
+ c as useSaveValidationRollout
9
+ };
@@ -16,22 +16,22 @@ import { useEditorStore as b } from "../stores/editor.js";
16
16
  import { buildMergeTagEntries as W, flattenDynamicContentList as Y } from "../utils/genericUtil.js";
17
17
  import Z from "../package.json.js";
18
18
  let n = null;
19
- const Ce = () => {
20
- const { features: c, template: u, isFeatureEnabled: m } = q(), { handleError: p, showToaster: k } = G(), { getToken: M, getCustomFonts: T, getSyncModulesStatus: v } = K(), { handleEvent: B } = z(), { handleModuleAdd: F } = j(), { getStripoBlocksConfig: A } = O(), { getStripoNotifications: V } = $(), f = () => n || (n = new Promise((i, s) => {
19
+ const Ct = () => {
20
+ const { features: c, template: u, isFeatureEnabled: m } = q(), { handleError: p, showToaster: k } = G(), { getToken: T, getCustomFonts: v, getSyncModulesStatus: B } = K(), { handleEvent: F } = z(), { handleModuleAdd: M } = j(), { getStripoBlocksConfig: A } = O(), { getStripoNotifications: V } = $(), f = () => n || (n = new Promise((i, s) => {
21
21
  var l;
22
22
  if (document.getElementById("UiEditorScript")) {
23
23
  i();
24
24
  return;
25
25
  }
26
- const o = Z.guido, r = `https://email-static.useinsider.com/guido/${(l = o == null ? void 0 : o.stripo) == null ? void 0 : l.version}/UIEditor.js`, e = document.createElement("script");
27
- e.id = "UiEditorScript", e.type = "module", e.src = r, e.onload = () => i(), e.onerror = () => {
28
- e.remove(), s(new Error(`Failed to load Stripo UIEditor script from S3: ${r}`));
29
- }, document.body.appendChild(e);
26
+ const o = Z.guido, r = `https://email-static.useinsider.com/guido/${(l = o == null ? void 0 : o.stripo) == null ? void 0 : l.version}/UIEditor.js`, t = document.createElement("script");
27
+ t.id = "UiEditorScript", t.type = "module", t.src = r, t.onload = () => i(), t.onerror = () => {
28
+ t.remove(), s(new Error(`Failed to load Stripo UIEditor script from S3: ${r}`));
29
+ }, document.body.appendChild(t);
30
30
  }), n.catch(() => {
31
31
  n = null;
32
32
  }), n), _ = async (i, s, o, a = [], r = !1) => {
33
33
  var y, E, h, C;
34
- const e = b(), { html: l, css: D } = i, { baseBlocks: g, extensions: R } = await A(), S = ((y = c.value) == null ? void 0 : y.displayConditions) ?? !0, P = ((E = c.value) == null ? void 0 : E.modulesDisabled) ?? !1, U = ((h = u.value) == null ? void 0 : h.forceRecreate) ?? !1;
34
+ const t = b(), { html: l, css: D } = i, { baseBlocks: g, extensions: R } = await A(), S = ((y = c.value) == null ? void 0 : y.displayConditions) ?? !0, P = ((E = c.value) == null ? void 0 : E.modulesDisabled) ?? !1, U = ((h = u.value) == null ? void 0 : h.forceRecreate) ?? !1;
35
35
  await window.UIEditor.initEditor(
36
36
  document.querySelector("#guido-editor"),
37
37
  {
@@ -57,7 +57,6 @@ const Ce = () => {
57
57
  messageSettingsEnabled: !0,
58
58
  displayGmailAnnotations: !0,
59
59
  displayHiddenPreheader: !1,
60
- keepModuleStylesEnabled: !0,
61
60
  displayTitle: !1,
62
61
  displayUTM: !1,
63
62
  selectElementAfterDrop: !0,
@@ -78,38 +77,38 @@ const Ce = () => {
78
77
  )
79
78
  }
80
79
  ],
81
- async onTokenRefreshRequest(t) {
80
+ async onTokenRefreshRequest(e) {
82
81
  try {
83
- const d = await M();
84
- t(d);
82
+ const d = await T();
83
+ e(d);
85
84
  } catch (d) {
86
85
  p(d, "Failed to refresh token");
87
86
  }
88
87
  },
89
88
  onTemplateLoaded() {
90
89
  try {
91
- const { importCss: t } = H(), { activateCustomViewStyles: d, updateTimerInClonedTemplate: I } = L(), { injectFullStory: x } = N();
92
- t(), d(), x(), I(), o.onReady(), e.isStripoInitialized = !0, e.loadingStatus = !1, setTimeout(() => {
93
- e.hasChanges = !1;
90
+ const { importCss: e } = H(), { activateCustomViewStyles: d, updateTimerInClonedTemplate: I } = L(), { injectFullStory: x } = N();
91
+ e(), d(), x(), I(), o.onReady(), t.isStripoInitialized = !0, t.loadingStatus = !1, setTimeout(() => {
92
+ t.hasChanges = !1;
94
93
  }, 1e3);
95
- } catch (t) {
96
- p(t, "Failed to load custom interface appearance");
94
+ } catch (e) {
95
+ p(e, "Failed to load custom interface appearance");
97
96
  }
98
97
  },
99
- onCodeEditorVisibilityChanged(t) {
100
- e.isCodeEditorOpen = t;
98
+ onCodeEditorVisibilityChanged(e) {
99
+ t.isCodeEditorOpen = e;
101
100
  },
102
- onEditorVisualModeChanged(t) {
103
- e.editorVisualMode = t.toLowerCase();
101
+ onEditorVisualModeChanged(e) {
102
+ t.editorVisualMode = e.toLowerCase();
104
103
  },
105
- onVersionHistoryVisibilityChanged(t) {
106
- e.isVersionHistoryOpen = t;
104
+ onVersionHistoryVisibilityChanged(e) {
105
+ t.isVersionHistoryOpen = e;
107
106
  },
108
107
  onDataChanged() {
109
- e.hasChanges = !0;
108
+ t.hasChanges = !0;
110
109
  },
111
- onEvent: B,
112
- onModuleAdd: F,
110
+ onEvent: F,
111
+ onModuleAdd: M,
113
112
  notifications: V(),
114
113
  ignoreClickOutsideSelectors: [
115
114
  "#guido-dynamic-content-modal",
@@ -125,11 +124,11 @@ const Ce = () => {
125
124
  const a = b();
126
125
  try {
127
126
  await f();
128
- const [r, e] = await Promise.all([
129
- T(),
130
- v()
127
+ const [r, t] = await Promise.all([
128
+ v(),
129
+ B()
131
130
  ]);
132
- a.syncModulesEnabled = e, await _(i, s, o, r, e);
131
+ a.syncModulesEnabled = t, await _(i, s, o, r, t);
133
132
  } catch {
134
133
  a.loadingStatus = !1, k({
135
134
  type: X.Error,
@@ -146,5 +145,5 @@ const Ce = () => {
146
145
  } };
147
146
  };
148
147
  export {
149
- Ce as useStripo
148
+ Ct as useStripo
150
149
  };