@useinsider/guido 3.19.0-beta.3abc7c5 → 3.19.0-beta.3daecd0
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 +0 -1
- package/dist/@types/config/schemas.js +118 -107
- package/dist/components/Guido.vue.js +9 -9
- package/dist/components/Guido.vue2.js +84 -75
- package/dist/components/organisms/AutoSaveController.vue2.js +8 -9
- package/dist/components/organisms/base/AuthErrorModal.vue.js +18 -0
- package/dist/components/organisms/base/AuthErrorModal.vue2.js +42 -0
- package/dist/components/organisms/header/EditorActions.vue.js +5 -5
- package/dist/components/organisms/header/EditorActions.vue2.js +55 -85
- package/dist/components/organisms/header/LeftSlot.vue.js +5 -5
- package/dist/components/organisms/header/LeftSlot.vue2.js +12 -16
- package/dist/components/wrappers/WpDrawer.vue.js +7 -9
- package/dist/components/wrappers/WpDrawer.vue2.js +1 -1
- package/dist/components/wrappers/WpModal.vue.js +1 -1
- package/dist/components/wrappers/WpModal.vue2.js +4 -3
- package/dist/composables/useAuthError.js +52 -0
- package/dist/composables/useAutoSave.js +11 -11
- package/dist/composables/useCortexBlueprintBridge.js +122 -54
- package/dist/composables/useEmailTemplateApplier.js +111 -50
- package/dist/composables/useHtmlCompiler.js +26 -37
- package/dist/composables/useHtmlValidator.js +0 -2
- package/dist/composables/useHttp.js +64 -54
- package/dist/composables/useLegacyStrategyConversion.js +23 -19
- package/dist/composables/useSave.js +45 -90
- package/dist/composables/useStripo.js +24 -20
- package/dist/composables/useToaster.js +17 -15
- package/dist/composables/validators/useCouponBlockValidator.js +21 -24
- package/dist/composables/validators/useLiquidValidator.js +15 -15
- package/dist/composables/validators/useUnsubscribeBlockValidator.js +27 -34
- package/dist/config/migrator/index.js +14 -13
- package/dist/config/migrator/itemsBlockMigrator.js +236 -248
- package/dist/config/migrator/recommendationMigrator.js +28 -21
- package/dist/config/migrator/recommendationPartnerMigrator.js +56 -0
- package/dist/enums/extensions/recommendationBlock.js +30 -29
- package/dist/extensions/Blocks/Items/block.js +48 -45
- package/dist/extensions/Blocks/Items/constants/cardLayout.js +20 -0
- package/dist/extensions/Blocks/Items/controls/name/trimming.js +18 -17
- package/dist/extensions/Blocks/Items/controls/settingsControl.js +114 -105
- package/dist/extensions/Blocks/Items/enums/productEnums.js +14 -9
- package/dist/extensions/Blocks/Items/layouts/horizontal.html.js +11 -9
- package/dist/extensions/Blocks/Items/template.js +219 -204
- package/dist/extensions/Blocks/Recommendation/block.js +15 -14
- package/dist/extensions/Blocks/Recommendation/controls/main/index.js +45 -38
- package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +72 -49
- package/dist/extensions/Blocks/Recommendation/store/recommendation.js +32 -38
- package/dist/extensions/Blocks/Recommendation/utils/partnerCustomizations.js +3 -1
- package/dist/extensions/Blocks/Recommendation/utils/partnerScope.js +25 -0
- package/dist/guido.css +1 -1
- package/dist/src/@types/config/schemas.d.ts +16 -4
- package/dist/src/components/Guido.vue.d.ts +1 -17
- package/dist/src/components/organisms/header/EditorActions.vue.d.ts +1 -17
- package/dist/src/components/organisms/header/HeaderWrapper.vue.d.ts +1 -17
- package/dist/src/components/organisms/header/RightSlot.vue.d.ts +1 -17
- package/dist/src/components/wrappers/WpDrawer.vue.d.ts +3 -4
- package/dist/src/components/wrappers/WpModal.vue.d.ts +5 -1
- package/dist/src/composables/useAuthError.d.ts +12 -0
- package/dist/src/composables/useConfig.d.ts +2 -2
- package/dist/src/composables/useCortexBlueprintBridge.d.ts +2 -3
- package/dist/src/composables/useEmailTemplateApplier.d.ts +18 -5
- package/dist/src/composables/useGuidoActions.d.ts +2 -0
- package/dist/src/composables/useHtmlValidator.d.ts +0 -21
- package/dist/src/composables/useHttp.d.ts +2 -0
- package/dist/src/composables/useSave.d.ts +1 -6
- package/dist/src/composables/validators/useCouponBlockValidator.d.ts +0 -3
- package/dist/src/composables/validators/useUnsubscribeBlockValidator.d.ts +0 -10
- package/dist/src/config/migrator/index.d.ts +2 -1
- package/dist/src/config/migrator/recommendationPartnerMigrator.d.ts +19 -0
- package/dist/src/enums/extensions/recommendationBlock.d.ts +1 -1
- package/dist/src/extensions/Blocks/Items/constants/cardLayout.d.ts +44 -0
- package/dist/src/extensions/Blocks/Items/enums/productEnums.d.ts +3 -0
- package/dist/src/extensions/Blocks/Items/template.d.ts +19 -0
- package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +0 -5
- package/dist/src/extensions/Blocks/Recommendation/types/nodeConfig.d.ts +6 -0
- package/dist/src/extensions/Blocks/Recommendation/utils/partnerScope.d.ts +33 -0
- package/dist/src/mock/cortexChatStore.d.ts +12 -0
- package/dist/src/stores/config.d.ts +20 -32
- package/dist/src/stores/guido-email-editor.d.ts +20 -10
- package/dist/src/stores/onboarding.d.ts +4 -0
- package/dist/src/stores/recommendation.d.ts +5 -0
- package/dist/src/utils/dateUtil.d.ts +10 -0
- package/dist/src/utils/genericUtil.d.ts +3 -0
- package/dist/src/utils/templatePreparation.d.ts +0 -30
- package/dist/static/styles/components/recommendation-strategy.css.js +9 -0
- package/dist/static/styles/components/version-history.css.js +2 -6
- package/dist/stores/config.js +67 -84
- package/dist/stores/guido-email-editor.js +3 -1
- package/dist/stores/onboarding.js +4 -0
- package/dist/utils/pairProductVariables.js +71 -71
- package/dist/utils/templatePreparation.js +36 -39
- package/package.json +1 -1
- package/dist/components/organisms/validation/ValidationErrorDrawer.vue.js +0 -20
- package/dist/components/organisms/validation/ValidationErrorDrawer.vue2.js +0 -48
- package/dist/composables/useSaveValidation.js +0 -279
- package/dist/composables/useSaveValidationRollout.js +0 -9
- package/dist/enums/save-validation.js +0 -4
- package/dist/src/@types/save-validation.d.ts +0 -19
- package/dist/src/composables/useSaveValidation.d.ts +0 -6
- package/dist/src/composables/useSaveValidationRollout.d.ts +0 -3
- package/dist/src/enums/save-validation.d.ts +0 -27
- package/dist/src/stores/save-validation.d.ts +0 -22
- package/dist/stores/save-validation.js +0 -30
- /package/dist/src/components/organisms/{validation/ValidationErrorDrawer.vue.d.ts → base/AuthErrorModal.vue.d.ts} +0 -0
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import { useActionsApi as
|
|
2
|
-
import { useConfig as
|
|
3
|
-
import { useHtmlCompiler as
|
|
4
|
-
import { RRS_CONFIG_VERSION as
|
|
5
|
-
import { useRecommendationExtensionStore as
|
|
6
|
-
import { mapLegacyStrategy as
|
|
1
|
+
import { useActionsApi as R } from "../composables/useActionsApi.js";
|
|
2
|
+
import { useConfig as k } from "../composables/useConfig.js";
|
|
3
|
+
import { useHtmlCompiler as N } from "../composables/useHtmlCompiler.js";
|
|
4
|
+
import { RRS_CONFIG_VERSION as U, DEFAULT_CURRENCY as m, DEFAULT_NODE_CONFIG as n } from "../extensions/Blocks/Recommendation/constants/defaultConfig.js";
|
|
5
|
+
import { useRecommendationExtensionStore as I } from "../extensions/Blocks/Recommendation/store/recommendation.js";
|
|
6
|
+
import { mapLegacyStrategy as x } from "../extensions/Blocks/Recommendation/utils/legacyStrategyMap.js";
|
|
7
7
|
import { DATA_ATTRIBUTES as A } from "../extensions/Blocks/Unsubscribe/utils/constants.js";
|
|
8
|
-
import { parsePageList as
|
|
9
|
-
import { useDynamicContentStore as
|
|
10
|
-
import { useEditorStore as
|
|
11
|
-
import { useUnsubscribeStore as
|
|
12
|
-
import { isPlainObject as
|
|
13
|
-
import { assignTrackingIds as
|
|
14
|
-
function
|
|
8
|
+
import { parsePageList as L } from "../extensions/Blocks/Unsubscribe/utils/utils.js";
|
|
9
|
+
import { useDynamicContentStore as z } from "../stores/dynamic-content.js";
|
|
10
|
+
import { useEditorStore as O } from "../stores/editor.js";
|
|
11
|
+
import { useUnsubscribeStore as _ } from "../stores/unsubscribe.js";
|
|
12
|
+
import { isPlainObject as v } from "./genericUtil.js";
|
|
13
|
+
import { assignTrackingIds as B } from "./linkTrackingIds.js";
|
|
14
|
+
function G(l) {
|
|
15
15
|
const i = new DOMParser().parseFromString(l, "text/html").querySelectorAll(`[${A.PAGE_LIST}]`), t = [];
|
|
16
|
-
return i.forEach((
|
|
17
|
-
const r =
|
|
18
|
-
r && t.push(...
|
|
16
|
+
return i.forEach((s) => {
|
|
17
|
+
const r = s.getAttribute(A.PAGE_LIST);
|
|
18
|
+
r && t.push(...L(r));
|
|
19
19
|
}), [...new Set(t)];
|
|
20
20
|
}
|
|
21
|
-
async function
|
|
21
|
+
async function M(l) {
|
|
22
22
|
const a = new DOMParser().parseFromString(l, "text/html").querySelectorAll(".recommendation-block-v2");
|
|
23
23
|
if (a.length === 0)
|
|
24
24
|
return;
|
|
25
|
-
const i =
|
|
25
|
+
const i = I();
|
|
26
26
|
a.forEach((t) => {
|
|
27
|
-
var d, g, f,
|
|
28
|
-
const
|
|
27
|
+
var d, g, f, c, y, S;
|
|
28
|
+
const s = t.getAttribute("recommendation-id"), r = s ? Number(s) : NaN;
|
|
29
29
|
if (!Number.isFinite(r))
|
|
30
30
|
return;
|
|
31
31
|
const p = t.getAttribute("esd-ext-config");
|
|
@@ -37,13 +37,13 @@ async function I(l) {
|
|
|
37
37
|
} catch {
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
|
-
if (!
|
|
40
|
+
if (!v(e))
|
|
41
41
|
return;
|
|
42
|
-
const C = !!e.strategyId || (e.configVersion ?? 0) >=
|
|
42
|
+
const C = !!e.strategyId || (e.configVersion ?? 0) >= U, o = {
|
|
43
43
|
// Normalize legacy strategy keys (e.g. `mostViewed` → `mostPopular`) so
|
|
44
44
|
// already-saved blocks that never re-run the migrator don't emit a
|
|
45
45
|
// strategy-less campaign URL. `||` also catches '' / undefined (SD-144882).
|
|
46
|
-
strategy:
|
|
46
|
+
strategy: x(e.strategy) || (C ? "" : n.strategy),
|
|
47
47
|
strategyId: e.strategyId ?? n.strategyId,
|
|
48
48
|
language: e.language ?? n.language,
|
|
49
49
|
size: e.size ?? n.size,
|
|
@@ -55,7 +55,7 @@ async function I(l) {
|
|
|
55
55
|
currencyCode: ((d = e.currency) == null ? void 0 : d.code) ?? m.code,
|
|
56
56
|
currencySymbol: ((g = e.currency) == null ? void 0 : g.symbol) ?? m.symbol,
|
|
57
57
|
currencyAlignment: ((f = e.currency) == null ? void 0 : f.alignment) ?? m.alignment,
|
|
58
|
-
currencyDecimalCount: ((
|
|
58
|
+
currencyDecimalCount: ((c = e.currency) == null ? void 0 : c.decimalCount) ?? m.decimalCount,
|
|
59
59
|
currencyDecimalSeparator: ((y = e.currency) == null ? void 0 : y.decimalSeparator) ?? m.decimalSeparator,
|
|
60
60
|
currencyThousandSeparator: ((S = e.currency) == null ? void 0 : S.thousandSeparator) ?? m.thousandSeparator
|
|
61
61
|
};
|
|
@@ -71,39 +71,39 @@ async function I(l) {
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
const re = () => {
|
|
74
|
-
const l =
|
|
74
|
+
const l = z(), u = O(), a = _(), { getCompiledEmail: i, getTemplateData: t, updateHtmlAndCss: s } = R(), { compileHtml: r, compileAmpHtml: p } = N(), { isFeatureEnabled: e } = k();
|
|
75
75
|
return {
|
|
76
76
|
prepareTemplateDetails: async () => {
|
|
77
77
|
let { html: o, css: d, syncModulesIds: g = [] } = await t();
|
|
78
78
|
if (e("linkTrackingIds"))
|
|
79
79
|
try {
|
|
80
|
-
const { html: b, changed:
|
|
81
|
-
u.trackIdSessionFloor = H,
|
|
80
|
+
const { html: b, changed: F, nextSeq: H } = B(o, u.trackIdSessionFloor);
|
|
81
|
+
u.trackIdSessionFloor = H, F && (o = b, await s(b, d));
|
|
82
82
|
} catch (b) {
|
|
83
83
|
console.error("Tracking-id step failed, saving anyway:", b);
|
|
84
84
|
}
|
|
85
|
-
const { html: f, ampHtml:
|
|
85
|
+
const { html: f, ampHtml: c = "", ampErrors: y = [] } = await i({
|
|
86
86
|
minimize: !0,
|
|
87
87
|
resetDataSavedFlag: !1
|
|
88
88
|
});
|
|
89
|
-
a.selectedUnsubscribePages.length && await a.fetchTemplates(), await
|
|
90
|
-
const { compiledHtml: S, stats: h, appliedRules:
|
|
89
|
+
a.selectedUnsubscribePages.length && await a.fetchTemplates(), await M(o);
|
|
90
|
+
const { compiledHtml: S, stats: h, appliedRules: w } = r(f), D = c && p(c).compiledHtml, E = l.getSelectedDynamicContentList, P = I(), T = G(o);
|
|
91
91
|
return console.debug("HTML Compilation Stats:", {
|
|
92
92
|
originalSize: h.originalSize,
|
|
93
93
|
compiledSize: h.compiledSize,
|
|
94
94
|
reduction: `${h.reductionPercentage.toFixed(2)}%`,
|
|
95
|
-
appliedRules:
|
|
95
|
+
appliedRules: w,
|
|
96
96
|
executionTime: `${h.executionTime.toFixed(2)}ms`
|
|
97
97
|
}), {
|
|
98
|
-
dynamicContentList:
|
|
98
|
+
dynamicContentList: E,
|
|
99
99
|
compiledHtml: S,
|
|
100
100
|
rawHtml: o,
|
|
101
101
|
css: d,
|
|
102
|
-
ampHtml:
|
|
102
|
+
ampHtml: D,
|
|
103
103
|
ampErrors: y,
|
|
104
104
|
modules: g.map(Number),
|
|
105
105
|
recommendation: {
|
|
106
|
-
campaignUrls:
|
|
106
|
+
campaignUrls: P.recommendationCampaignUrls,
|
|
107
107
|
configs: {}
|
|
108
108
|
},
|
|
109
109
|
unsubscribe: {
|
|
@@ -111,13 +111,10 @@ const re = () => {
|
|
|
111
111
|
config: T
|
|
112
112
|
}
|
|
113
113
|
};
|
|
114
|
-
}
|
|
115
|
-
// Exposed so the back/test validate-only path can seed the reco store the
|
|
116
|
-
// same way a full save does (required-field findings depend on it).
|
|
117
|
-
hydrateRecommendationStore: I
|
|
114
|
+
}
|
|
118
115
|
};
|
|
119
116
|
};
|
|
120
117
|
export {
|
|
121
|
-
|
|
118
|
+
G as getHtmlReferencedUnsubscribePages,
|
|
122
119
|
re as useTemplatePreparation
|
|
123
120
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@useinsider/guido",
|
|
3
|
-
"version": "3.19.0-beta.
|
|
3
|
+
"version": "3.19.0-beta.3daecd0",
|
|
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",
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import a from "./ValidationErrorDrawer.vue2.js";
|
|
2
|
-
/* empty css */
|
|
3
|
-
import s from "../../../_virtual/_plugin-vue2_normalizer.js";
|
|
4
|
-
var i = function() {
|
|
5
|
-
var r = this, o = r._self._c, t = r._self._setupProxy;
|
|
6
|
-
return o(t.WpDrawer, { attrs: { id: "guido__validation-error-drawer", size: "small", "footer-button-group-options": t.footerButtonGroupOptions, status: t.store.isDrawerOpen, "title-text": t.titleText }, on: { onCloseEvent: t.handleClose, primaryButtonEvent: t.handleClose, secondaryButtonEvent: t.handleSaveAndContinue } }, [o("div", { staticClass: "d-f f-d-c validation-error-list" }, r._l(t.rows, function(e, n) {
|
|
7
|
-
return o("div", { key: n, staticClass: "d-f a-i-c validation-error-row" }, [o(t.InIcons, { staticClass: "validation-error-row__icon i-c-12", attrs: { name: "filled-caution-triangle" } }), o("span", { staticClass: "validation-error-row__text" }, [r._v(r._s(e))])], 1);
|
|
8
|
-
}), 0)]);
|
|
9
|
-
}, l = [], _ = /* @__PURE__ */ s(
|
|
10
|
-
a,
|
|
11
|
-
i,
|
|
12
|
-
l,
|
|
13
|
-
!1,
|
|
14
|
-
null,
|
|
15
|
-
"30d2e1f9"
|
|
16
|
-
);
|
|
17
|
-
const p = _.exports;
|
|
18
|
-
export {
|
|
19
|
-
p as default
|
|
20
|
-
};
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { defineComponent as m, ref as p, computed as a } 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 h } from "../../../stores/save-validation.js";
|
|
8
|
-
import { InIcons as w } from "@useinsider/design-system-vue";
|
|
9
|
-
const I = /* @__PURE__ */ m({
|
|
10
|
-
__name: "ValidationErrorDrawer",
|
|
11
|
-
setup(_) {
|
|
12
|
-
const r = v(), e = h(), n = y(), s = g(), { saveWithErrors: i } = S(), o = p(!1), l = a(() => `${r("email-editor.validation-errors")} (${e.errorCount})`), u = a(() => {
|
|
13
|
-
const t = {
|
|
14
|
-
primaryButton: {
|
|
15
|
-
styling: "solid",
|
|
16
|
-
type: "primary",
|
|
17
|
-
labelText: r("email-editor.update-design")
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
return s.allowSaveWithErrors && e.intent !== "test" && (t.secondaryButton = {
|
|
21
|
-
styling: "solid",
|
|
22
|
-
type: "subtle-primary",
|
|
23
|
-
labelText: r("email-editor.save-and-continue"),
|
|
24
|
-
loadingStatus: o.value
|
|
25
|
-
}), t;
|
|
26
|
-
}), d = a(() => e.errors.map((t) => {
|
|
27
|
-
const c = t.detail ? ` (${t.detail})` : "";
|
|
28
|
-
return `${t.message}${c}`;
|
|
29
|
-
}));
|
|
30
|
-
return { __sfc: !0, trans: r, store: e, editorStore: n, configStore: s, saveWithErrors: i, isSaving: o, titleText: l, footerButtonGroupOptions: u, rows: d, handleClose: () => {
|
|
31
|
-
e.isDrawerOpen && e.close();
|
|
32
|
-
}, handleSaveAndContinue: async () => {
|
|
33
|
-
if (!o.value) {
|
|
34
|
-
o.value = !0, n.loadingStatus = !0;
|
|
35
|
-
try {
|
|
36
|
-
await i() ? e.close() : n.loadingStatus = !1;
|
|
37
|
-
} catch (t) {
|
|
38
|
-
console.warn("Soft-save failed; keeping the drawer open.", t), n.loadingStatus = !1;
|
|
39
|
-
} finally {
|
|
40
|
-
o.value = !1;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}, WpDrawer: f, InIcons: w };
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
export {
|
|
47
|
-
I as default
|
|
48
|
-
};
|
|
@@ -1,279 +0,0 @@
|
|
|
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, getRecommendationBlockIds as J, findInvalidCustomFields as tt } from "./useHtmlValidator.js";
|
|
19
|
-
import { useHttp as et } from "./useHttp.js";
|
|
20
|
-
import { useTranslations as nt } from "./useTranslations.js";
|
|
21
|
-
import { findInvalidCouponBlocks as it, COUPON_TAG_MODIFIED_KEY as ot } from "./validators/useCouponBlockValidator.js";
|
|
22
|
-
import { findDuplicateUnsubPageTypes as rt, countUnsubBlocksWithoutPage as st, EMPTY_BLOCK_KEY as at } from "./validators/useUnsubscribeBlockValidator.js";
|
|
23
|
-
const ct = "newsletter.html-content-is-empty", lt = "custom-fields.missing-closing-braces", ut = "custom-fields.missing-opening-braces", I = "custom-fields.invalid-custom-fields", mt = "newsletter.display-conditions-invalid-syntax", dt = "custom-conditions.wrong-equality-operators", pt = "custom-conditions.missing-if-endif-tag", gt = "custom-conditions.no-space-after-braces", ft = "custom-conditions.no-braces-inside-if-tag", yt = "newsletter.fill-all-necessary-fields", Et = "newsletter.invalid-image-type", It = "unsubscribe-templates.select-checkbox-groups", St = "unsubscribe-templates.select-radio-button-groups", Ct = "newsletter.invalid-url-link-for-toaster", F = "journey-builder.liquid-validation-failed", _t = "/newsletter/template-library/check-template-html-body", ht = /src="[^"]*\.(svg|pst)"/gm, R = /({%(.*?)%})/g, kt = ["if", "endif", "else", "elif", "now"], Tt = (e) => !kt.includes(e.toLowerCase()), Ft = (e) => ["if", "endif"].includes(e.toLowerCase());
|
|
24
|
-
function Ot(e) {
|
|
25
|
-
return it(e).map((i) => ({
|
|
26
|
-
rule: o.CouponTagModified,
|
|
27
|
-
type: r.Warning,
|
|
28
|
-
key: ot,
|
|
29
|
-
detail: i
|
|
30
|
-
}));
|
|
31
|
-
}
|
|
32
|
-
function Rt(e) {
|
|
33
|
-
return rt(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: st(e) }, () => ({
|
|
41
|
-
rule: o.UnsubBlockMissingTemplate,
|
|
42
|
-
type: r.Warning,
|
|
43
|
-
key: at
|
|
44
|
-
}));
|
|
45
|
-
}
|
|
46
|
-
function Nt(e, i) {
|
|
47
|
-
const n = e.match(R);
|
|
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
|
-
Tt(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 bt(e) {
|
|
65
|
-
return e.length > 0 ? [] : [{ rule: o.EmptyHtml, type: r.Warning, key: ct }];
|
|
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: lt
|
|
73
|
-
}] : i < n ? [{
|
|
74
|
-
rule: o.MismatchedBraces,
|
|
75
|
-
type: r.Warning,
|
|
76
|
-
key: ut
|
|
77
|
-
}] : [];
|
|
78
|
-
}
|
|
79
|
-
function Dt(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 vt(e, i, n, a) {
|
|
88
|
-
const u = J(e);
|
|
89
|
-
return tt(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 Kt(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: mt,
|
|
104
|
-
detail: u
|
|
105
|
-
}), s && s.forEach((g) => {
|
|
106
|
-
g.trim() === "=" && a.push({
|
|
107
|
-
rule: o.WrongEqualityOperator,
|
|
108
|
-
type: r.Error,
|
|
109
|
-
key: dt
|
|
110
|
-
}), (g.match(/^[a-zA-Z]*$/g) ?? []).forEach((f) => {
|
|
111
|
-
Ft(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: pt
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
return a;
|
|
123
|
-
}
|
|
124
|
-
function wt(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: gt
|
|
130
|
-
}];
|
|
131
|
-
}
|
|
132
|
-
function Bt(e) {
|
|
133
|
-
return (e.match(R) || []).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: ft
|
|
137
|
-
}];
|
|
138
|
-
}
|
|
139
|
-
function Yt(e) {
|
|
140
|
-
return (e.match(ht) ?? []).map((i) => ({
|
|
141
|
-
rule: o.InvalidImageType,
|
|
142
|
-
type: r.Error,
|
|
143
|
-
key: Et,
|
|
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 ae = () => {
|
|
155
|
-
const { config: e, isFeatureEnabled: i } = z(), n = nt(), { post: a } = et(), { getCompiledEmail: u, getTemplateData: s } = j(), { compileHtml: m } = $(), { hydrateRecommendationStore: y } = X(), g = H(), f = V(), E = W(), L = q(), N = (t) => ({
|
|
156
|
-
rule: t.rule,
|
|
157
|
-
type: t.type,
|
|
158
|
-
detail: t.detail,
|
|
159
|
-
message: "key" in t ? n(t.key) : t.message
|
|
160
|
-
}), b = 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
|
-
}, A = async (t) => {
|
|
170
|
-
try {
|
|
171
|
-
const l = await a(_t, { html: T(t) }), { status: c, message: d } = l.data, p = [];
|
|
172
|
-
return c || p.push({
|
|
173
|
-
rule: o.InvalidLinks,
|
|
174
|
-
type: r.Error,
|
|
175
|
-
// status===undefined means a bare message instead of a boolean; surface it,
|
|
176
|
-
// but fall back to the canned key when it's missing so a malformed body
|
|
177
|
-
// never renders a literal 'undefined' row (SD-147430).
|
|
178
|
-
...c === void 0 && d ? { message: d } : { key: Ct }
|
|
179
|
-
}), d === n(k) && p.push({
|
|
180
|
-
rule: o.LinkCheckInProgress,
|
|
181
|
-
type: r.Error,
|
|
182
|
-
key: k
|
|
183
|
-
}), p;
|
|
184
|
-
} catch (l) {
|
|
185
|
-
return console.warn("Link-check collector failed; skipping the link rule.", l), [];
|
|
186
|
-
}
|
|
187
|
-
}, D = async (t) => {
|
|
188
|
-
try {
|
|
189
|
-
const l = await a("/newsletter/contents/validate-syntax", [{
|
|
190
|
-
identifier: "default",
|
|
191
|
-
syntax: "liquid",
|
|
192
|
-
contents: {
|
|
193
|
-
subject: null,
|
|
194
|
-
preheader: null,
|
|
195
|
-
html: T(t),
|
|
196
|
-
ampHtml: null
|
|
197
|
-
}
|
|
198
|
-
}]);
|
|
199
|
-
if (!Array.isArray(l.data)) {
|
|
200
|
-
const d = l.data;
|
|
201
|
-
return [{
|
|
202
|
-
rule: o.LiquidSyntax,
|
|
203
|
-
type: r.Warning,
|
|
204
|
-
message: d.message ?? n(F)
|
|
205
|
-
}];
|
|
206
|
-
}
|
|
207
|
-
const [c] = l.data;
|
|
208
|
-
return Object.values((c == null ? void 0 : c.errors) ?? {}).map((d) => ({
|
|
209
|
-
rule: o.LiquidSyntax,
|
|
210
|
-
type: r.Warning,
|
|
211
|
-
message: d.replace(/^line \d+:\s*/, "")
|
|
212
|
-
}));
|
|
213
|
-
} catch {
|
|
214
|
-
return [{
|
|
215
|
-
rule: o.LiquidSyntax,
|
|
216
|
-
type: r.Error,
|
|
217
|
-
message: n(F)
|
|
218
|
-
}];
|
|
219
|
-
}
|
|
220
|
-
}, v = () => {
|
|
221
|
-
const t = E.invalidBlockIds().map((c) => ({
|
|
222
|
-
rule: o.RecommendationRequiredFields,
|
|
223
|
-
type: r.Error,
|
|
224
|
-
key: G,
|
|
225
|
-
detail: c
|
|
226
|
-
})), l = (f.recommendationConfigs ?? []).filter((c) => c.filters.some((d) => d.value === "")).map(() => ({
|
|
227
|
-
rule: o.RecommendationFilters,
|
|
228
|
-
type: r.Error,
|
|
229
|
-
key: yt
|
|
230
|
-
}));
|
|
231
|
-
return [...t, ...l];
|
|
232
|
-
}, K = async (t, l) => {
|
|
233
|
-
var _, h;
|
|
234
|
-
const c = [
|
|
235
|
-
...l.map((w) => w.value),
|
|
236
|
-
...M,
|
|
237
|
-
...((h = (_ = e.value) == null ? void 0 : _.template) == null ? void 0 : h.customFieldAttributes) ?? []
|
|
238
|
-
], d = B(t), p = await b(d), { isTransactional: C } = L;
|
|
239
|
-
return [
|
|
240
|
-
...await A(t),
|
|
241
|
-
...C ? [] : Nt(t, c),
|
|
242
|
-
...bt(t),
|
|
243
|
-
...At(t),
|
|
244
|
-
...Dt(t),
|
|
245
|
-
...C ? [] : vt(t, c, d, p),
|
|
246
|
-
...Kt(t),
|
|
247
|
-
...wt(t),
|
|
248
|
-
...Bt(t),
|
|
249
|
-
...v(),
|
|
250
|
-
...Yt(t),
|
|
251
|
-
...O(
|
|
252
|
-
t,
|
|
253
|
-
U,
|
|
254
|
-
o.CheckboxUnsubGroup,
|
|
255
|
-
It
|
|
256
|
-
),
|
|
257
|
-
...O(
|
|
258
|
-
t,
|
|
259
|
-
P,
|
|
260
|
-
o.RadioButtonUnsubGroup,
|
|
261
|
-
St
|
|
262
|
-
)
|
|
263
|
-
];
|
|
264
|
-
}, S = async (t, l) => [
|
|
265
|
-
...Ot(t),
|
|
266
|
-
...Rt(t),
|
|
267
|
-
...Lt(t),
|
|
268
|
-
...i("liquidSyntax") ? await D(t) : await K(t, l)
|
|
269
|
-
].map(N);
|
|
270
|
-
return { collectSaveValidationErrors: S, validateCurrentTemplate: async () => {
|
|
271
|
-
const { html: t } = await s();
|
|
272
|
-
await y(t);
|
|
273
|
-
const { html: l } = await u({ minimize: !0, resetDataSavedFlag: !1 }), { compiledHtml: c } = m(l);
|
|
274
|
-
return S(c, g.getSelectedDynamicContentList);
|
|
275
|
-
} };
|
|
276
|
-
};
|
|
277
|
-
export {
|
|
278
|
-
ae as useSaveValidation
|
|
279
|
-
};
|
|
@@ -1,9 +0,0 @@
|
|
|
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
|
-
};
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
var n = /* @__PURE__ */ ((s) => (s.CouponTagModified = "coupon-tag-modified", s.DuplicateUnsubBlock = "duplicate-unsub-block", s.UnsubBlockMissingTemplate = "unsub-block-missing-template", s.LiquidSyntax = "liquid-syntax", s.InvalidLinks = "invalid-links", s.LinkCheckInProgress = "link-check-in-progress", s.CustomFieldScript = "custom-field-script", s.EmptyHtml = "empty-html", s.MismatchedBraces = "mismatched-braces", s.InvalidDynamicTag = "invalid-dynamic-tag", s.InvalidCustomField = "invalid-custom-field", s.ConditionsSyntax = "conditions-syntax", s.WrongEqualityOperator = "wrong-equality-operator", s.MissingIfEndif = "missing-if-endif", s.ConditionTagSpacing = "condition-tag-spacing", s.BracesInsideIfTag = "braces-inside-if-tag", s.RecommendationRequiredFields = "recommendation-required-fields", s.RecommendationFilters = "recommendation-filters", s.InvalidImageType = "invalid-image-type", s.CheckboxUnsubGroup = "checkbox-unsub-group", s.RadioButtonUnsubGroup = "radio-button-unsub-group", s))(n || {});
|
|
2
|
-
export {
|
|
3
|
-
n as SaveValidationRule
|
|
4
|
-
};
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { SaveValidationRule } from '@@/Enums/save-validation';
|
|
2
|
-
import type { ToasterTypeOptions } from '@@/Enums/toaster';
|
|
3
|
-
/** Which action triggered the validation run. Drives telemetry only in v1. */
|
|
4
|
-
export type SaveValidationIntent = 'save' | 'back' | 'test';
|
|
5
|
-
/**
|
|
6
|
-
* A single validation failure instance, one per drawer row. Names avoid the
|
|
7
|
-
* public `ValidationError` (config validation) collision — NOT exported from
|
|
8
|
-
* library.ts.
|
|
9
|
-
*/
|
|
10
|
-
export interface SaveValidationError {
|
|
11
|
-
/** Stable discriminator for tests and de-duplication. */
|
|
12
|
-
rule: SaveValidationRule;
|
|
13
|
-
/** Final translated string — trans() is applied at collect time. */
|
|
14
|
-
message: string;
|
|
15
|
-
/** Raw user content (field name / tag / src) — not i18n. */
|
|
16
|
-
detail?: string;
|
|
17
|
-
/** Mirrors the legacy toaster severity. Kept for the discriminator/tests; the drawer renders a uniform icon and never reads it. */
|
|
18
|
-
type: ToasterTypeOptions;
|
|
19
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { DynamicContent } from '@@/Types/generic';
|
|
2
|
-
import type { SaveValidationError } from '@@/Types/save-validation';
|
|
3
|
-
export declare const useSaveValidation: () => {
|
|
4
|
-
collectSaveValidationErrors: (compiledHtml: string, dynamicContentList: DynamicContent[]) => Promise<SaveValidationError[]>;
|
|
5
|
-
validateCurrentTemplate: () => Promise<SaveValidationError[]>;
|
|
6
|
-
};
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Stable discriminators for each save-validation rule site — one per rule that
|
|
3
|
-
* can produce a drawer row, kept in sync with the collector + legacy validator chains.
|
|
4
|
-
*/
|
|
5
|
-
export declare enum SaveValidationRule {
|
|
6
|
-
CouponTagModified = "coupon-tag-modified",
|
|
7
|
-
DuplicateUnsubBlock = "duplicate-unsub-block",
|
|
8
|
-
UnsubBlockMissingTemplate = "unsub-block-missing-template",
|
|
9
|
-
LiquidSyntax = "liquid-syntax",
|
|
10
|
-
InvalidLinks = "invalid-links",
|
|
11
|
-
LinkCheckInProgress = "link-check-in-progress",
|
|
12
|
-
CustomFieldScript = "custom-field-script",
|
|
13
|
-
EmptyHtml = "empty-html",
|
|
14
|
-
MismatchedBraces = "mismatched-braces",
|
|
15
|
-
InvalidDynamicTag = "invalid-dynamic-tag",
|
|
16
|
-
InvalidCustomField = "invalid-custom-field",
|
|
17
|
-
ConditionsSyntax = "conditions-syntax",
|
|
18
|
-
WrongEqualityOperator = "wrong-equality-operator",
|
|
19
|
-
MissingIfEndif = "missing-if-endif",
|
|
20
|
-
ConditionTagSpacing = "condition-tag-spacing",
|
|
21
|
-
BracesInsideIfTag = "braces-inside-if-tag",
|
|
22
|
-
RecommendationRequiredFields = "recommendation-required-fields",
|
|
23
|
-
RecommendationFilters = "recommendation-filters",
|
|
24
|
-
InvalidImageType = "invalid-image-type",
|
|
25
|
-
CheckboxUnsubGroup = "checkbox-unsub-group",
|
|
26
|
-
RadioButtonUnsubGroup = "radio-button-unsub-group"
|
|
27
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { SaveValidationError, SaveValidationIntent } from '@@/Types/save-validation';
|
|
2
|
-
interface SaveValidationState {
|
|
3
|
-
errors: SaveValidationError[];
|
|
4
|
-
isDrawerOpen: boolean;
|
|
5
|
-
intent: SaveValidationIntent | null;
|
|
6
|
-
}
|
|
7
|
-
export declare const useSaveValidationStore: import("pinia").StoreDefinition<"guidoSaveValidation", SaveValidationState, {
|
|
8
|
-
errorCount: (state: {
|
|
9
|
-
errors: {
|
|
10
|
-
rule: import("../enums/save-validation").SaveValidationRule;
|
|
11
|
-
message: string;
|
|
12
|
-
detail?: string | undefined;
|
|
13
|
-
type: import("../enums/toaster").ToasterTypeOptions;
|
|
14
|
-
}[];
|
|
15
|
-
isDrawerOpen: boolean;
|
|
16
|
-
intent: SaveValidationIntent | null;
|
|
17
|
-
} & import("pinia").PiniaCustomStateProperties<SaveValidationState>) => number;
|
|
18
|
-
}, {
|
|
19
|
-
open(errors: SaveValidationError[], intent: SaveValidationIntent): void;
|
|
20
|
-
close(): void;
|
|
21
|
-
}>;
|
|
22
|
-
export {};
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { defineStore as n } from "pinia";
|
|
2
|
-
function i(e) {
|
|
3
|
-
const t = /* @__PURE__ */ new Set();
|
|
4
|
-
return e.filter((r) => {
|
|
5
|
-
const s = JSON.stringify([r.rule, r.message, r.detail ?? ""]);
|
|
6
|
-
return t.has(s) ? !1 : (t.add(s), !0);
|
|
7
|
-
});
|
|
8
|
-
}
|
|
9
|
-
const o = n("guidoSaveValidation", {
|
|
10
|
-
state: () => ({
|
|
11
|
-
errors: [],
|
|
12
|
-
isDrawerOpen: !1,
|
|
13
|
-
intent: null
|
|
14
|
-
}),
|
|
15
|
-
getters: {
|
|
16
|
-
errorCount: (e) => e.errors.length
|
|
17
|
-
},
|
|
18
|
-
actions: {
|
|
19
|
-
open(e, t) {
|
|
20
|
-
this.errors = i(e), this.intent = t, this.isDrawerOpen = !0;
|
|
21
|
-
},
|
|
22
|
-
// Errors are retained so rows don't blank during the ~300ms close animation.
|
|
23
|
-
close() {
|
|
24
|
-
this.isDrawerOpen = !1;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
export {
|
|
29
|
-
o as useSaveValidationStore
|
|
30
|
-
};
|
|
File without changes
|