@useinsider/guido 3.19.0 → 3.20.0-beta.0849ec7

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 (148) hide show
  1. package/README.md +22 -3
  2. package/dist/@types/config/schemas.js +76 -53
  3. package/dist/components/Guido.vue.js +4 -4
  4. package/dist/components/Guido.vue2.js +102 -86
  5. package/dist/components/organisms/AutoSaveController.vue2.js +9 -8
  6. package/dist/components/organisms/base/AuthErrorModal.vue.js +18 -0
  7. package/dist/components/organisms/base/AuthErrorModal.vue2.js +42 -0
  8. package/dist/components/organisms/base/Toaster.vue2.js +13 -12
  9. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +13 -11
  10. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +78 -57
  11. package/dist/components/organisms/extensions/recommendation/LegacyStrategyUpdatedModal.vue.js +18 -0
  12. package/dist/components/organisms/extensions/recommendation/LegacyStrategyUpdatedModal.vue2.js +25 -0
  13. package/dist/components/organisms/extensions/recommendation/RemoveStrategyModal.vue2.js +28 -42
  14. package/dist/components/organisms/header/EditorActions.vue.js +5 -5
  15. package/dist/components/organisms/header/EditorActions.vue2.js +90 -57
  16. package/dist/components/organisms/header/LeftSlot.vue.js +5 -5
  17. package/dist/components/organisms/header/LeftSlot.vue2.js +16 -12
  18. package/dist/components/organisms/onboarding/OnboardingWrapper.vue2.js +28 -24
  19. package/dist/components/organisms/onboarding/RecommendationLegacyStrategyOnboarding.vue.js +21 -0
  20. package/dist/components/organisms/onboarding/RecommendationLegacyStrategyOnboarding.vue2.js +46 -0
  21. package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.js +21 -0
  22. package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue2.js +47 -0
  23. package/dist/components/organisms/validation/ValidationErrorDrawer.vue.js +20 -0
  24. package/dist/components/organisms/validation/ValidationErrorDrawer.vue2.js +49 -0
  25. package/dist/components/wrappers/WpDrawer.vue.js +9 -7
  26. package/dist/components/wrappers/WpDrawer.vue2.js +1 -1
  27. package/dist/components/wrappers/WpModal.vue.js +1 -1
  28. package/dist/components/wrappers/WpModal.vue2.js +4 -3
  29. package/dist/composables/useActionsApi.js +52 -47
  30. package/dist/composables/useAuthError.js +52 -0
  31. package/dist/composables/useAutoSave.js +11 -11
  32. package/dist/composables/useCodeEditorApi.js +23 -9
  33. package/dist/composables/useCortexBlueprintBridge.js +122 -54
  34. package/dist/composables/useCustomInterfaceAppearance.js +65 -51
  35. package/dist/composables/useEmailTemplateApplier.js +111 -50
  36. package/dist/composables/useHtmlCompiler.js +37 -26
  37. package/dist/composables/useHtmlValidator.js +89 -82
  38. package/dist/composables/useHttp.js +64 -54
  39. package/dist/composables/useLegacyStrategyConversion.js +65 -0
  40. package/dist/composables/useRecommendation.js +40 -35
  41. package/dist/composables/useSave.js +90 -45
  42. package/dist/composables/useSaveValidation.js +282 -0
  43. package/dist/composables/useSaveValidationRollout.js +9 -0
  44. package/dist/composables/useStripo.js +43 -39
  45. package/dist/composables/useToaster.js +18 -22
  46. package/dist/composables/useTranslations.js +3 -2
  47. package/dist/composables/useVersionHistoryApi.js +33 -24
  48. package/dist/composables/validators/useCouponBlockValidator.js +24 -21
  49. package/dist/composables/validators/useLiquidValidator.js +15 -15
  50. package/dist/composables/validators/useUnsubscribeBlockValidator.js +34 -27
  51. package/dist/config/migrator/index.js +14 -13
  52. package/dist/config/migrator/itemsBlockMigrator.js +236 -248
  53. package/dist/config/migrator/recommendationMigrator.js +28 -21
  54. package/dist/config/migrator/recommendationPartnerMigrator.js +56 -0
  55. package/dist/enums/extensions/recommendationBlock.js +51 -34
  56. package/dist/enums/save-validation.js +4 -0
  57. package/dist/extensions/Blocks/Items/constants/cardLayout.js +20 -0
  58. package/dist/extensions/Blocks/Items/controls/name/trimming.js +18 -17
  59. package/dist/extensions/Blocks/Items/controls/settingsControl.js +114 -105
  60. package/dist/extensions/Blocks/Items/enums/productEnums.js +14 -9
  61. package/dist/extensions/Blocks/Items/layouts/horizontal.html.js +11 -9
  62. package/dist/extensions/Blocks/Items/template.js +219 -204
  63. package/dist/extensions/Blocks/Recommendation/block.js +65 -45
  64. package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +21 -20
  65. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +103 -90
  66. package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +150 -52
  67. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +74 -74
  68. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +274 -92
  69. package/dist/extensions/Blocks/Recommendation/utils/legacyStrategyMigration.js +42 -0
  70. package/dist/extensions/Blocks/Recommendation/utils/nodeConfigWriter.js +26 -16
  71. package/dist/extensions/Blocks/Recommendation/utils/partnerCustomizations.js +3 -1
  72. package/dist/extensions/Blocks/Recommendation/utils/partnerScope.js +25 -0
  73. package/dist/extensions/Blocks/Recommendation/utils/productIds.js +5 -3
  74. package/dist/extensions/Blocks/Recommendation/utils/strategyCommit.js +24 -0
  75. package/dist/extensions/Blocks/Recommendation/validation/requiredFields.js +21 -12
  76. package/dist/guido.css +1 -1
  77. package/dist/services/recommendationApi.js +46 -37
  78. package/dist/src/@types/config/schemas.d.ts +36 -0
  79. package/dist/src/@types/save-validation.d.ts +19 -0
  80. package/dist/src/components/Guido.vue.d.ts +17 -1
  81. package/dist/src/components/organisms/base/AuthErrorModal.vue.d.ts +2 -0
  82. package/dist/src/components/organisms/extensions/recommendation/LegacyStrategyUpdatedModal.vue.d.ts +2 -0
  83. package/dist/src/components/organisms/header/EditorActions.vue.d.ts +17 -1
  84. package/dist/src/components/organisms/header/HeaderWrapper.vue.d.ts +17 -1
  85. package/dist/src/components/organisms/header/RightSlot.vue.d.ts +17 -1
  86. package/dist/src/components/organisms/onboarding/RecommendationLegacyStrategyOnboarding.vue.d.ts +2 -0
  87. package/dist/src/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.d.ts +2 -0
  88. package/dist/src/components/organisms/validation/ValidationErrorDrawer.vue.d.ts +2 -0
  89. package/dist/src/components/wrappers/WpDrawer.vue.d.ts +4 -3
  90. package/dist/src/components/wrappers/WpModal.vue.d.ts +5 -1
  91. package/dist/src/composables/useAuthError.d.ts +12 -0
  92. package/dist/src/composables/useConfig.d.ts +8 -0
  93. package/dist/src/composables/useCortexBlueprintBridge.d.ts +2 -3
  94. package/dist/src/composables/useEmailTemplateApplier.d.ts +18 -5
  95. package/dist/src/composables/useGuidoActions.d.ts +2 -0
  96. package/dist/src/composables/useHtmlValidator.d.ts +21 -0
  97. package/dist/src/composables/useHttp.d.ts +2 -0
  98. package/dist/src/composables/useLegacyStrategyConversion.d.ts +3 -0
  99. package/dist/src/composables/useSave.d.ts +6 -1
  100. package/dist/src/composables/useSaveValidation.d.ts +6 -0
  101. package/dist/src/composables/useSaveValidationRollout.d.ts +3 -0
  102. package/dist/src/composables/validators/useCouponBlockValidator.d.ts +3 -0
  103. package/dist/src/composables/validators/useUnsubscribeBlockValidator.d.ts +10 -0
  104. package/dist/src/config/migrator/index.d.ts +2 -1
  105. package/dist/src/config/migrator/recommendationPartnerMigrator.d.ts +19 -0
  106. package/dist/src/enums/extensions/recommendationBlock.d.ts +7 -1
  107. package/dist/src/enums/save-validation.d.ts +27 -0
  108. package/dist/src/extensions/Blocks/Items/constants/cardLayout.d.ts +44 -0
  109. package/dist/src/extensions/Blocks/Items/enums/productEnums.d.ts +3 -0
  110. package/dist/src/extensions/Blocks/Items/template.d.ts +19 -0
  111. package/dist/src/extensions/Blocks/Recommendation/block.d.ts +10 -0
  112. package/dist/src/extensions/Blocks/Recommendation/constants/defaultConfig.d.ts +1 -0
  113. package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +1 -1
  114. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +2 -0
  115. package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +10 -0
  116. package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.d.ts +7 -2
  117. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +162 -1
  118. package/dist/src/extensions/Blocks/Recommendation/types/nodeConfig.d.ts +6 -0
  119. package/dist/src/extensions/Blocks/Recommendation/utils/legacyStrategyMigration.d.ts +32 -0
  120. package/dist/src/extensions/Blocks/Recommendation/utils/partnerScope.d.ts +33 -0
  121. package/dist/src/extensions/Blocks/Recommendation/utils/productIds.d.ts +2 -0
  122. package/dist/src/extensions/Blocks/Recommendation/utils/strategyCommit.d.ts +14 -0
  123. package/dist/src/extensions/Blocks/Recommendation/validation/requiredFields.d.ts +4 -0
  124. package/dist/src/mock/cortexChatStore.d.ts +12 -0
  125. package/dist/src/services/recommendationApi.d.ts +2 -1
  126. package/dist/src/stores/config.d.ts +374 -0
  127. package/dist/src/stores/guido-email-editor.d.ts +20 -10
  128. package/dist/src/stores/onboarding.d.ts +812 -10
  129. package/dist/src/stores/recommendation.d.ts +5 -0
  130. package/dist/src/stores/save-validation.d.ts +22 -0
  131. package/dist/src/utils/dateUtil.d.ts +10 -0
  132. package/dist/src/utils/genericUtil.d.ts +3 -0
  133. package/dist/src/utils/stripoEditorApi.d.ts +4 -0
  134. package/dist/src/utils/templatePreparation.d.ts +30 -0
  135. package/dist/static/assets/icons/filled-arrow-rising.svg.js +5 -0
  136. package/dist/static/assets/icons/line-info.svg.js +5 -0
  137. package/dist/static/styles/components/recommendation-strategy.css.js +113 -9
  138. package/dist/static/styles/components/skeleton.css.js +23 -0
  139. package/dist/static/styles/components/version-history.css.js +2 -6
  140. package/dist/stores/config.js +55 -24
  141. package/dist/stores/guido-email-editor.js +3 -1
  142. package/dist/stores/onboarding.js +50 -36
  143. package/dist/stores/save-validation.js +30 -0
  144. package/dist/stores/unsubscribe.js +3 -3
  145. package/dist/utils/pairProductVariables.js +71 -71
  146. package/dist/utils/stripoEditorApi.js +11 -0
  147. package/dist/utils/templatePreparation.js +54 -51
  148. package/package.json +2 -1
