@useinsider/guido 3.27.0-beta.ee85b86 → 3.27.1-beta.842075e
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 +5 -10
- package/dist/components/Guido.vue.js +7 -7
- package/dist/components/Guido.vue2.js +83 -86
- package/dist/composables/useHtmlCompiler.js +8 -9
- package/dist/composables/useModuleRepair.js +32 -63
- package/dist/composables/useRecommendation.js +8 -16
- package/dist/composables/useStripo.js +43 -44
- package/dist/config/compiler/htmlCompilerRules.js +6 -16
- package/dist/config/compiler/recommendationCompilerRules.js +29 -41
- package/dist/config/migrator/unsubscribeMigrator.js +112 -100
- package/dist/enums/recommendation.js +4 -5
- package/dist/extensions/Blocks/Recommendation/controls/image/index.js +58 -40
- package/dist/extensions/Blocks/Unsubscribe/block.js +104 -96
- package/dist/extensions/Blocks/Unsubscribe/utils/constants.js +4 -3
- package/dist/extensions/Blocks/Unsubscribe/utils/swapMergeTagInHref.js +5 -0
- package/dist/guido.css +1 -1
- package/dist/package.json.js +4 -4
- package/dist/src/@types/generic.d.ts +0 -7
- package/dist/src/composables/useModuleRepair.d.ts +0 -6
- package/dist/src/composables/useRecommendation.d.ts +0 -4
- package/dist/src/enums/recommendation.d.ts +0 -1
- package/dist/src/extensions/Blocks/Recommendation/controls/image/index.d.ts +2 -0
- package/dist/src/extensions/Blocks/Unsubscribe/utils/constants.d.ts +1 -0
- package/dist/src/extensions/Blocks/Unsubscribe/utils/swapMergeTagInHref.d.ts +1 -0
- package/dist/src/utils/dynamicContentConverter.d.ts +18 -20
- package/dist/src/utils/genericUtil.d.ts +8 -4
- package/dist/static/stripo-runtime-manifest.json.js +2 -2
- package/dist/utils/dynamicContentConverter.js +27 -41
- package/dist/utils/genericUtil.js +39 -39
- package/package.json +2 -2
- package/dist/components/organisms/dynamic-content/AmbiguousDynamicContentModal.vue.js +0 -24
- package/dist/components/organisms/dynamic-content/AmbiguousDynamicContentModal.vue2.js +0 -59
- package/dist/composables/useAmbiguousDynamicContent.js +0 -72
- package/dist/enums/dynamic-content.js +0 -4
- package/dist/src/components/organisms/dynamic-content/AmbiguousDynamicContentModal.vue.d.ts +0 -2
- package/dist/src/composables/useAmbiguousDynamicContent.d.ts +0 -7
- package/dist/src/enums/dynamic-content.d.ts +0 -3
- package/dist/src/stores/module-dynamic-content.d.ts +0 -30
- package/dist/src/utils/dynamicContentPendingMarker.d.ts +0 -2
- package/dist/stores/module-dynamic-content.js +0 -20
- package/dist/utils/dynamicContentPendingMarker.js +0 -6
package/README.md
CHANGED
|
@@ -119,8 +119,7 @@ const config: GuidoConfigInput = {
|
|
|
119
119
|
// { [partnerName]: [{ text, value, children }] } (architect is multi-partner).
|
|
120
120
|
// Guido flattens the active (first) partner's leaf attributes and uses them to
|
|
121
121
|
// repair label-form tokens (`{{ Phone Number }}` -> `{{phone_number}}`) in
|
|
122
|
-
// dropped saved modules;
|
|
123
|
-
// modal (see "Saved-module token repair"); an unresolvable token raises a single warning toaster
|
|
122
|
+
// dropped saved modules; an unresolvable token raises a single warning toaster
|
|
124
123
|
// (translation key `dynamic-content.unresolved-attributes-on-drop`, registered
|
|
125
124
|
// host-side). Omit it and the repair is a silent no-op. Default: {}.
|
|
126
125
|
dynamicContentList?: DynamicContentList,
|
|
@@ -692,22 +691,18 @@ const closeModal = () => {
|
|
|
692
691
|
|
|
693
692
|
### Saved-module token repair
|
|
694
693
|
|
|
695
|
-
Legacy
|
|
694
|
+
Legacy **saved modules** may serialize their merge-tag chips by display label
|
|
696
695
|
(`{{ Phone Number }}`) instead of the canonical token (`{{phone_number}}`), which the
|
|
697
696
|
backend can't resolve. When such a module is dropped or copied into the editor, Guido
|
|
698
697
|
repairs these automatically using the `template.dynamicContentList` catalog (see
|
|
699
698
|
[Configuration](#configuration)):
|
|
700
699
|
|
|
701
|
-
- **
|
|
702
|
-
-
|
|
703
|
-
- **Valid tokens are never rewritten**: an exact catalog value, an Items block variable, or an exact entry of `template.customFieldAttributes` (e.g. the host's long-form aliases `name`, `surname`), stays as written — so `{{name | downcase | capitalize}}` survives a drop.
|
|
704
|
-
- **Catalog attributes the module ends up using are registered** for Save's allow-list, the same way the picker registers them, so a repaired or chosen token does not fail Save as an invalid custom field.
|
|
705
|
-
- **Label match with several attributes** (e.g. a bare `Name` shared by a default attribute and a commerce field) is not guessed: the token is left in place and a modal asks the user to pick an attribute per label, showing each option as `category › label`. Applying the choice is one undo step; closing the modal keeps the tokens and shows the warning toaster below. A module whose choice was still open when the design was saved asks again when the design is reopened. Register these keys host-side: `email-editor.ambiguous-dynamic-content-title`, `email-editor.ambiguous-dynamic-content-message` and `email-editor.ambiguous-dynamic-content-apply` (Cancel reuses `action-builder.cancel`).
|
|
706
|
-
- Liquid nested tokens (`coupon.code`), recommendation-block variables (`123_0_price`), allowed system tokens, and `data-*` product tags are left untouched.
|
|
700
|
+
- **Label match** → canonical value: `{{ Phone Number }}` → `{{phone_number}}` (any author `| default:` / format tail is preserved).
|
|
701
|
+
- Already-canonical values, Liquid nested tokens (`coupon.code`), recommendation-block variables (`123_0_price`), allowed system tokens, and `data-*` product tags are left untouched.
|
|
707
702
|
- An **unresolvable** token is left in place and raises a single **warning toaster** (translation key `dynamic-content.unresolved-attributes-on-drop`; register the copy host-side).
|
|
708
703
|
|
|
709
704
|
Pass `template.dynamicContentList` as a **partner-keyed** tree
|
|
710
|
-
(`{ [partnerName]: DynamicContentNode[] }`, where a node is `{ text,
|
|
705
|
+
(`{ [partnerName]: DynamicContentNode[] }`, where a node is `{ text, value, children? }`).
|
|
711
706
|
Guido flattens the **active (first) partner's** leaf attributes. Products that manage
|
|
712
707
|
multiple partners (e.g. architect) should key by partner and place the active partner
|
|
713
708
|
first. Omit the prop and the repair is a safe no-op — nothing is rewritten and no
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import o from "./Guido.vue2.js";
|
|
2
2
|
/* empty css */
|
|
3
3
|
import i from "../_virtual/_plugin-vue2_normalizer.js";
|
|
4
|
-
var
|
|
4
|
+
var s = function() {
|
|
5
5
|
var a = this, r = a._self._c, e = a._self._setupProxy;
|
|
6
|
-
return r("div", { ref: "wrapperRef", staticClass: "guido-editor__wrapper", class: { "guido-editor__no-header": e.noHeader } }, [r(e.HeaderWrapper), r(e.AutoSaveController, { ref: "autoSaveControllerRef" }), e.editorStore.isPreviewModeOpen ? r(e.PreviewContainer) : a._e(), r("div", { directives: [{ name: "show", rawName: "v-show", value: !e.previewStore.isLoaded, expression: "!previewStore.isLoaded" }], staticClass: "guido-editor__container", class: { "guido-editor__no-header": e.noHeader }, attrs: { id: "guido-editor" } }), r(e.Toaster), r(e.AuthErrorModal), r(e.FilterSelectionDrawer), e.isRrsEnabled || e.hasAssignedStrategy ? r(e.AssignStrategyDrawer) : a._e(), e.isRrsEnabled || e.hasAssignedStrategy ? r(e.RemoveStrategyModal) : a._e(), e.isRrsEnabled ? r(e.LegacyStrategyUpdatedModal) : a._e(), e.isLegacyUnsubscribeConversionEnabled ? r(e.LegacyUnsubscribeConvertedModal) : a._e(),
|
|
6
|
+
return r("div", { ref: "wrapperRef", staticClass: "guido-editor__wrapper", class: { "guido-editor__no-header": e.noHeader } }, [r(e.HeaderWrapper), r(e.AutoSaveController, { ref: "autoSaveControllerRef" }), e.editorStore.isPreviewModeOpen ? r(e.PreviewContainer) : a._e(), r("div", { directives: [{ name: "show", rawName: "v-show", value: !e.previewStore.isLoaded, expression: "!previewStore.isLoaded" }], staticClass: "guido-editor__container", class: { "guido-editor__no-header": e.noHeader }, attrs: { id: "guido-editor" } }), r(e.Toaster), r(e.AuthErrorModal), r(e.FilterSelectionDrawer), e.isRrsEnabled || e.hasAssignedStrategy ? r(e.AssignStrategyDrawer) : a._e(), e.isRrsEnabled || e.hasAssignedStrategy ? r(e.RemoveStrategyModal) : a._e(), e.isRrsEnabled ? r(e.LegacyStrategyUpdatedModal) : a._e(), e.isLegacyUnsubscribeConversionEnabled ? r(e.LegacyUnsubscribeConvertedModal) : a._e(), r(e.SaveAsTemplateDrawer), e.isSaveValidationEnabled ? r(e.ValidationErrorDrawer) : a._e(), e.isExternalDisplayConditionsEnabled ? r(e.DisplayConditionsHost) : a._e(), e.isTestPartner() ? a._e() : r(e.OnboardingWrapper, { on: { "onboarding-finished": function(l) {
|
|
7
7
|
return e.emit("onboarding:finished");
|
|
8
8
|
} } }), r(e.UnsubscribeWrapper), r(e.LoadingWrapper)], 1);
|
|
9
|
-
}, t = [],
|
|
9
|
+
}, t = [], n = /* @__PURE__ */ i(
|
|
10
10
|
o,
|
|
11
|
-
|
|
11
|
+
s,
|
|
12
12
|
t,
|
|
13
13
|
!1,
|
|
14
14
|
null,
|
|
15
|
-
"
|
|
15
|
+
"8fc59697"
|
|
16
16
|
);
|
|
17
|
-
const
|
|
17
|
+
const v = n.exports;
|
|
18
18
|
export {
|
|
19
|
-
|
|
19
|
+
v as default
|
|
20
20
|
};
|
|
@@ -1,82 +1,79 @@
|
|
|
1
|
-
import { defineComponent as
|
|
2
|
-
import { useCortexBlueprintBridge as
|
|
3
|
-
import { useEditorLock as
|
|
4
|
-
import { startEditorOpenMetrics as
|
|
5
|
-
import { provideGuidoActions as
|
|
6
|
-
import { useGuidoStateBridge as
|
|
7
|
-
import { usePartner as
|
|
8
|
-
import { useSaveValidationRollout as
|
|
9
|
-
import { useStripo as
|
|
10
|
-
import { useTimerClone as
|
|
11
|
-
import { useToaster as
|
|
12
|
-
import { useTranslations as
|
|
13
|
-
import { migrate as
|
|
14
|
-
import { ModuleFolderDefaults as
|
|
15
|
-
import { RIBBON_SELECTOR as
|
|
16
|
-
import { ToasterTypeOptions as
|
|
17
|
-
import { useRecommendationExtensionStore as z, disposeStrategyPageReturnListeners as
|
|
18
|
-
import { disposeUnsubscribeListeners as
|
|
19
|
-
import { disposeDisplayConditionRequest as
|
|
20
|
-
import
|
|
21
|
-
import
|
|
22
|
-
import
|
|
23
|
-
import
|
|
24
|
-
import
|
|
25
|
-
import
|
|
26
|
-
import
|
|
27
|
-
import
|
|
28
|
-
import
|
|
29
|
-
import { useStripoApi as
|
|
30
|
-
import { useConfigStore as
|
|
31
|
-
import { useDynamicContentStore as
|
|
1
|
+
import { defineComponent as ye, defineAsyncComponent as a, ref as W, computed as l, watch as G, onMounted as be, onUnmounted as ve } from "vue";
|
|
2
|
+
import { useCortexBlueprintBridge as Se } from "../composables/useCortexBlueprintBridge.js";
|
|
3
|
+
import { useEditorLock as he } from "../composables/useEditorLock.js";
|
|
4
|
+
import { startEditorOpenMetrics as Ee } from "../composables/useEditorOpenMetrics.js";
|
|
5
|
+
import { provideGuidoActions as Ce } from "../composables/useGuidoActions.js";
|
|
6
|
+
import { useGuidoStateBridge as De } from "../composables/useGuidoStateBridge.js";
|
|
7
|
+
import { usePartner as we } from "../composables/usePartner.js";
|
|
8
|
+
import { useSaveValidationRollout as Te } from "../composables/useSaveValidationRollout.js";
|
|
9
|
+
import { useStripo as ke } from "../composables/useStripo.js";
|
|
10
|
+
import { useTimerClone as Fe } from "../composables/useTimerClone.js";
|
|
11
|
+
import { useToaster as Ie } from "../composables/useToaster.js";
|
|
12
|
+
import { useTranslations as Le } from "../composables/useTranslations.js";
|
|
13
|
+
import { migrate as Me } from "../config/migrator/index.js";
|
|
14
|
+
import { ModuleFolderDefaults as $ } from "../enums/defaults.js";
|
|
15
|
+
import { RIBBON_SELECTOR as Re } from "../enums/onboarding.js";
|
|
16
|
+
import { ToasterTypeOptions as Oe } from "../enums/toaster.js";
|
|
17
|
+
import { useRecommendationExtensionStore as z, disposeStrategyPageReturnListeners as Ue } from "../extensions/Blocks/Recommendation/store/recommendation.js";
|
|
18
|
+
import { disposeUnsubscribeListeners as Ne } from "../extensions/Blocks/Unsubscribe/block.js";
|
|
19
|
+
import { disposeDisplayConditionRequest as _e } from "../extensions/DisplayConditions/bridge.js";
|
|
20
|
+
import Ae from "./organisms/AutoSaveController.vue.js";
|
|
21
|
+
import Pe from "./organisms/base/AuthErrorModal.vue.js";
|
|
22
|
+
import xe from "./organisms/base/Toaster.vue.js";
|
|
23
|
+
import Be from "./organisms/extensions/recommendation/FilterSelectionDrawer.vue.js";
|
|
24
|
+
import He from "./organisms/header/HeaderWrapper.vue.js";
|
|
25
|
+
import Ve from "./organisms/LoadingWrapper.vue.js";
|
|
26
|
+
import We from "./organisms/save-as-template/SaveAsTemplateDrawer.vue.js";
|
|
27
|
+
import Ge from "./organisms/unsubscribe/UnsubscribeWrapper.vue.js";
|
|
28
|
+
import $e from "./organisms/validation/ValidationErrorDrawer.vue.js";
|
|
29
|
+
import { useStripoApi as ze } from "../services/stripoApi.js";
|
|
30
|
+
import { useConfigStore as qe } from "../stores/config.js";
|
|
31
|
+
import { useDynamicContentStore as Ke } from "../stores/dynamic-content.js";
|
|
32
32
|
import { useEditorStore as C } from "../stores/editor.js";
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
39
|
-
|
|
40
|
-
const Vt = /* @__PURE__ */ Se({
|
|
33
|
+
import { useOnboardingStore as je } from "../stores/onboarding.js";
|
|
34
|
+
import { usePreviewStore as Je } from "../stores/preview.js";
|
|
35
|
+
import { useSaveValidationStore as Qe } from "../stores/save-validation.js";
|
|
36
|
+
import { useTemplateStore as Xe } from "../stores/template.js";
|
|
37
|
+
import { useUnsubscribeStore as Ye } from "../stores/unsubscribe.js";
|
|
38
|
+
import { readTrackFloor as q } from "../utils/linkTrackingIds.js";
|
|
39
|
+
const Pt = /* @__PURE__ */ ye({
|
|
41
40
|
__name: "Guido",
|
|
42
41
|
props: {
|
|
43
42
|
config: null,
|
|
44
43
|
ready: { type: Boolean, default: !0 }
|
|
45
44
|
},
|
|
46
45
|
emits: ["dynamic-content:open", "back", "save:start", "save:complete", "on-change", "ready", "onboarding:finished", "test-email:click"],
|
|
47
|
-
setup(
|
|
48
|
-
const c =
|
|
46
|
+
setup(K, { expose: j, emit: i }) {
|
|
47
|
+
const c = K, r = Ee(), J = a(
|
|
49
48
|
() => import("./organisms/email-preview/PreviewContainer.vue.js")
|
|
50
|
-
),
|
|
49
|
+
), Q = a(
|
|
51
50
|
() => import("./organisms/onboarding/OnboardingWrapper.vue.js")
|
|
52
|
-
),
|
|
51
|
+
), X = a(
|
|
53
52
|
() => import("./organisms/extensions/recommendation/AssignStrategyDrawer.vue.js")
|
|
54
|
-
),
|
|
53
|
+
), Y = a(
|
|
55
54
|
() => import("./organisms/extensions/recommendation/RemoveStrategyModal.vue.js")
|
|
56
|
-
),
|
|
55
|
+
), Z = a(
|
|
57
56
|
() => import("./organisms/display-conditions/DisplayConditionsHost.vue.js")
|
|
58
|
-
), D = W(),
|
|
57
|
+
), D = W(), ee = a(
|
|
59
58
|
() => import("./organisms/extensions/recommendation/LegacyStrategyUpdatedModal.vue.js")
|
|
60
|
-
),
|
|
59
|
+
), te = a(
|
|
61
60
|
() => import("./organisms/unsubscribe/LegacyUnsubscribeConvertedModal.vue.js")
|
|
62
|
-
),
|
|
63
|
-
() => import("./organisms/dynamic-content/AmbiguousDynamicContentModal.vue.js")
|
|
64
|
-
), y = W(), g = Qe(), w = tt(), re = q(), o = Je();
|
|
61
|
+
), g = W(), y = Ke(), w = Ye(), o = qe();
|
|
65
62
|
c.ready && o.init(c.config);
|
|
66
|
-
const d = C(),
|
|
63
|
+
const d = C(), oe = Je(), p = l(() => d.hasChanges), { isTestPartner: ne } = we(), { isEnabled: re, loadRollout: T } = Te(), { showToaster: k } = Ie(), F = Le(), I = () => {
|
|
67
64
|
var t;
|
|
68
65
|
if (d.isVersionHistoryOpen) {
|
|
69
66
|
console.debug("guido:save:silent:blocked", { isVersionHistoryOpen: !0 }), k({
|
|
70
|
-
type:
|
|
67
|
+
type: Oe.Warning,
|
|
71
68
|
message: F("email-editor.save-blocked-outside-editor")
|
|
72
69
|
});
|
|
73
70
|
return;
|
|
74
71
|
}
|
|
75
72
|
return (t = D.value) == null ? void 0 : t.saveSilent();
|
|
76
|
-
},
|
|
73
|
+
}, L = (t) => {
|
|
77
74
|
d.loadingStatus = t;
|
|
78
75
|
};
|
|
79
|
-
|
|
76
|
+
Se(), De();
|
|
80
77
|
const b = () => {
|
|
81
78
|
var t, e;
|
|
82
79
|
return {
|
|
@@ -84,20 +81,20 @@ const Vt = /* @__PURE__ */ Se({
|
|
|
84
81
|
userId: o.userId,
|
|
85
82
|
username: o.username,
|
|
86
83
|
partnerName: o.partnerName,
|
|
87
|
-
savedModulesFolderName: ((t = o.editor) == null ? void 0 : t.savedModulesFolderName) ||
|
|
88
|
-
defaultModulesFolderName: ((e = o.editor) == null ? void 0 : e.defaultModulesFolderName) ||
|
|
84
|
+
savedModulesFolderName: ((t = o.editor) == null ? void 0 : t.savedModulesFolderName) || $.SAVED_MODULES,
|
|
85
|
+
defaultModulesFolderName: ((e = o.editor) == null ? void 0 : e.defaultModulesFolderName) || $.DEFAULT_MODULES
|
|
89
86
|
};
|
|
90
|
-
}, { initPlugin:
|
|
87
|
+
}, { initPlugin: M, preloadRuntime: R } = ke(r), { runExclusive: O, beginMount: U, isCurrentMount: v } = he();
|
|
91
88
|
let f = 0;
|
|
92
|
-
const { getDefaultTemplate:
|
|
89
|
+
const { getDefaultTemplate: N } = ze(), { cloneTimersOnSave: _, hasTimerBlocks: A } = Fe(), ie = l(() => {
|
|
93
90
|
var t;
|
|
94
91
|
return !((t = o.ui) != null && t.showHeader);
|
|
95
|
-
}),
|
|
92
|
+
}), se = l(() => o.isFeatureEnabled("reusableRecommendationStrategy")), ae = l(() => o.externalDisplayConditions), ce = l(
|
|
96
93
|
() => o.isFeatureEnabled("legacyUnsubscribeConversion")
|
|
97
|
-
),
|
|
94
|
+
), de = l(
|
|
98
95
|
() => !!z().recommendationConfigs.strategyId
|
|
99
96
|
);
|
|
100
|
-
|
|
97
|
+
Ce({
|
|
101
98
|
onBack: () => {
|
|
102
99
|
console.debug("guido:back"), i("back");
|
|
103
100
|
},
|
|
@@ -113,11 +110,11 @@ const Vt = /* @__PURE__ */ Se({
|
|
|
113
110
|
}
|
|
114
111
|
});
|
|
115
112
|
const P = (t) => {
|
|
116
|
-
console.debug("dynamic-content:close", t),
|
|
113
|
+
console.debug("dynamic-content:close", t), y.setSelectedDynamicContent(t), document.dispatchEvent(new CustomEvent("dynamic-content:close", { detail: t }));
|
|
117
114
|
}, x = () => {
|
|
118
115
|
console.debug("dynamic-content:close", "Without Data"), document.dispatchEvent(new CustomEvent("dynamic-content:close", { detail: { text: "", value: "" } }));
|
|
119
116
|
};
|
|
120
|
-
|
|
117
|
+
G(() => p.value, () => {
|
|
121
118
|
i("on-change", p.value);
|
|
122
119
|
});
|
|
123
120
|
const S = (t) => {
|
|
@@ -127,8 +124,8 @@ const Vt = /* @__PURE__ */ Se({
|
|
|
127
124
|
let m = null;
|
|
128
125
|
const h = () => {
|
|
129
126
|
var e;
|
|
130
|
-
const t = document.querySelector(
|
|
131
|
-
(e =
|
|
127
|
+
const t = document.querySelector(Re);
|
|
128
|
+
(e = g.value) == null || e.style.setProperty("--ribbon-offset", `${(t == null ? void 0 : t.offsetHeight) ?? 0}px`);
|
|
132
129
|
}, E = async () => {
|
|
133
130
|
var t;
|
|
134
131
|
r.mark("host_ready");
|
|
@@ -141,49 +138,49 @@ const Vt = /* @__PURE__ */ Se({
|
|
|
141
138
|
});
|
|
142
139
|
const e = o.template, s = (e == null ? void 0 : e.html) || "", u = (e == null ? void 0 : e.css) || "", B = (e == null ? void 0 : e.preselectedDynamicContent) || [];
|
|
143
140
|
w.selectedUnsubscribePages = (e == null ? void 0 : e.selectedUnsubscribePages) || [];
|
|
144
|
-
const
|
|
141
|
+
const me = ((t = e == null ? void 0 : e.migration) == null ? void 0 : t.recommendationConfigs) ?? {}, H = o.isFeatureEnabled("linkTrackingIds"), le = {
|
|
145
142
|
partnerName: o.partnerName,
|
|
146
143
|
campaignUrls: e == null ? void 0 : e.recommendationCampaignUrls,
|
|
147
144
|
rrsEnabled: o.isFeatureEnabled("reusableRecommendationStrategy")
|
|
148
|
-
},
|
|
145
|
+
}, ue = {
|
|
149
146
|
itemsPriceFormatting: o.isFeatureEnabled("itemsPriceFormatting")
|
|
150
|
-
}, V = (
|
|
147
|
+
}, V = (ge) => r.timed(
|
|
151
148
|
"migration",
|
|
152
|
-
() =>
|
|
149
|
+
() => Me(ge, me, le, ue)
|
|
153
150
|
);
|
|
154
151
|
let n = {
|
|
155
152
|
html: s && await V(s),
|
|
156
153
|
css: u
|
|
157
154
|
};
|
|
158
|
-
n.html || (n = await r.timed("default_template", () =>
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
const
|
|
155
|
+
n.html || (n = await r.timed("default_template", () => N()), n.html = await V(n.html));
|
|
156
|
+
const pe = H ? q(n.html, (e == null ? void 0 : e.trackIdCounter) || 0) : 0;
|
|
157
|
+
A(n.html) && (n.html = await r.timed("timer_clone", () => _(n.html))), H && (d.trackIdSessionFloor = Math.max(pe, q(n.html)));
|
|
158
|
+
const fe = {
|
|
162
159
|
preselectedDynamicContentList: B,
|
|
163
160
|
onReady: () => {
|
|
164
161
|
console.debug("guido:ready"), i("ready");
|
|
165
162
|
}
|
|
166
163
|
};
|
|
167
|
-
f = U(), await
|
|
164
|
+
f = U(), await M(n, b(), fe, n.html !== s), y.selectedDynamicContentList = B;
|
|
168
165
|
} catch (e) {
|
|
169
166
|
console.error("Failed to initialize Stripo editor:", e), r.markFailed();
|
|
170
167
|
}
|
|
171
168
|
};
|
|
172
|
-
return
|
|
169
|
+
return be(async () => {
|
|
173
170
|
var e;
|
|
174
|
-
console.debug("Guido says happy coding 🎉"), console.debug("🚗 Ka-Chow"), z().$reset(), C().$reset(),
|
|
175
|
-
const t = (e =
|
|
171
|
+
console.debug("Guido says happy coding 🎉"), console.debug("🚗 Ka-Chow"), z().$reset(), C().$reset(), Xe().$reset(), Qe().$reset(), je().resetOnboarding("recommendationLegacyStrategyOnboarding"), T(), h();
|
|
172
|
+
const t = (e = g.value) == null ? void 0 : e.parentElement;
|
|
176
173
|
if (t && (m = new ResizeObserver(h), m.observe(t)), R(), c.ready)
|
|
177
174
|
await E();
|
|
178
175
|
else {
|
|
179
|
-
const s =
|
|
176
|
+
const s = G(() => c.ready, (u) => {
|
|
180
177
|
u && (s(), E());
|
|
181
178
|
});
|
|
182
179
|
}
|
|
183
180
|
document.addEventListener("dynamic-content:open", S);
|
|
184
|
-
}),
|
|
185
|
-
if (
|
|
186
|
-
|
|
181
|
+
}), ve(() => {
|
|
182
|
+
if (Ne(), Ue(), r.dispose(), m == null || m.disconnect(), document.removeEventListener("dynamic-content:open", S), v(f)) {
|
|
183
|
+
_e();
|
|
187
184
|
try {
|
|
188
185
|
const t = C();
|
|
189
186
|
t.isStripoInitialized = !1, t.isAccessibilityTestingOpen = !1, t.imagesHidden = !1, t.colorVisionDeficiency = "";
|
|
@@ -199,17 +196,17 @@ const Vt = /* @__PURE__ */ Se({
|
|
|
199
196
|
console.debug("Failed to remove Stripo editor: No editor found");
|
|
200
197
|
}
|
|
201
198
|
}), o.reset();
|
|
202
|
-
}),
|
|
199
|
+
}), j({
|
|
203
200
|
dynamicContent: {
|
|
204
201
|
insert: P,
|
|
205
202
|
close: x
|
|
206
203
|
},
|
|
207
204
|
hasChanges: p,
|
|
208
|
-
saveSilent:
|
|
209
|
-
setLoading:
|
|
210
|
-
}), { __sfc: !0, openMetrics: r, PreviewContainer:
|
|
205
|
+
saveSilent: I,
|
|
206
|
+
setLoading: L
|
|
207
|
+
}), { __sfc: !0, openMetrics: r, PreviewContainer: J, OnboardingWrapper: Q, AssignStrategyDrawer: X, RemoveStrategyModal: Y, DisplayConditionsHost: Z, autoSaveControllerRef: D, LegacyStrategyUpdatedModal: ee, LegacyUnsubscribeConvertedModal: te, wrapperRef: g, dynamicContentStore: y, unsubscribeStore: w, props: c, configStore: o, editorStore: d, previewStore: oe, hasChanges: p, isTestPartner: ne, isSaveValidationEnabled: re, loadRollout: T, showToaster: k, trans: F, saveSilent: I, setLoading: L, emit: i, buildMetadata: b, initPlugin: M, preloadRuntime: R, runExclusive: O, beginMount: U, isCurrentMount: v, mountGeneration: f, getDefaultTemplate: N, cloneTimersOnSave: _, hasTimerBlocks: A, noHeader: ie, isRrsEnabled: se, isExternalDisplayConditionsEnabled: ae, isLegacyUnsubscribeConversionEnabled: ce, hasAssignedStrategy: de, insertDynamicContent: P, closeDynamicContent: x, handleDynamicContentOpen: S, ribbonObserver: m, updateRibbonOffset: h, startEditor: E, AutoSaveController: Ae, AuthErrorModal: Pe, Toaster: xe, FilterSelectionDrawer: Be, HeaderWrapper: He, LoadingWrapper: Ve, SaveAsTemplateDrawer: We, UnsubscribeWrapper: Ge, ValidationErrorDrawer: $e };
|
|
211
208
|
}
|
|
212
209
|
});
|
|
213
210
|
export {
|
|
214
|
-
|
|
211
|
+
Pt as default
|
|
215
212
|
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { defaultHtmlCompilerRules as d } from "../config/compiler/htmlCompilerRules.js";
|
|
2
2
|
import { itemsCompilerRules as f } from "../config/compiler/itemsCompilerRules.js";
|
|
3
3
|
import { liquidCompilerRules as g } from "../config/compiler/liquidCompilerRules.js";
|
|
4
|
-
import { outlookCompilerRules as
|
|
5
|
-
import { recommendationCompilerRules as
|
|
4
|
+
import { outlookCompilerRules as R } from "../config/compiler/outlookCompilerRules.js";
|
|
5
|
+
import { recommendationCompilerRules as v } from "../config/compiler/recommendationCompilerRules.js";
|
|
6
6
|
import { socialCompilerRules as H } from "../config/compiler/socialCompilerRules.js";
|
|
7
7
|
import { unsubscribeCompilerRules as b } from "../config/compiler/unsubscribeCompilerRules.js";
|
|
8
8
|
import { createHtmlCompiler as n } from "../utils/htmlCompiler.js";
|
|
@@ -32,20 +32,19 @@ const x = /* @__PURE__ */ new Set([
|
|
|
32
32
|
"liquid-coupon-code",
|
|
33
33
|
// Editor-only attribute strip — AMP4EMAIL has no `contenteditable`, so leaving
|
|
34
34
|
// it in narrows/breaks rendering. Pure attribute removal, emits nothing.
|
|
35
|
-
"remove-contenteditable"
|
|
36
|
-
"remove-dc-pending-marker"
|
|
35
|
+
"remove-contenteditable"
|
|
37
36
|
]), I = () => {
|
|
38
|
-
const { compiler: i, isFeatureEnabled:
|
|
37
|
+
const { compiler: i, isFeatureEnabled: u, partner: a } = C(), c = p(() => {
|
|
39
38
|
var m, l;
|
|
40
39
|
const e = ((m = i.value) == null ? void 0 : m.customRules) || [];
|
|
41
40
|
return [
|
|
42
41
|
...!!((l = i.value) != null && l.ignoreDefaultRules) ? [] : d,
|
|
43
|
-
...
|
|
42
|
+
...v,
|
|
44
43
|
...b,
|
|
45
44
|
...f,
|
|
46
|
-
...
|
|
45
|
+
...R,
|
|
47
46
|
...H,
|
|
48
|
-
...
|
|
47
|
+
...u("liquidSyntax") ? g : [],
|
|
49
48
|
...e.map((t, o) => ({
|
|
50
49
|
...t,
|
|
51
50
|
priority: t.priority + 1e3 + o
|
|
@@ -54,7 +53,7 @@ const x = /* @__PURE__ */ new Set([
|
|
|
54
53
|
];
|
|
55
54
|
}), r = p(() => {
|
|
56
55
|
var t;
|
|
57
|
-
const e = c.value, s = n(e), m = n(e.filter((o) => x.has(o.id))), l = (t =
|
|
56
|
+
const e = c.value, s = n(e), m = n(e.filter((o) => x.has(o.id))), l = (t = a.value) == null ? void 0 : t.fallbackFont;
|
|
58
57
|
return {
|
|
59
58
|
compileHtml: (o) => s.compile(o, void 0, l),
|
|
60
59
|
compileAmpHtml: (o) => m.compile(o, void 0, l)
|
|
@@ -1,75 +1,44 @@
|
|
|
1
|
-
import { useConfig as
|
|
2
|
-
import { useToaster as
|
|
3
|
-
import { useTranslations as
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
import { convertLegacyUnsubscribeInModuleHtml as R } from "../utils/legacyUnsubscribeConversion.js";
|
|
15
|
-
import { extractUsedDynamicContent as k } from "../utils/registerUsedDynamicContent.js";
|
|
16
|
-
const q = "dynamic-content.unresolved-attributes-on-drop", H = /^(\s*<[a-zA-Z][a-zA-Z0-9-]*)/;
|
|
17
|
-
let y = 0;
|
|
18
|
-
const $ = (s) => {
|
|
19
|
-
y += 1;
|
|
20
|
-
const o = `${Date.now().toString(36)}-${y}`;
|
|
21
|
-
return { html: s.replace(H, `$1 ${T.Pending}="${o}"`), id: o };
|
|
22
|
-
}, I = (s, o) => {
|
|
23
|
-
try {
|
|
24
|
-
const i = k(s, o.map(({ text: a, value: m }) => ({ text: a, value: m })));
|
|
25
|
-
i.length > 0 && E().registerDynamicContent(i);
|
|
26
|
-
} catch (i) {
|
|
27
|
-
console.error("Failed to register module dynamic content:", i);
|
|
28
|
-
}
|
|
29
|
-
}, re = () => {
|
|
30
|
-
const { template: s, isFeatureEnabled: o } = h(), { showToaster: i } = v(), a = M(), m = (r) => {
|
|
31
|
-
var u, e;
|
|
32
|
-
const t = o("liquidSyntax") ? [] : S((u = s.value) == null ? void 0 : u.dynamicContentList), c = _(t);
|
|
33
|
-
return c.size === 0 ? { html: r, unresolved: [], ambiguous: [], candidates: t } : {
|
|
34
|
-
...F(
|
|
35
|
-
r,
|
|
36
|
-
c,
|
|
37
|
-
[...((e = s.value) == null ? void 0 : e.customFieldAttributes) ?? [], ...O]
|
|
38
|
-
),
|
|
39
|
-
candidates: t
|
|
40
|
-
};
|
|
41
|
-
};
|
|
42
|
-
return { handleModuleAdd: (r, t) => {
|
|
43
|
-
var c, u;
|
|
1
|
+
import { useConfig as f } from "./useConfig.js";
|
|
2
|
+
import { useToaster as d } from "./useToaster.js";
|
|
3
|
+
import { useTranslations as C } from "./useTranslations.js";
|
|
4
|
+
import { ToasterTypeOptions as T } from "../enums/toaster.js";
|
|
5
|
+
import { useEditorStore as h } from "../stores/editor.js";
|
|
6
|
+
import { buildDynamicContentLookup as v, convertModuleDynamicContent as D } from "../utils/dynamicContentConverter.js";
|
|
7
|
+
import { flattenDynamicContentList as L } from "../utils/genericUtil.js";
|
|
8
|
+
import { repairItemsCurrencyAttributes as M } from "../utils/itemsCurrencyRepair.js";
|
|
9
|
+
import { convertLegacyUnsubscribeInModuleHtml as O } from "../utils/legacyUnsubscribeConversion.js";
|
|
10
|
+
const E = "dynamic-content.unresolved-attributes-on-drop", S = () => {
|
|
11
|
+
const { template: p, isFeatureEnabled: n } = f(), { showToaster: y } = d(), b = C();
|
|
12
|
+
return { handleModuleAdd: (t, r) => {
|
|
13
|
+
var c, i, l;
|
|
44
14
|
try {
|
|
45
|
-
if ((
|
|
15
|
+
if ((t == null ? void 0 : t.action) !== "ADD" && (t == null ? void 0 : t.action) !== "COPY")
|
|
46
16
|
return;
|
|
47
|
-
const e = (c =
|
|
48
|
-
if (!e || typeof
|
|
17
|
+
const e = (c = r == null ? void 0 : r.getTargetNode) == null ? void 0 : c.call(r), s = (i = e == null ? void 0 : e.getOuterHTML) == null ? void 0 : i.call(e);
|
|
18
|
+
if (!e || typeof s != "string")
|
|
49
19
|
return;
|
|
50
|
-
let
|
|
51
|
-
convertToPriceFormat:
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
let
|
|
56
|
-
if (
|
|
20
|
+
let o = M(s, {
|
|
21
|
+
convertToPriceFormat: n("itemsPriceFormatting")
|
|
22
|
+
}), u = !1;
|
|
23
|
+
n("legacyUnsubscribeConversion") && ({ html: o, converted: u } = O(o));
|
|
24
|
+
const m = v(L((l = p.value) == null ? void 0 : l.dynamicContentList));
|
|
25
|
+
let a = [];
|
|
26
|
+
if (m.size > 0 && ({ html: o, unresolved: a } = D(o, m, n("liquidSyntax"))), o !== s && r.modifyHtml(e).replaceWith(o), u)
|
|
57
27
|
try {
|
|
58
|
-
|
|
59
|
-
} catch (
|
|
60
|
-
console.error("Failed to request the legacy unsubscribe modal:",
|
|
28
|
+
h().isLegacyUnsubscribeModalRequested = !0;
|
|
29
|
+
} catch (g) {
|
|
30
|
+
console.error("Failed to request the legacy unsubscribe modal:", g);
|
|
61
31
|
}
|
|
62
|
-
|
|
63
|
-
type:
|
|
64
|
-
message:
|
|
32
|
+
a.length > 0 && y({
|
|
33
|
+
type: T.Warning,
|
|
34
|
+
message: b(E)
|
|
65
35
|
});
|
|
66
36
|
} catch (e) {
|
|
67
37
|
console.error("Failed to repair module on add:", e);
|
|
68
38
|
}
|
|
69
|
-
}
|
|
39
|
+
} };
|
|
70
40
|
};
|
|
71
41
|
export {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
re as useModuleRepair
|
|
42
|
+
E as UNRESOLVED_DYNAMIC_CONTENT_ON_DROP_KEY,
|
|
43
|
+
S as useModuleRepair
|
|
75
44
|
};
|
|
@@ -3,9 +3,9 @@ import { MinDeviceViewport as C, DefaultPadding as R } from "../enums/recommenda
|
|
|
3
3
|
import { useRecommendationExtensionStore as g } from "../extensions/Blocks/Recommendation/store/recommendation.js";
|
|
4
4
|
import { generateCompleteFilterQuery as b } from "../extensions/Blocks/Recommendation/utils/filterUtil.js";
|
|
5
5
|
import { getPartnerRecommendationParams as h } from "../extensions/Blocks/Recommendation/utils/partnerCustomizations.js";
|
|
6
|
-
import { sanitizeProductIds as
|
|
7
|
-
import { useConfigStore as
|
|
8
|
-
const
|
|
6
|
+
import { sanitizeProductIds as P } from "../extensions/Blocks/Recommendation/utils/productIds.js";
|
|
7
|
+
import { useConfigStore as S } from "../stores/config.js";
|
|
8
|
+
const M = () => ({
|
|
9
9
|
calculateCardWidth: ({
|
|
10
10
|
mobileLeftPadding: s,
|
|
11
11
|
mobileRightPadding: c,
|
|
@@ -24,11 +24,7 @@ const B = () => ({
|
|
|
24
24
|
mobileLeftPadding: 0,
|
|
25
25
|
mobileRightPadding: 0,
|
|
26
26
|
cardsInRow: 2,
|
|
27
|
-
unresponsive: !1
|
|
28
|
-
priceBeforeTextValue: "",
|
|
29
|
-
priceAfterTextValue: "",
|
|
30
|
-
discountBeforeTextValue: "",
|
|
31
|
-
discountAfterTextValue: ""
|
|
27
|
+
unresponsive: !1
|
|
32
28
|
};
|
|
33
29
|
const { recommendationConfigs: i } = a, e = i.orientation === "grid" ? "vertical" : "horizontal";
|
|
34
30
|
return {
|
|
@@ -37,16 +33,12 @@ const B = () => ({
|
|
|
37
33
|
mobileLeftPadding: 0,
|
|
38
34
|
mobileRightPadding: 0,
|
|
39
35
|
cardsInRow: i.cardsInRow,
|
|
40
|
-
unresponsive: i.unresponsive
|
|
41
|
-
priceBeforeTextValue: "",
|
|
42
|
-
priceAfterTextValue: "",
|
|
43
|
-
discountBeforeTextValue: "",
|
|
44
|
-
discountAfterTextValue: ""
|
|
36
|
+
unresponsive: i.unresponsive
|
|
45
37
|
};
|
|
46
38
|
},
|
|
47
39
|
buildCampaignUrl: (s, c) => {
|
|
48
40
|
var l;
|
|
49
|
-
const o = g(), a =
|
|
41
|
+
const o = g(), a = S(), i = Number(s);
|
|
50
42
|
let e;
|
|
51
43
|
if (c)
|
|
52
44
|
e = c;
|
|
@@ -78,7 +70,7 @@ const B = () => ({
|
|
|
78
70
|
return delete r[s], o.recommendationCampaignUrls = r, "";
|
|
79
71
|
}
|
|
80
72
|
const t = new URLSearchParams();
|
|
81
|
-
t.set("locale", e.language), t.set("currency", e.currencyCode), t.set("partnerName", a.partnerName), t.set("size", e.size), t.set("details", "true"), t.set("campaignId", a.variationId), e.strategy === "manualMerchandising" ? t.set("productId",
|
|
73
|
+
t.set("locale", e.language), t.set("currency", e.currencyCode), t.set("partnerName", a.partnerName), t.set("size", e.size), t.set("details", "true"), t.set("campaignId", a.variationId), e.strategy === "manualMerchandising" ? t.set("productId", P(e.productIds)) : e.strategy === "similarViewed" && t.set("productId", "{itemId}"), e.strategy === "userBased" && t.set("userId", "{user_id}");
|
|
82
74
|
const f = e.filters.filter((r) => r.isValid), m = b(f);
|
|
83
75
|
m && t.set("filter", m), e.shuffleProducts && t.set("shuffle", "true"), Object.entries(h(a.partnerName, e.strategy)).forEach(([r, n]) => t.set(r, n));
|
|
84
76
|
const p = decodeURIComponent(t.toString()), u = `${I.RECOMMENDATION_API_URL}/v2/${d}?${p}`;
|
|
@@ -86,5 +78,5 @@ const B = () => ({
|
|
|
86
78
|
}
|
|
87
79
|
});
|
|
88
80
|
export {
|
|
89
|
-
|
|
81
|
+
M as useRecommendation
|
|
90
82
|
};
|