@@ -1,55 +1,100 @@
1
- import { useActionsApi as T } from "./useActionsApi.js";
1
+ import { useActionsApi as W } from "./useActionsApi.js";
2
2
  import { useConfig as q } from "./useConfig.js";
3
- import { useEditorLock as C } from "./useEditorLock.js";
4
- import { useSaveStart as L, useSaveComplete as M } from "./useGuidoActions.js";
5
- import { useSyncModuleExtractor as D } from "./useSyncModuleExtractor.js";
6
- import { ToasterTypeOptions as P } from "../enums/toaster.js";
7
- import { useStripoApi as U } from "../services/stripoApi.js";
8
- import { useTemplatePreparation as A } from "../utils/templatePreparation.js";
9
- import { useAllowlist as h } from "./useAllowlist.js";
10
- import { useHtmlValidator as F } from "./useHtmlValidator.js";
11
- import { useToaster as O } from "./useToaster.js";
12
- import { useCouponBlockValidator as W } from "./validators/useCouponBlockValidator.js";
13
- import { useLiquidValidator as j } from "./validators/useLiquidValidator.js";
14
- import { useSyncModuleBlockValidator as z } from "./validators/useSyncModuleBlockValidator.js";
15
- import { useUnsubscribeBlockValidator as G } from "./validators/useUnsubscribeBlockValidator.js";
16
- const rt = () => {
17
- const n = L(), c = M(), { validateHtml: d } = F(), { validateLiquidSyntax: m } = j(), { validateCouponBlockTags: u } = W(), { validateUnsubscribeBlockUniqueness: p, validateUnsubscribeBlockHasTemplate: f } = G(), { validateSyncModuleBlocks: v } = z(), { callbacks: s, isFeatureEnabled: r } = q(), { extractSyncModuleData: S } = D(), { setSyncModuleUnsubscriptionPages: b } = U(), { editorSave: w } = T(), { showToaster: V } = O(), { getBlockedDomains: y, resolveToast: k } = h(), { runExclusive: x } = C(), H = async (a, o) => {
18
- var l;
19
- n();
20
- const { prepareTemplateDetails: B } = A(), t = await B();
21
- if (!v(t.rawHtml, o) || !u(t.compiledHtml) || !p(t.compiledHtml) || !f(t.compiledHtml))
22
- return;
23
- if (r("liquidSyntax")) {
24
- if (!await m(t.compiledHtml))
25
- return;
26
- } else if (!await d(t.compiledHtml, t.dynamicContentList, !0))
27
- return;
28
- if ((l = s.value) != null && l.externalValidation && !await s.value.externalValidation(t))
3
+ import { useEditorLock as O } from "./useEditorLock.js";
4
+ import { useSaveStart as D, useSaveComplete as F } from "./useGuidoActions.js";
5
+ import { useSaveValidation as j } from "./useSaveValidation.js";
6
+ import { useSaveValidationRollout as z } from "./useSaveValidationRollout.js";
7
+ import { useSyncModuleExtractor as G } from "./useSyncModuleExtractor.js";
8
+ import { ToasterTypeOptions as I } from "../enums/toaster.js";
9
+ import { useStripoApi as J } from "../services/stripoApi.js";
10
+ import { useConfigStore as K } from "../stores/config.js";
11
+ import { useDynamicContentStore as N } from "../stores/dynamic-content.js";
12
+ import { useSaveValidationStore as Q } from "../stores/save-validation.js";
13
+ import { useTemplatePreparation as X, getHtmlReferencedUnsubscribePages as Y } from "../utils/templatePreparation.js";
14
+ import { useAllowlist as Z } from "./useAllowlist.js";
15
+ import { useHtmlValidator as _ } from "./useHtmlValidator.js";
16
+ import { useToaster as $ } from "./useToaster.js";
17
+ import { useCouponBlockValidator as tt } from "./validators/useCouponBlockValidator.js";
18
+ import { useLiquidValidator as et } from "./validators/useLiquidValidator.js";
19
+ import { useSyncModuleBlockValidator as ot } from "./validators/useSyncModuleBlockValidator.js";
20
+ import { useUnsubscribeBlockValidator as st } from "./validators/useUnsubscribeBlockValidator.js";
21
+ const Bt = () => {
22
+ const r = D(), f = F(), { validateHtml: p } = _(), { validateLiquidSyntax: v } = et(), { validateCouponBlockTags: y } = tt(), { validateUnsubscribeBlockUniqueness: S, validateUnsubscribeBlockHasTemplate: w } = st(), { validateSyncModuleBlocks: n } = ot(), { callbacks: a, isFeatureEnabled: m } = q(), { extractSyncModuleData: b } = G(), { setSyncModuleUnsubscriptionPages: g } = J(), { editorSave: E, getTemplateData: H } = W(), { showToaster: V } = $(), { getBlockedDomains: x, resolveToast: k } = Z(), { prepareTemplateDetails: d } = X(), { collectSaveValidationErrors: C } = j(), { isEnabled: B } = z(), T = Q(), h = N(), P = K(), { runExclusive: l } = O(), c = async (t, e, o) => {
23
+ if (!m("allowlistEnabled"))
24
+ return !1;
25
+ const i = await x(t, e);
26
+ if (!i.length)
27
+ return !1;
28
+ if (!o) {
29
+ const s = await k(i);
30
+ s != null && s.message && V({
31
+ type: I.Warning,
32
+ message: s.message,
33
+ actionButton: s.actionButton
34
+ });
35
+ }
36
+ return !0;
37
+ }, L = async (t) => !y(t.compiledHtml) || !S(t.compiledHtml) || !w(t.compiledHtml) ? !1 : m("liquidSyntax") ? v(t.compiledHtml) : p(t.compiledHtml, t.dynamicContentList, !0), u = async (t, e) => {
38
+ if (!await E())
29
39
  return;
30
- if (r("allowlistEnabled")) {
31
- const i = await y(t.compiledHtml, t.css);
32
- if (i.length) {
33
- if (!o) {
34
- const e = await k(i);
35
- e != null && e.message && V({
36
- type: P.Warning,
37
- message: e.message,
38
- actionButton: e.actionButton
39
- });
40
+ const { unsubscribePayload: i, stripoModules: s } = b(t.rawHtml);
41
+ if (await g(i), t.modules = s, !e.suppress) {
42
+ const R = e.blankCompiled ? { compiledHtml: "", ampHtml: "" } : {};
43
+ f({ ...t, ...R, silent: e.silent });
44
+ }
45
+ return t;
46
+ }, U = async (t, e) => {
47
+ var i;
48
+ r();
49
+ const o = await d();
50
+ if (n(o.rawHtml, e)) {
51
+ if (B.value && !e) {
52
+ const s = await C(
53
+ o.compiledHtml,
54
+ o.dynamicContentList
55
+ );
56
+ if (s.length) {
57
+ T.open(s, "save");
58
+ return;
40
59
  }
60
+ } else if (!await L(o))
41
61
  return;
42
- }
62
+ if (!((i = a.value) != null && i.externalValidation && !await a.value.externalValidation(o)) && !await c(o.compiledHtml, o.css, e))
63
+ return u(o, { silent: e, suppress: t });
43
64
  }
44
- if (!await w())
65
+ }, A = async () => {
66
+ var e;
67
+ if (!P.allowSaveWithErrors)
45
68
  return;
46
- const { unsubscribePayload: E, stripoModules: g } = S(t.rawHtml);
47
- return await b(E), t.modules = g, a || c({ ...t, silent: o }), t;
69
+ r();
70
+ const t = await d();
71
+ if (n(t.rawHtml, !1) && !((e = a.value) != null && e.externalValidation && !await a.value.externalValidation(t)) && !await c(t.compiledHtml, t.css, !1))
72
+ return u(t, { silent: !1, blankCompiled: !0 });
73
+ }, M = async () => {
74
+ r();
75
+ const { html: t, css: e } = await H();
76
+ if (!n(t, !0) || await c(t, e, !0))
77
+ return;
78
+ const o = Y(t), i = {
79
+ dynamicContentList: h.getSelectedDynamicContentList,
80
+ compiledHtml: "",
81
+ rawHtml: t,
82
+ css: e,
83
+ ampHtml: "",
84
+ ampErrors: [],
85
+ modules: [],
86
+ recommendation: { campaignUrls: {}, configs: {} },
87
+ unsubscribe: {
88
+ status: o.length > 0,
89
+ config: o
90
+ }
91
+ };
92
+ return u(i, { silent: !0 });
48
93
  };
49
- return { save: (a = !1, o = !1) => x(
50
- () => H(a, o)
51
- ) };
94
+ return { save: (t = !1, e = !1) => l(
95
+ () => U(t, e)
96
+ ), saveWithErrors: () => l(A), saveRawOnly: () => l(M) };
52
97
  };
53
98
  export {
54
- rt as useSave
99
+ Bt as useSave
55
100
  };
@@ -0,0 +1,282 @@
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 M } from "../extensions/Blocks/Checkbox/constants/selectors.js";
6
+ import { itemsBlockDynamicVariables as U } 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 { getInvalidFields as G, STRATEGY_FIELD_KEY as q, RecommendationAssignStrategyKey as H, RecommendationRequiredFieldsKey as V } from "../extensions/Blocks/Recommendation/validation/requiredFields.js";
10
+ import { useConfigStore as X } from "../stores/config.js";
11
+ import { useDynamicContentStore as j } from "../stores/dynamic-content.js";
12
+ import { useRecommendationStore as z } from "../stores/recommendation.js";
13
+ import { base64EncodeWithSpecialChars as T } from "../utils/base64.js";
14
+ import { escapeHtml as $ } from "../utils/htmlEscape.js";
15
+ import { useTemplatePreparation as Q } from "../utils/templatePreparation.js";
16
+ import { useActionsApi as Z } from "./useActionsApi.js";
17
+ import { useConfig as J } from "./useConfig.js";
18
+ import { useHtmlCompiler as ee } from "./useHtmlCompiler.js";
19
+ import { buildPartnerAttributeNameSet as te, getInvalidDynamicContentTags as ne, getRecommendationBlockIds as ie, findInvalidCustomFields as oe } from "./useHtmlValidator.js";
20
+ import { useHttp as re } from "./useHttp.js";
21
+ import { useTranslations as se } from "./useTranslations.js";
22
+ import { findInvalidCouponBlocks as ae, COUPON_TAG_MODIFIED_KEY as ce } from "./validators/useCouponBlockValidator.js";
23
+ import { findDuplicateUnsubPageTypes as le, countUnsubBlocksWithoutPage as me, EMPTY_BLOCK_KEY as ue } from "./validators/useUnsubscribeBlockValidator.js";
24
+ const de = "newsletter.html-content-is-empty", pe = "custom-fields.missing-closing-braces", ge = "custom-fields.missing-opening-braces", I = "custom-fields.invalid-custom-fields", fe = "newsletter.display-conditions-invalid-syntax", ye = "custom-conditions.wrong-equality-operators", Ee = "custom-conditions.missing-if-endif-tag", Ie = "custom-conditions.no-space-after-braces", Se = "custom-conditions.no-braces-inside-if-tag", _e = "newsletter.fill-all-necessary-fields", Ce = "newsletter.invalid-image-type", he = "unsubscribe-templates.select-checkbox-groups", ke = "unsubscribe-templates.select-radio-button-groups", Te = "newsletter.invalid-url-link-for-toaster", F = "journey-builder.liquid-validation-failed", Fe = "/newsletter/template-library/check-template-html-body", Oe = /src="[^"]*\.(svg|pst)"/gm, R = /({%(.*?)%})/g, Re = ["if", "endif", "else", "elif", "now"], Le = (t) => !Re.includes(t.toLowerCase()), Ne = (t) => ["if", "endif"].includes(t.toLowerCase());
25
+ function be(t) {
26
+ return ae(t).map((i) => ({
27
+ rule: o.CouponTagModified,
28
+ type: r.Warning,
29
+ key: ce,
30
+ detail: i
31
+ }));
32
+ }
33
+ function Ae(t) {
34
+ return le(t).map((i) => ({
35
+ rule: o.DuplicateUnsubBlock,
36
+ type: r.Error,
37
+ key: i.messageKey
38
+ }));
39
+ }
40
+ function ve(t) {
41
+ return Array.from({ length: me(t) }, () => ({
42
+ rule: o.UnsubBlockMissingTemplate,
43
+ type: r.Warning,
44
+ key: ue
45
+ }));
46
+ }
47
+ function De(t, i) {
48
+ const n = t.match(R);
49
+ if (!n)
50
+ return [];
51
+ const c = [];
52
+ return n.forEach((u) => {
53
+ const a = u.slice(2, -2).trim().match(/(".*?"|[^"\s]+)(?=\s*|\s*$)/g);
54
+ if (a && a.length > 0) {
55
+ const [d] = a;
56
+ Le(d) && !i.includes(d) && c.push({
57
+ rule: o.CustomFieldScript,
58
+ type: r.Warning,
59
+ key: I,
60
+ detail: d
61
+ });
62
+ }
63
+ }), c;
64
+ }
65
+ function Ke(t) {
66
+ return t.length > 0 ? [] : [{ rule: o.EmptyHtml, type: r.Warning, key: de }];
67
+ }
68
+ function we(t) {
69
+ const i = (t.match(/{/gm) || []).length, n = (t.match(/}/gm) || []).length;
70
+ return i > n ? [{
71
+ rule: o.MismatchedBraces,
72
+ type: r.Warning,
73
+ key: pe
74
+ }] : i < n ? [{
75
+ rule: o.MismatchedBraces,
76
+ type: r.Warning,
77
+ key: ge
78
+ }] : [];
79
+ }
80
+ function Be(t) {
81
+ return ne(t).map((i) => ({
82
+ rule: o.InvalidDynamicTag,
83
+ type: r.Warning,
84
+ key: I,
85
+ detail: i
86
+ }));
87
+ }
88
+ function Ye(t, i, n, c) {
89
+ const u = ie(t);
90
+ return oe(t, i, u, n, c).map((a) => ({
91
+ rule: o.InvalidCustomField,
92
+ type: r.Error,
93
+ key: I,
94
+ detail: a
95
+ }));
96
+ }
97
+ function xe(t) {
98
+ const i = t.match(/{%(.*?)%}/g), n = [], c = [];
99
+ if (i && i.forEach((u) => {
100
+ const a = u.match(Y), d = u.match(x), E = (a == null ? void 0 : a.join("")) || "";
101
+ (!a || u !== E) && !d && c.push({
102
+ rule: o.ConditionsSyntax,
103
+ type: r.Error,
104
+ key: fe,
105
+ detail: u
106
+ }), a && a.forEach((g) => {
107
+ g.trim() === "=" && c.push({
108
+ rule: o.WrongEqualityOperator,
109
+ type: r.Error,
110
+ key: ye
111
+ }), (g.match(/^[a-zA-Z]*$/g) ?? []).forEach((f) => {
112
+ Ne(f) && n.push(f);
113
+ });
114
+ });
115
+ }), n.length) {
116
+ const u = n.filter((d) => d === "if").length, a = n.filter((d) => d === "endif").length;
117
+ u !== a && c.push({
118
+ rule: o.MissingIfEndif,
119
+ type: r.Error,
120
+ key: Ee
121
+ });
122
+ }
123
+ return c;
124
+ }
125
+ function Me(t) {
126
+ const i = (t.match(/{% /gm) || []).length, n = (t.match(/ %}/gm) || []).length;
127
+ return i === n ? [] : [{
128
+ rule: o.ConditionTagSpacing,
129
+ type: r.Warning,
130
+ key: Ie
131
+ }];
132
+ }
133
+ function Ue(t) {
134
+ return (t.match(R) || []).filter((n) => n.includes("if")).map((n) => (n.match(/{{.*}}/gm) || []).length).reduce((n, c) => n + c, 0) === 0 ? [] : [{
135
+ rule: o.BracesInsideIfTag,
136
+ type: r.Warning,
137
+ key: Se
138
+ }];
139
+ }
140
+ function Pe(t) {
141
+ return (t.match(Oe) ?? []).map((i) => ({
142
+ rule: o.InvalidImageType,
143
+ type: r.Error,
144
+ key: Ce,
145
+ detail: i
146
+ }));
147
+ }
148
+ function O(t, i, n, c) {
149
+ const u = new DOMParser().parseFromString(t, "text/html");
150
+ return Array.from(u.querySelectorAll(i)).filter((a) => {
151
+ var d;
152
+ return !((d = a.id) != null && d.trim());
153
+ }).map(() => ({ rule: n, type: r.Error, key: c }));
154
+ }
155
+ const dt = () => {
156
+ const { config: t, isFeatureEnabled: i } = J(), n = se(), { post: c } = re(), { getCompiledEmail: u, getTemplateData: a } = Z(), { compileHtml: d } = ee(), { hydrateRecommendationStore: E } = Q(), g = j(), f = z(), y = W(), L = X(), N = (e) => ({
157
+ rule: e.rule,
158
+ type: e.type,
159
+ detail: e.detail,
160
+ message: "key" in e ? n(e.key) : $(e.message)
161
+ }), b = async (e) => {
162
+ if (e.size === 0)
163
+ return /* @__PURE__ */ new Set();
164
+ try {
165
+ await y.fetchRecommendationFilters();
166
+ } catch {
167
+ return null;
168
+ }
169
+ return te(y.filterList);
170
+ }, A = async (e) => {
171
+ try {
172
+ const l = await c(Fe, { html: T(e) }), { status: s, message: m } = l.data, p = [];
173
+ return s || p.push({
174
+ rule: o.InvalidLinks,
175
+ type: r.Error,
176
+ // status===undefined means a bare message instead of a boolean; surface it,
177
+ // but fall back to the canned key when it's missing so a malformed body
178
+ // never renders a literal 'undefined' row (SD-147430).
179
+ ...s === void 0 && m ? { message: m } : { key: Te }
180
+ }), m === n(k) && p.push({
181
+ rule: o.LinkCheckInProgress,
182
+ type: r.Error,
183
+ key: k
184
+ }), p;
185
+ } catch (l) {
186
+ return console.warn("Link-check collector failed; skipping the link rule.", l), [];
187
+ }
188
+ }, v = async (e) => {
189
+ try {
190
+ const l = await c("/newsletter/contents/validate-syntax", [{
191
+ identifier: "default",
192
+ syntax: "liquid",
193
+ contents: {
194
+ subject: null,
195
+ preheader: null,
196
+ html: T(e),
197
+ ampHtml: null
198
+ }
199
+ }]);
200
+ if (!Array.isArray(l.data)) {
201
+ const m = l.data;
202
+ return [{
203
+ rule: o.LiquidSyntax,
204
+ type: r.Warning,
205
+ message: m.message ?? n(F)
206
+ }];
207
+ }
208
+ const [s] = l.data;
209
+ return Object.values((s == null ? void 0 : s.errors) ?? {}).map((m) => ({
210
+ rule: o.LiquidSyntax,
211
+ type: r.Warning,
212
+ message: m.replace(/^line \d+:\s*/, "")
213
+ }));
214
+ } catch {
215
+ return [{
216
+ rule: o.LiquidSyntax,
217
+ type: r.Error,
218
+ message: n(F)
219
+ }];
220
+ }
221
+ }, D = () => {
222
+ const e = Object.values(y.blockStates).map((s) => G(s.recommendationConfigs, y)).filter((s) => s.length > 0).map((s) => {
223
+ const m = s.every((p) => p === q);
224
+ return {
225
+ rule: o.RecommendationRequiredFields,
226
+ type: m ? r.Warning : r.Error,
227
+ key: m ? H : V
228
+ };
229
+ }), l = (f.recommendationConfigs ?? []).filter((s) => s.filters.some((m) => m.value === "")).map(() => ({
230
+ rule: o.RecommendationFilters,
231
+ type: r.Error,
232
+ key: _e
233
+ }));
234
+ return [...e, ...l];
235
+ }, K = async (e, l) => {
236
+ var C, h;
237
+ const s = [
238
+ ...l.map((w) => w.value),
239
+ ...U,
240
+ ...((h = (C = t.value) == null ? void 0 : C.template) == null ? void 0 : h.customFieldAttributes) ?? []
241
+ ], m = B(e), p = await b(m), { isTransactional: _ } = L;
242
+ return [
243
+ ...await A(e),
244
+ ..._ ? [] : De(e, s),
245
+ ...Ke(e),
246
+ ...we(e),
247
+ ...Be(e),
248
+ ..._ ? [] : Ye(e, s, m, p),
249
+ ...xe(e),
250
+ ...Me(e),
251
+ ...Ue(e),
252
+ ...D(),
253
+ ...Pe(e),
254
+ ...O(
255
+ e,
256
+ M,
257
+ o.CheckboxUnsubGroup,
258
+ he
259
+ ),
260
+ ...O(
261
+ e,
262
+ P,
263
+ o.RadioButtonUnsubGroup,
264
+ ke
265
+ )
266
+ ];
267
+ }, S = async (e, l) => [
268
+ ...be(e),
269
+ ...Ae(e),
270
+ ...ve(e),
271
+ ...i("liquidSyntax") ? await v(e) : await K(e, l)
272
+ ].map(N);
273
+ return { collectSaveValidationErrors: S, validateCurrentTemplate: async () => {
274
+ const { html: e } = await a();
275
+ await E(e);
276
+ const { html: l } = await u({ minimize: !0, resetDataSavedFlag: !1 }), { compiledHtml: s } = d(l);
277
+ return S(s, g.getSelectedDynamicContentList);
278
+ } };
279
+ };
280
+ export {
281
+ dt as useSaveValidation
282
+ };
@@ -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
+ };
@@ -1,59 +1,59 @@
1
- import { useActionsApi as x } from "./useActionsApi.js";
2
- import { useBlocksConfig as L } from "./useBlocksConfig.js";
3
- import { useConfig as O } from "./useConfig.js";
4
- import { useCustomInterfaceAppearance as H } from "./useCustomInterfaceAppearance.js";
1
+ import { useActionsApi as L } from "./useActionsApi.js";
2
+ import { useBlocksConfig as O } from "./useBlocksConfig.js";
3
+ import { useConfig as H } from "./useConfig.js";
4
+ import { useCustomInterfaceAppearance as w } from "./useCustomInterfaceAppearance.js";
5
5
  import { useFullStoryBridge as N } from "./useFullStoryBridge.js";
6
6
  import { useModuleRepair as j } from "./useModuleRepair.js";
7
7
  import { useStripoEventHandler as z } from "./useStripoEventHandler.js";
8
8
  import { useStripoNotifications as $ } from "./useStripoNotifications.js";
9
9
  import { useToaster as G } from "./useToaster.js";
10
10
  import { localePatch as J } from "../config/i18n/index.js";
11
- import { en as w } from "../config/i18n/en/index.js";
11
+ import { en as b } from "../config/i18n/en/index.js";
12
12
  import { ToasterTypeOptions as X } from "../enums/toaster.js";
13
13
  import { useStripoApi as K } from "../services/stripoApi.js";
14
14
  import Q from "../static/styles/customEditorStyle.css.js";
15
- import { useEditorStore as b } from "../stores/editor.js";
15
+ import { useEditorStore as k } 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 } = O(), { handleError: p, showToaster: k } = G(), { getToken: B, getCustomFonts: M, getSyncModulesStatus: T } = K(), { handleEvent: v } = z(), { handleModuleAdd: F } = j(), { getStripoBlocksConfig: A } = L(), { getStripoNotifications: V } = $(), f = () => n || (n = new Promise((i, s) => {
19
+ const he = () => {
20
+ const { features: c, template: u, isFeatureEnabled: p } = H(), { handleError: m, showToaster: v } = G(), { getToken: B, getCustomFonts: M, getSyncModulesStatus: T } = K(), { handleEvent: F } = z(), { handleModuleAdd: A } = j(), { getStripoBlocksConfig: V } = O(), { getStripoNotifications: _ } = $(), f = () => n || (n = new Promise((r, s) => {
21
21
  var d;
22
22
  if (document.getElementById("UiEditorScript")) {
23
- i();
23
+ r();
24
24
  return;
25
25
  }
26
- const o = Z.guido, r = `https://email-static.useinsider.com/guido/${(d = o == null ? void 0 : o.stripo) == null ? void 0 : d.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}`));
26
+ const o = Z.guido, i = `https://email-static.useinsider.com/guido/${(d = o == null ? void 0 : o.stripo) == null ? void 0 : d.version}/UIEditor.js`, e = document.createElement("script");
27
+ e.id = "UiEditorScript", e.type = "module", e.src = i, e.onload = () => r(), e.onerror = () => {
28
+ e.remove(), s(new Error(`Failed to load Stripo UIEditor script from S3: ${i}`));
29
29
  }, document.body.appendChild(e);
30
30
  }), n.catch(() => {
31
31
  n = null;
32
- }), n), _ = async (i, s, o, a = [], r = !1) => {
32
+ }), n), D = async (r, s, o, a = [], i = !1) => {
33
33
  var y, E, h, C;
34
- const e = b(), { html: d, 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 = !!d || (((h = u.value) == null ? void 0 : h.forceRecreate) ?? !1);
35
- await window.UIEditor.initEditor(
34
+ const e = k(), { html: d, css: R } = r, { baseBlocks: g, extensions: P } = await V(), S = ((y = c.value) == null ? void 0 : y.displayConditions) ?? !0, U = ((E = c.value) == null ? void 0 : E.modulesDisabled) ?? !1, I = !!d || (((h = u.value) == null ? void 0 : h.forceRecreate) ?? !1), q = "https://email-static.useinsider.com https://edge.fullstory.com https://rs.fullstory.com";
35
+ w().importCss(), await window.UIEditor.initEditor(
36
36
  document.querySelector("#guido-editor"),
37
37
  {
38
38
  metadata: s,
39
39
  html: d,
40
- css: D,
41
- forceRecreate: U,
40
+ css: R,
41
+ forceRecreate: I,
42
42
  locale: "en",
43
43
  undoButtonSelector: "#guido__undo-button",
44
44
  redoButtonSelector: "#guido__redo-button",
45
45
  mobileViewButtonSelector: ".guido__view-option-selection-mobile",
46
46
  desktopViewButtonSelector: ".guido__view-option-selection-desktop",
47
47
  codeEditorButtonSelector: "#guido__code-button",
48
- customAppearanceMergetags: !m("liquidSyntax"),
48
+ customAppearanceMergetags: !p("liquidSyntax"),
49
49
  customAppearanceMergetagsBorderColor: "#f1f3fe",
50
50
  customAppearanceMergetagsBackgroundColor: "#f1f3fe",
51
51
  customViewStyles: Q,
52
52
  conditionsEnabled: S,
53
53
  customConditionsEnabled: S,
54
54
  enableXSSSecurity: !0,
55
- modulesDisabled: P,
56
- syncModulesEnabled: r,
55
+ modulesDisabled: U,
56
+ syncModulesEnabled: i,
57
57
  messageSettingsEnabled: !0,
58
58
  displayGmailAnnotations: !0,
59
59
  displayHiddenPreheader: !1,
@@ -62,7 +62,7 @@ const Ce = () => {
62
62
  displayUTM: !1,
63
63
  selectElementAfterDrop: !0,
64
64
  sameFontSizeForOutlook: !0,
65
- allowedScriptSourceDomains: "https://email-static.useinsider.com https://edge.fullstory.com https://rs.fullstory.com",
65
+ allowedScriptSourceDomains: q,
66
66
  ...g ? { baseBlocks: g } : {},
67
67
  editorFonts: {
68
68
  showDefaultStandardFonts: !0,
@@ -74,7 +74,7 @@ const Ce = () => {
74
74
  entries: W(
75
75
  o.preselectedDynamicContentList,
76
76
  Y((C = u.value) == null ? void 0 : C.dynamicContentList),
77
- m("liquidSyntax")
77
+ p("liquidSyntax")
78
78
  )
79
79
  }
80
80
  ],
@@ -83,17 +83,17 @@ const Ce = () => {
83
83
  const l = await B();
84
84
  t(l);
85
85
  } catch (l) {
86
- p(l, "Failed to refresh token");
86
+ m(l, "Failed to refresh token");
87
87
  }
88
88
  },
89
89
  onTemplateLoaded() {
90
90
  try {
91
- const { importCss: t } = H(), { activateCustomViewStyles: l, updateTimerInClonedTemplate: I } = x(), { injectFullStory: q } = N();
92
- t(), l(), q(), I(), o.onReady(), e.isStripoInitialized = !0, e.loadingStatus = !1, setTimeout(() => {
91
+ const { activateCustomViewStyles: t, updateTimerInClonedTemplate: l } = L(), { injectFullStory: x } = N();
92
+ w().importCss(), t(), x(), l(), o.onReady(), e.isStripoInitialized = !0, e.loadingStatus = !1, setTimeout(() => {
93
93
  e.hasChanges = !1;
94
94
  }, 1e3);
95
95
  } catch (t) {
96
- p(t, "Failed to load custom interface appearance");
96
+ m(t, "Failed to load custom interface appearance");
97
97
  }
98
98
  },
99
99
  onCodeEditorVisibilityChanged(t) {
@@ -108,34 +108,38 @@ const Ce = () => {
108
108
  onDataChanged() {
109
109
  e.hasChanges = !0, e.changeSeq += 1;
110
110
  },
111
- onEvent: v,
112
- onModuleAdd: F,
113
- notifications: V(),
111
+ onEvent: F,
112
+ onModuleAdd: A,
113
+ notifications: _(),
114
+ // Stripo deselects the block on any click outside the canvas, so every surface
115
+ // that belongs to the block's own flow has to be listed here (SD-153273).
114
116
  ignoreClickOutsideSelectors: [
115
117
  "#guido-dynamic-content-modal",
116
118
  ".in-on-board-wrapper",
117
- ".in-drawer__container"
119
+ ".in-drawer__container",
120
+ ".in-modal-v2-wrapper",
121
+ ".in-toasts-wrapper"
118
122
  ],
119
- extensions: R,
123
+ extensions: P,
120
124
  localePatch: J
121
125
  }
122
126
  );
123
127
  };
124
- return { initPlugin: async (i, s, o) => {
125
- const a = b();
128
+ return { initPlugin: async (r, s, o) => {
129
+ const a = k();
126
130
  try {
127
131
  await f();
128
- const [r, e] = await Promise.all([
132
+ const [i, e] = await Promise.all([
129
133
  M(),
130
134
  T()
131
135
  ]);
132
- a.syncModulesEnabled = e, await _(i, s, o, r, e);
136
+ a.syncModulesEnabled = e, await D(r, s, o, i, e);
133
137
  } catch {
134
- a.loadingStatus = !1, k({
138
+ a.loadingStatus = !1, v({
135
139
  type: X.Error,
136
- message: w["An error has occurred. Please report the error code to support."],
140
+ message: b["An error has occurred. Please report the error code to support."],
137
141
  actionButton: {
138
- text: w["Reload page"],
142
+ text: b["Reload page"],
139
143
  onClick: () => window.location.reload()
140
144
  }
141
145
  });
@@ -146,5 +150,5 @@ const Ce = () => {
146
150
  } };
147
151
  };
148
152
  export {
149
- Ce as useStripo
153
+ he as useStripo
150
154
  };