@useinsider/guido 3.2.0 → 3.3.0

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 (144) hide show
  1. package/README.md +117 -1
  2. package/dist/@types/config/schemas.js +153 -95
  3. package/dist/components/Guido.vue.js +4 -4
  4. package/dist/components/Guido.vue2.js +90 -88
  5. package/dist/components/organisms/AutoSaveController.vue.js +17 -0
  6. package/dist/components/organisms/AutoSaveController.vue2.js +13 -0
  7. package/dist/components/organisms/header/AutoSaveToggle.vue.js +22 -0
  8. package/dist/components/organisms/header/AutoSaveToggle.vue2.js +19 -0
  9. package/dist/components/organisms/header/RightSlot.vue.js +8 -8
  10. package/dist/components/organisms/header/RightSlot.vue2.js +9 -8
  11. package/dist/components/organisms/onboarding/AMPOnboarding.vue2.js +51 -31
  12. package/dist/components/organisms/onboarding/GenericOnboarding.vue.js +1 -1
  13. package/dist/components/organisms/onboarding/GenericOnboarding.vue2.js +23 -22
  14. package/dist/components/organisms/onboarding/ItemsOnboarding.vue.js +1 -1
  15. package/dist/components/organisms/onboarding/ItemsOnboarding.vue2.js +37 -39
  16. package/dist/components/organisms/onboarding/TextBlockOnboarding.vue.js +3 -3
  17. package/dist/components/organisms/onboarding/TextBlockOnboarding.vue2.js +30 -41
  18. package/dist/components/organisms/onboarding/VersionHistoryOnboarding.vue2.js +15 -14
  19. package/dist/composables/useActionsApi.js +4 -4
  20. package/dist/composables/useAutoSave.js +71 -0
  21. package/dist/composables/useFullStoryBridge.js +14 -0
  22. package/dist/composables/useRecommendation.js +46 -26
  23. package/dist/composables/useRibbonOffset.js +21 -0
  24. package/dist/composables/useSave.js +19 -16
  25. package/dist/composables/useStripo.js +40 -40
  26. package/dist/composables/validators/useCouponBlockValidator.js +24 -0
  27. package/dist/config/compiler/recommendationCompilerRules.js +79 -74
  28. package/dist/config/compiler/unsubscribeCompilerRules.js +40 -37
  29. package/dist/config/compiler/utils/recommendationCompilerUtils.js +107 -71
  30. package/dist/config/migrator/index.js +9 -9
  31. package/dist/config/migrator/radioButtonMigrator.js +64 -44
  32. package/dist/config/migrator/recommendation/compositionMapper.js +98 -0
  33. package/dist/config/migrator/recommendation/extractors.js +27 -0
  34. package/dist/config/migrator/recommendation/htmlBuilder.js +496 -0
  35. package/dist/config/migrator/recommendation/parseLegacyConfig.js +33 -0
  36. package/dist/config/migrator/recommendation/settingsMapper.js +70 -0
  37. package/dist/config/migrator/recommendation/themeMapper.js +93 -0
  38. package/dist/config/migrator/recommendationMigrator.js +74 -290
  39. package/dist/enums/extensions/recommendationBlock.js +2 -1
  40. package/dist/enums/onboarding.js +7 -2
  41. package/dist/enums/unsubscribe.js +34 -27
  42. package/dist/extensions/Blocks/Items/controls/price/singlePrice.js +38 -38
  43. package/dist/extensions/Blocks/Items/enums/productEnums.js +19 -7
  44. package/dist/extensions/Blocks/RadioButton/template.js +1 -1
  45. package/dist/extensions/Blocks/Recommendation/block.js +35 -32
  46. package/dist/extensions/Blocks/Recommendation/constants/controlIds.js +1 -1
  47. package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +5 -5
  48. package/dist/extensions/Blocks/Recommendation/controls/customAttribute/index.js +21 -18
  49. package/dist/extensions/Blocks/Recommendation/controls/customAttribute/textTrim.js +99 -0
  50. package/dist/extensions/Blocks/Recommendation/controls/main/algorithm.js +27 -26
  51. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +3 -1
  52. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +228 -181
  53. package/dist/extensions/Blocks/Recommendation/controls/name/textTrim.js +27 -57
  54. package/dist/extensions/Blocks/Recommendation/controls/shared/textTrimCssRules.js +14 -0
  55. package/dist/extensions/Blocks/Recommendation/services/configService.js +65 -29
  56. package/dist/extensions/Blocks/Recommendation/settingsPanel.js +18 -17
  57. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +123 -79
  58. package/dist/extensions/Blocks/Recommendation/templates/grid/elementRenderer.js +19 -10
  59. package/dist/extensions/Blocks/Recommendation/templates/grid/template.js +8 -8
  60. package/dist/extensions/Blocks/Recommendation/templates/list/elementRenderer.js +25 -15
  61. package/dist/extensions/Blocks/Recommendation/templates/list/template.js +11 -11
  62. package/dist/extensions/Blocks/Recommendation/templates/utils.js +1 -1
  63. package/dist/extensions/Blocks/Recommendation/utils/filterUtil.js +17 -14
  64. package/dist/extensions/Blocks/Recommendation/utils/legacyStrategyMap.js +21 -0
  65. package/dist/extensions/Blocks/Recommendation/utils/preserveTextStyles.js +13 -22
  66. package/dist/extensions/Blocks/Unsubscribe/block.js +11 -11
  67. package/dist/guido.css +1 -1
  68. package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js +393 -264
  69. package/dist/node_modules/valibot/dist/index.js +450 -235
  70. package/dist/package.json.js +1 -1
  71. package/dist/services/templateLibraryApi.js +5 -4
  72. package/dist/src/@types/config/defaults.d.ts +5 -1
  73. package/dist/src/@types/config/index.d.ts +3 -3
  74. package/dist/src/@types/config/schemas.d.ts +217 -0
  75. package/dist/src/@types/config/types.d.ts +9 -1
  76. package/dist/src/components/Guido.vue.d.ts +1 -1
  77. package/dist/src/components/organisms/AutoSaveController.vue.d.ts +2 -0
  78. package/dist/src/components/organisms/header/AutoSaveToggle.vue.d.ts +2 -0
  79. package/dist/src/components/organisms/header/EditorActions.vue.d.ts +1 -1
  80. package/dist/src/components/organisms/header/HeaderWrapper.vue.d.ts +1 -1
  81. package/dist/src/components/organisms/header/RightSlot.vue.d.ts +1 -1
  82. package/dist/src/components/wrappers/WpModal.vue.d.ts +1 -1
  83. package/dist/src/composables/useActionsApi.d.ts +1 -1
  84. package/dist/src/composables/useAutoSave.d.ts +3 -0
  85. package/dist/src/composables/useConfig.d.ts +58 -0
  86. package/dist/src/composables/useFullStoryBridge.d.ts +11 -0
  87. package/dist/src/composables/useRecommendation.d.ts +10 -1
  88. package/dist/src/composables/useRecommendation.test.d.ts +1 -0
  89. package/dist/src/composables/useRibbonOffset.d.ts +4 -0
  90. package/dist/src/composables/useSave.d.ts +1 -1
  91. package/dist/src/composables/validators/useCouponBlockValidator.d.ts +3 -0
  92. package/dist/src/config/migrator/index.d.ts +2 -1
  93. package/dist/src/config/migrator/recommendation/compositionMapper.d.ts +2 -0
  94. package/dist/src/config/migrator/recommendation/compositionMapper.test.d.ts +1 -0
  95. package/dist/src/config/migrator/recommendation/extractors.d.ts +7 -0
  96. package/dist/src/config/migrator/recommendation/extractors.test.d.ts +1 -0
  97. package/dist/src/config/migrator/recommendation/htmlBuilder.d.ts +11 -0
  98. package/dist/src/config/migrator/recommendation/parseLegacyConfig.d.ts +15 -0
  99. package/dist/src/config/migrator/recommendation/parseLegacyConfig.test.d.ts +1 -0
  100. package/dist/src/config/migrator/recommendation/settingsMapper.d.ts +7 -0
  101. package/dist/src/config/migrator/recommendation/settingsMapper.test.d.ts +1 -0
  102. package/dist/src/config/migrator/recommendation/themeMapper.d.ts +5 -0
  103. package/dist/src/config/migrator/recommendation/themeMapper.test.d.ts +1 -0
  104. package/dist/src/config/migrator/recommendation/types.d.ts +205 -0
  105. package/dist/src/config/migrator/recommendationMigrator.d.ts +13 -1
  106. package/dist/src/config/migrator/recommendationMigrator.test.d.ts +1 -0
  107. package/dist/src/enums/onboarding.d.ts +6 -0
  108. package/dist/src/enums/unsubscribe.d.ts +5 -0
  109. package/dist/src/extensions/Blocks/RadioButton/template.d.ts +1 -1
  110. package/dist/src/extensions/Blocks/Recommendation/constants/controlIds.d.ts +1 -0
  111. package/dist/src/extensions/Blocks/Recommendation/controls/customAttribute/index.d.ts +3 -0
  112. package/dist/src/extensions/Blocks/Recommendation/controls/customAttribute/textTrim.d.ts +35 -0
  113. package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.test.d.ts +1 -0
  114. package/dist/src/extensions/Blocks/Recommendation/controls/name/textTrim.d.ts +3 -20
  115. package/dist/src/extensions/Blocks/Recommendation/controls/shared/textTrimCssRules.d.ts +29 -0
  116. package/dist/src/extensions/Blocks/Recommendation/services/configService.d.ts +10 -0
  117. package/dist/src/extensions/Blocks/Recommendation/services/configService.test.d.ts +1 -0
  118. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +34 -0
  119. package/dist/src/extensions/Blocks/Recommendation/types/nodeConfig.d.ts +1 -1
  120. package/dist/src/extensions/Blocks/Recommendation/utils/legacyStrategyMap.d.ts +21 -0
  121. package/dist/src/extensions/Blocks/Recommendation/utils/legacyStrategyMap.test.d.ts +1 -0
  122. package/dist/src/extensions/Blocks/Recommendation/utils/preserveTextStyles.d.ts +0 -3
  123. package/dist/src/library.d.ts +1 -1
  124. package/dist/src/stores/autosave.d.ts +12 -0
  125. package/dist/src/stores/config.d.ts +522 -0
  126. package/dist/src/stores/editor.d.ts +23 -0
  127. package/dist/src/stores/onboarding.d.ts +4 -0
  128. package/dist/src/utils/htmlEscape.d.ts +5 -0
  129. package/dist/src/utils/htmlEscape.test.d.ts +1 -0
  130. package/dist/src/utils/timeUtil.d.ts +8 -0
  131. package/dist/static/styles/components/button.css.js +16 -9
  132. package/dist/static/styles/components/loader.css.js +4 -0
  133. package/dist/static/styles/components/narrow-panel.css.js +52 -0
  134. package/dist/stores/autosave.js +17 -0
  135. package/dist/stores/editor.js +3 -1
  136. package/dist/stores/onboarding.js +4 -0
  137. package/dist/utils/htmlEscape.js +13 -0
  138. package/dist/utils/pairProductVariables.js +89 -88
  139. package/dist/utils/templatePreparation.js +72 -32
  140. package/dist/utils/timeUtil.js +19 -0
  141. package/package.json +7 -3
  142. package/dist/enums/displayConditions.js +0 -80
  143. package/dist/extensions/Blocks/Recommendation/templates/grid/migration.js +0 -251
  144. package/dist/src/enums/displayConditions.d.ts +0 -2
@@ -263,4 +263,27 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
263
263
  templateId: string;
264
264
  syncModulesEnabled: boolean;
265
265
  }>) => boolean;
266
+ isInSaveableState: (state: {
267
+ loadingStatus: boolean;
268
+ isCodeEditorOpen: boolean;
269
+ isSaveAsTemplateDrawerOpen: boolean;
270
+ isVersionHistoryOpen: boolean;
271
+ isPreviewModeOpen: boolean;
272
+ editorVisualMode: string;
273
+ hasChanges: boolean;
274
+ isStripoInitialized: boolean;
275
+ templateId: string;
276
+ syncModulesEnabled: boolean;
277
+ } & import("pinia").PiniaCustomStateProperties<{
278
+ loadingStatus: boolean;
279
+ isCodeEditorOpen: boolean;
280
+ isSaveAsTemplateDrawerOpen: boolean;
281
+ isVersionHistoryOpen: boolean;
282
+ isPreviewModeOpen: boolean;
283
+ editorVisualMode: string;
284
+ hasChanges: boolean;
285
+ isStripoInitialized: boolean;
286
+ templateId: string;
287
+ syncModulesEnabled: boolean;
288
+ }>) => boolean;
266
289
  }, {}>;
@@ -1392,6 +1392,10 @@ export declare const useOnboardingStore: import("pinia").StoreDefinition<"guidoO
1392
1392
  close(type: OnboardingType): Promise<void>;
1393
1393
  next(type: OnboardingType): void;
1394
1394
  previous(type: OnboardingType): void;
1395
+ updateCardPosition(type: OnboardingType, cardIndex: number, position: {
1396
+ top: string;
1397
+ position: string;
1398
+ }): void;
1395
1399
  setConfig(type: OnboardingType, config: OnboardingCardConfig[]): void;
1396
1400
  onDiscoverNowClicked(): Promise<void>;
1397
1401
  onRemindMeLater(): void;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Escape HTML special characters for safe inclusion in attribute values
3
+ * or text content. Use for any string that may contain untrusted input.
4
+ */
5
+ export declare function escapeHtml(text: string): string;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Formats a Date as local time in 24-hour format.
3
+ * Pass `useTimezone = true` to append the UTC offset and city name — useful when the
4
+ * timestamp must clearly communicate the client's timezone.
5
+ * @example formatLocalTime(date) -> 12:20:02
6
+ * @example formatLocalTime(date, true) -> 12:20:02 (UTC+3 Istanbul)
7
+ */
8
+ export declare const formatLocalTime: (date: Date, useTimezone?: boolean) => string;
@@ -1,4 +1,4 @@
1
- const o = `.control-shadow-wrapper:has(.button) {
1
+ const n = `.control-shadow-wrapper:has(.button) {
2
2
  border-radius: 0;
3
3
  box-shadow: none;
4
4
  background-color: transparent;
@@ -99,18 +99,12 @@ ue-check-button.checked:not(.flat-white) input:checked + label .icon-button {
99
99
  color: var(--guido-color-primary-500);
100
100
  }
101
101
 
102
- ue-select.full-width .button {
103
- border: none !important;
104
- background-color: var(--guido-color-neutral-200) !important;
105
- color: var(--guido-color-neutral-800) !important;
106
- }
107
-
108
102
  ue-select.full-width .button .icon-button {
109
103
  color: var(--guido-color-gray-600) !important;
110
104
  }
111
105
 
112
106
  ue-select.full-width .button:hover:not(:disabled,.disabled) {
113
- background-color: var(--guido-color-neutral-100) !important;
107
+ background-color: var(--guido-color-gray-0) !important;
114
108
  }
115
109
 
116
110
  ue-color {
@@ -130,7 +124,20 @@ ue-select-text-input .select-text-input-toggle .button {
130
124
  justify-content: center;
131
125
  background-color: transparent !important;
132
126
  }
127
+
128
+
129
+ .control-shadow-wrapper,
130
+ ue-button:not(.no-shadow,.flat-white),
131
+ ue-toggle:not(.no-shadow,.flat-white),
132
+ :is(ue-popover-toggler,ue-toggle-icon-picker,ue-emoji-toggle),
133
+ .button-group,
134
+ ue-counter:not(.no-shadow),
135
+ :is(ue-select,ue-mergetags,ue-font-family-select):not(.no-shadow),
136
+ ue-check-button:not(.no-shadow,.flat-white) {
137
+ background: none;
138
+ padding: 0;
139
+ }
133
140
  `;
134
141
  export {
135
- o as default
142
+ n as default
136
143
  };
@@ -4,6 +4,10 @@ const n = `ue-loader-component.full-height {
4
4
  z-index: 9;
5
5
  backdrop-filter: blur(2px);
6
6
  }
7
+
8
+ ue-loader-component .service-element.loader {
9
+ box-shadow: var(--guido-color-primary-500) 1px 1px 0 0 !important;
10
+ }
7
11
  `;
8
12
  export {
9
13
  n as default
@@ -28,6 +28,58 @@ ue-stripe-thumb:hover:not(.disabled),
28
28
  border-color: var(--guido-color-primary-500);
29
29
  }
30
30
 
31
+ /* Module search — initial */
32
+ .module-search-container {
33
+ background-color: var(--guido-color-gray-0);
34
+ border: 1px solid var(--guido-color-gray-300);
35
+ border-radius: 4px;
36
+ }
37
+
38
+ .module-search-container .service-element {
39
+ background-color: unset;
40
+ }
41
+
42
+ .module-filter-toggle {
43
+ top: -1px !important;
44
+ right: -1px !important;
45
+ }
46
+
47
+ .module-filter-toggle > .button,
48
+ .module-search-container:hover .module-filter-toggle > .button {
49
+ border: none;
50
+ background: transparent;
51
+ }
52
+
53
+ /* Module search — hover */
54
+ .module-search-container:has(.module-search-chip-input:hover) {
55
+ border-color: var(--guido-color-primary-500);
56
+ }
57
+
58
+ .module-search-container .module-search-chip-input .service-element:hover {
59
+ background-color: var(--guido-color-gray-0);
60
+ border-radius: 4px;
61
+ }
62
+
63
+ .module-search-container .module-filter-toggle:hover > .button {
64
+ background-color: var(--guido-color-gray-1);
65
+ }
66
+
67
+ /* Module search — selected (.on) */
68
+ .module-search-container:has(.module-search-chip-input.on),
69
+ .module-search-container:has(.module-search-chip-input.on):hover {
70
+ border-color: var(--guido-color-primary-500);
71
+ box-shadow: 0 0 0 3px var(--guido-color-primary-200) !important;
72
+ }
73
+
74
+ .module-search-container .module-search-chip-input.on .input-section {
75
+ background-color: unset;
76
+ box-shadow: unset;
77
+ }
78
+
79
+ .module-categories-list .menu-item {
80
+ padding: 8px 20px !important;
81
+ }
82
+
31
83
  .modules-layout-wrapper {
32
84
  padding: 0 16px 16px;
33
85
  grid-row-gap: 16px;
@@ -0,0 +1,17 @@
1
+ import { defineStore as e } from "pinia";
2
+ const t = {
3
+ IDLE: "idle",
4
+ SAVING: "saving",
5
+ SAVED: "saved",
6
+ ERROR: "error"
7
+ }, o = e("guidoAutosave", {
8
+ state: () => ({
9
+ isOn: !1,
10
+ lastSavedAt: null,
11
+ status: t.IDLE
12
+ })
13
+ });
14
+ export {
15
+ t as AUTOSAVE_STATUS,
16
+ o as useAutosaveStore
17
+ };
@@ -25,7 +25,9 @@ const o = e("guidoEditor", {
25
25
  isExportButtonDisabled: (i) => i.loadingStatus || i.isVersionHistoryOpen,
26
26
  isSaveAsButtonDisabled: (i) => i.loadingStatus || i.isVersionHistoryOpen,
27
27
  isTestButtonDisabled: (i) => i.loadingStatus || i.isVersionHistoryOpen,
28
- isSaveButtonDisabled: (i) => i.loadingStatus || i.isVersionHistoryOpen || i.isPreviewModeOpen
28
+ isSaveButtonDisabled: (i) => i.loadingStatus || i.isVersionHistoryOpen || i.isPreviewModeOpen,
29
+ // Autosave
30
+ isInSaveableState: (i) => !i.loadingStatus && !i.isVersionHistoryOpen && !i.isPreviewModeOpen && !i.isCodeEditorOpen
29
31
  }
30
32
  });
31
33
  export {
@@ -71,6 +71,10 @@ const t = () => ({
71
71
  previous(n) {
72
72
  this.onboardings[n].cardIndex > 0 && this.onboardings[n].cardIndex--;
73
73
  },
74
+ updateCardPosition(n, i, o) {
75
+ const s = this.onboardings[n].config[i];
76
+ s && (s.top = o.top, s.position = o.position);
77
+ },
74
78
  setConfig(n, i) {
75
79
  this.onboardings[n].config = i ?? [], this.onboardings[n].cardIndex >= this.onboardings[n].config.length && (this.onboardings[n].cardIndex = 0);
76
80
  },
@@ -0,0 +1,13 @@
1
+ const c = {
2
+ "&": "&amp;",
3
+ "<": "&lt;",
4
+ ">": "&gt;",
5
+ '"': "&quot;",
6
+ "'": "&#x27;"
7
+ };
8
+ function n(t) {
9
+ return t.replace(/[&<>"']/g, (e) => c[e]);
10
+ }
11
+ export {
12
+ n as escapeHtml
13
+ };
@@ -1,84 +1,85 @@
1
- import { productPairs as P } from "../extensions/Blocks/Items/enums/productEnums.js";
2
- function L(F) {
3
- const R = F.replaceAll("{%", "<!--{%").replaceAll("%}", "%}-->"), $ = new DOMParser().parseFromString(R, "text/html"), y = P.PAIRS_FOR_EXTENSION;
4
- Object.entries(y).forEach(([n, l]) => {
5
- $.querySelectorAll(".ins-product-td").forEach((c) => {
6
- const E = c.getAttribute("data-number") || "1", T = c.getAttribute("data-type") || "CART_ITEMS";
7
- c.querySelectorAll(`[product-attr="${n}"]`).forEach((e) => {
8
- var H;
9
- const b = e.getAttribute("data-type") || T, u = e.getAttribute("data-number") || E, p = l[b];
10
- if (p)
11
- switch (n) {
1
+ import { productPairs as L } from "../extensions/Blocks/Items/enums/productEnums.js";
2
+ function q(w) {
3
+ const y = w.replaceAll("{%", "<!--{%").replaceAll("%}", "%}-->"), T = new DOMParser().parseFromString(y, "text/html"), C = L.PAIRS_FOR_EXTENSION;
4
+ Object.entries(C).forEach(([r, f]) => {
5
+ T.querySelectorAll(".ins-product-td").forEach((o) => {
6
+ const A = o.getAttribute("data-number") || "1", b = o.getAttribute("data-type") || "CART_ITEMS";
7
+ o.querySelectorAll(`[product-attr="${r}"]`).forEach((e) => {
8
+ var k, F, I;
9
+ const $ = e.getAttribute("data-type") || b, d = e.getAttribute("data-number") || A, u = f[$];
10
+ if (u)
11
+ switch (r) {
12
12
  case "imageSrc": {
13
- let t = null, o = null;
14
- if (e.tagName === "IMG" ? (t = e, o = t.closest("a")) : (t = e.querySelector("img"), o = e.querySelector("a") || e.closest("a")), !t)
13
+ let t = null, i = null;
14
+ if (e.tagName === "IMG" ? (t = e, i = t.closest("a")) : (t = e.querySelector("img"), i = e.querySelector("a") || e.closest("a")), !t)
15
15
  break;
16
- const i = p.DEFAULT, a = p.ATTR;
17
- if (i && t.src) {
18
- const r = t.src;
19
- i.some((f) => {
20
- const s = f.split("/").pop() || "", _ = r.split("/").pop() || "";
21
- return r.includes(f) || r.includes(s) || _ === s;
22
- }) && (t.src = `{{${a}_${u}}}`);
16
+ const a = u.DEFAULT, s = u.ATTR;
17
+ if (a && t.src) {
18
+ const c = t.src;
19
+ a.some((h) => {
20
+ const l = h.split("/").pop() || "", g = c.split("/").pop() || "";
21
+ return c.includes(h) || c.includes(l) || g === l;
22
+ }) && (t.src = `{{${s}_${d}}}`);
23
23
  }
24
- if (o) {
25
- const r = (H = y.itemLink) == null ? void 0 : H[b];
26
- if (r) {
27
- const d = r.HREF, f = r.DEFAULT_HREF || "#!", s = o.href;
28
- (s === "#" || s === "" || s.endsWith("#!") || s.endsWith(f) || s === `${window.location.href}${f}` || !s || s === window.location.href) && (o.href = `{{${d}_${u}}}`);
24
+ const n = (F = (k = C.name) == null ? void 0 : k[$]) == null ? void 0 : F.ATTR;
25
+ if (n && t.setAttribute("alt", `{{${n}_${d}}}`), i) {
26
+ const c = (I = C.itemLink) == null ? void 0 : I[$];
27
+ if (c) {
28
+ const E = c.HREF, h = c.DEFAULT_HREF || "#!", l = i.href;
29
+ (l === "#" || l === "" || l.endsWith("#!") || l.endsWith(h) || l === `${window.location.href}${h}` || !l || l === window.location.href) && (i.href = `{{${E}_${d}}}`);
29
30
  }
30
31
  }
31
32
  break;
32
33
  }
33
34
  case "name": {
34
- const t = p, o = t.ATTR, i = t.DEFAULT_HREF || "#!", a = t.HREF;
35
- e.textContent && (e.textContent = `{{${o}_${u}}}`);
36
- const r = e.closest("a") || (e.tagName === "A" ? e : null);
37
- if (r && a) {
38
- const d = r.href, f = `${window.location.href}${i}`;
39
- (d === f || d.endsWith(i)) && (r.href = `{{${a}_${u}}}`);
35
+ const t = u, i = t.ATTR, a = t.DEFAULT_HREF || "#!", s = t.HREF;
36
+ e.textContent && (e.textContent = `{{${i}_${d}}}`);
37
+ const n = e.closest("a") || (e.tagName === "A" ? e : null);
38
+ if (n && s) {
39
+ const c = n.href, E = `${window.location.href}${a}`;
40
+ (c === E || c.endsWith(a)) && (n.href = `{{${s}_${d}}}`);
40
41
  }
41
42
  break;
42
43
  }
43
44
  case "price":
44
45
  case "originalPrice": {
45
- const t = p, o = e.getAttribute("data-formated"), i = e.getAttribute("data-single_price"), a = o === "true", r = i === "true", d = e.getAttribute("data-curency") || "before";
46
- let f;
47
- r ? f = a ? t.SINGLE_PRICE_FORMATTED : t.SINGLE_PRICE : f = a ? t.PRICE_FORMATTED : t.PRICE;
48
- const s = t.CURRENCY;
49
- let _ = `{{${f}_${u}}}`;
50
- if (s) {
51
- const k = `{{${s}_${u}}}`;
52
- _ = d === "after" ? `${_} ${k}` : `${k} ${_}`;
46
+ const t = u, i = e.getAttribute("data-formated"), a = e.getAttribute("data-single_price"), s = i === "true", n = a === "true", c = e.getAttribute("data-curency") || "before";
47
+ let E;
48
+ n ? E = s ? t.SINGLE_PRICE_FORMATTED : t.SINGLE_PRICE : E = s ? t.PRICE_FORMATTED : t.PRICE;
49
+ const h = t.CURRENCY;
50
+ let l = `{{${E}_${d}}}`;
51
+ if (h) {
52
+ const g = `{{${h}_${d}}}`;
53
+ l = c === "after" ? `${l} ${g}` : `${g} ${l}`;
53
54
  }
54
- e.textContent = _;
55
+ e.textContent = l;
55
56
  break;
56
57
  }
57
58
  case "quantity": {
58
- const t = p, o = t.ATTR, i = t.DEFAULT;
59
- e.textContent && e.textContent.trim() === i && (e.textContent = `{{${o}_${u}}}`);
59
+ const t = u, i = t.ATTR, a = t.DEFAULT;
60
+ e.textContent && e.textContent.trim() === a && (e.textContent = `{{${i}_${d}}}`);
60
61
  break;
61
62
  }
62
63
  case "button": {
63
- const t = p, o = t.HREF, i = t.DEFAULT_HREF || "#!", a = e.tagName === "A" ? e : e.querySelector("a");
64
- if (a) {
65
- const r = a.href || "", d = `${window.location.href}${i}`;
66
- (r === "" || r === "#" || r === d || r.endsWith(i) || r.endsWith("#!") || r === window.location.href) && (a.href = `{{${o}_${u}}}`);
64
+ const t = u, i = t.HREF, a = t.DEFAULT_HREF || "#!", s = e.tagName === "A" ? e : e.querySelector("a");
65
+ if (s) {
66
+ const n = s.href || "", c = `${window.location.href}${a}`;
67
+ (n === "" || n === "#" || n === c || n.endsWith(a) || n.endsWith("#!") || n === window.location.href) && (s.href = `{{${i}_${d}}}`);
67
68
  }
68
69
  break;
69
70
  }
70
71
  case "itemLink": {
71
- const t = p, o = t.HREF, i = t.DEFAULT_HREF || "#!", a = e;
72
- if (a.href) {
73
- const r = a.href, d = `${window.location.href}${i}`;
74
- (r === d || r.endsWith(i)) && (a.href = `{{${o}_${u}}}`);
72
+ const t = u, i = t.HREF, a = t.DEFAULT_HREF || "#!", s = e;
73
+ if (s.href) {
74
+ const n = s.href, c = `${window.location.href}${a}`;
75
+ (n === c || n.endsWith(a)) && (s.href = `{{${i}_${d}}}`);
75
76
  }
76
77
  break;
77
78
  }
78
79
  default: {
79
- if ("ATTR" in p) {
80
- const t = p.ATTR;
81
- e.textContent && (e.textContent = `{{${t}_${u}}}`);
80
+ if ("ATTR" in u) {
81
+ const t = u.ATTR;
82
+ e.textContent && (e.textContent = `{{${t}_${d}}}`);
82
83
  }
83
84
  break;
84
85
  }
@@ -86,55 +87,55 @@ function L(F) {
86
87
  });
87
88
  });
88
89
  });
89
- const S = R.match(/<!DOCTYPE[^>]*>/i), I = S ? `${S[0]}
90
- ` : "", w = $.querySelectorAll(".ins-product-td"), m = [];
91
- w.forEach((n) => {
92
- const l = n.getAttribute("data-type") || "CART_ITEMS", A = n.getAttribute("data-number") || "1", c = n.getAttribute("data-nodup"), E = n.outerHTML;
93
- m.push({
94
- element: n,
95
- outerHtml: E,
96
- type: l,
97
- number: A,
98
- nodup: c || void 0
90
+ const S = y.match(/<!DOCTYPE[^>]*>/i), M = S ? `${S[0]}
91
+ ` : "", P = T.querySelectorAll(".ins-product-td"), H = [];
92
+ P.forEach((r) => {
93
+ const f = r.getAttribute("data-type") || "CART_ITEMS", p = r.getAttribute("data-number") || "1", o = r.getAttribute("data-nodup"), A = r.outerHTML;
94
+ H.push({
95
+ element: r,
96
+ outerHtml: A,
97
+ type: f,
98
+ number: p,
99
+ nodup: o || void 0
99
100
  });
100
101
  });
101
- let h = I + $.documentElement.outerHTML;
102
- m.reverse().forEach(({ outerHtml: n, type: l, number: A }) => {
103
- let c = "";
104
- switch (l) {
102
+ let _ = M + T.documentElement.outerHTML;
103
+ H.reverse().forEach(({ outerHtml: r, type: f, number: p }) => {
104
+ let o = "";
105
+ switch (f) {
105
106
  case "CART_ITEMS":
106
- c = "ins_apr_total_product_kind";
107
+ o = "ins_apr_total_product_kind";
107
108
  break;
108
109
  case "BROWSED_ITEMS":
109
- c = "browsed_item_total_product_kind";
110
+ o = "browsed_item_total_product_kind";
110
111
  break;
111
112
  case "PURCHASED_ITEMS":
112
- c = "purchased_item_total_product_kind";
113
+ o = "purchased_item_total_product_kind";
113
114
  break;
114
115
  }
115
- if (c) {
116
- const T = parseInt(A) - 1, b = `${`{% if ${c} > ${T} %}`}${n}{% endif %}`;
117
- h = h.replace(n, b);
116
+ if (o) {
117
+ const b = parseInt(p) - 1, $ = `${`{% if ${o} > ${b} %}`}${r}{% endif %}`;
118
+ _ = _.replace(r, $);
118
119
  }
119
120
  });
120
- const M = $.querySelectorAll('[product-attr="originalPrice"][data-type="CART_ITEMS"]'), g = [];
121
- return M.forEach((n) => {
122
- const l = n.getAttribute("data-number"), A = n.getAttribute("data-type");
123
- if (!l || A !== "CART_ITEMS")
121
+ const D = T.querySelectorAll('[product-attr="originalPrice"][data-type="CART_ITEMS"]'), R = [];
122
+ return D.forEach((r) => {
123
+ const f = r.getAttribute("data-number"), p = r.getAttribute("data-type");
124
+ if (!f || p !== "CART_ITEMS")
124
125
  return;
125
- const c = n.closest(".product-original-price-class");
126
- if (c) {
127
- const E = c.outerHTML;
128
- g.some((C) => C.tdOuterHtml === E) || g.push({ tdOuterHtml: E, number: l });
126
+ const o = r.closest(".product-original-price-class");
127
+ if (o) {
128
+ const A = o.outerHTML;
129
+ R.some((m) => m.tdOuterHtml === A) || R.push({ tdOuterHtml: A, number: f });
129
130
  }
130
- }), g.reverse().forEach(({ tdOuterHtml: n, number: l }) => {
131
- const A = `{% if ins_apr_price_${l} != ins_apr_originalprice_${l} %}`;
132
- if (!h.includes(A) && !n.includes("{% if")) {
133
- const E = `${A}${n}{% endif %}`;
134
- h = h.replace(n, E);
131
+ }), R.reverse().forEach(({ tdOuterHtml: r, number: f }) => {
132
+ const p = `{% if ins_apr_price_${f} != ins_apr_originalprice_${f} %}`;
133
+ if (!_.includes(p) && !r.includes("{% if")) {
134
+ const A = `${p}${r}{% endif %}`;
135
+ _ = _.replace(r, A);
135
136
  }
136
- }), h.replaceAll("<!--{%", "{%").replaceAll("%}-->", "%}").replaceAll("&lt;!--{%", "{%").replaceAll("%}--&gt;", "%}");
137
+ }), _.replaceAll("<!--{%", "{%").replaceAll("%}-->", "%}").replaceAll("&lt;!--{%", "{%").replaceAll("%}--&gt;", "%}");
137
138
  }
138
139
  export {
139
- L as pairProductVariables
140
+ q as pairProductVariables
140
141
  };
@@ -1,53 +1,93 @@
1
1
  import { useActionsApi as T } from "../composables/useActionsApi.js";
2
- import { useHtmlCompiler as P } from "../composables/useHtmlCompiler.js";
3
- import { useRecommendationExtensionStore as A } from "../extensions/Blocks/Recommendation/store/recommendation.js";
4
- import { DATA_ATTRIBUTES as l } from "../extensions/Blocks/Unsubscribe/utils/constants.js";
5
- import { parsePageList as h } from "../extensions/Blocks/Unsubscribe/utils/utils.js";
6
- import { useDynamicContentStore as C } from "../stores/dynamic-content.js";
7
- import { useUnsubscribeStore as D } from "../stores/unsubscribe.js";
8
- function x(i, e) {
9
- const r = new DOMParser().parseFromString(i, "text/html").querySelectorAll(`[${l.PAGE_LIST}]`), n = [];
10
- return r.forEach((t) => {
11
- const o = t.getAttribute(l.PAGE_LIST);
12
- o && n.push(...h(o));
13
- }), e.filter((t) => n.includes(t));
2
+ import { useHtmlCompiler as C } from "../composables/useHtmlCompiler.js";
3
+ import { DEFAULT_CURRENCY as l, DEFAULT_NODE_CONFIG as a } from "../extensions/Blocks/Recommendation/constants/defaultConfig.js";
4
+ import { useRecommendationExtensionStore as b } from "../extensions/Blocks/Recommendation/store/recommendation.js";
5
+ import { DATA_ATTRIBUTES as y } from "../extensions/Blocks/Unsubscribe/utils/constants.js";
6
+ import { parsePageList as P } from "../extensions/Blocks/Unsubscribe/utils/utils.js";
7
+ import { useDynamicContentStore as D } from "../stores/dynamic-content.js";
8
+ import { useUnsubscribeStore as E } from "../stores/unsubscribe.js";
9
+ function U(i, r) {
10
+ const s = new DOMParser().parseFromString(i, "text/html").querySelectorAll(`[${y.PAGE_LIST}]`), c = [];
11
+ return s.forEach((t) => {
12
+ const o = t.getAttribute(y.PAGE_LIST);
13
+ o && c.push(...P(o));
14
+ }), r.filter((t) => c.includes(t));
14
15
  }
15
- const I = () => {
16
- const i = C(), e = D(), { getCompiledEmail: a, getTemplateData: m } = T(), { compileHtml: r } = P();
16
+ function F(i) {
17
+ const m = new DOMParser().parseFromString(i, "text/html").querySelectorAll(".recommendation-block-v2");
18
+ if (m.length === 0)
19
+ return;
20
+ const d = b();
21
+ m.forEach((s) => {
22
+ var g, f, u, n, S;
23
+ const c = s.getAttribute("recommendation-id"), t = c ? Number(c) : NaN;
24
+ if (!Number.isFinite(t))
25
+ return;
26
+ const o = s.getAttribute("esd-ext-config");
27
+ if (!o)
28
+ return;
29
+ let e;
30
+ try {
31
+ e = JSON.parse(o);
32
+ } catch {
33
+ return;
34
+ }
35
+ if (!e || typeof e != "object" || Array.isArray(e))
36
+ return;
37
+ const p = {
38
+ strategy: e.strategy ?? a.strategy,
39
+ language: e.language ?? a.language,
40
+ size: e.size ?? a.size,
41
+ // Spread the default arrays so each block gets a fresh reference
42
+ // instead of sharing the singleton in DEFAULT_NODE_CONFIG.
43
+ productIds: e.productIds ?? [...a.productIds],
44
+ filters: e.filters ?? [...a.filters],
45
+ shuffleProducts: e.shuffleProducts ?? a.shuffleProducts,
46
+ currencyCode: ((g = e.currency) == null ? void 0 : g.code) ?? l.code,
47
+ currencyAlignment: ((f = e.currency) == null ? void 0 : f.alignment) ?? l.alignment,
48
+ currencyDecimalCount: ((u = e.currency) == null ? void 0 : u.decimalCount) ?? l.decimalCount,
49
+ currencyDecimalSeparator: ((n = e.currency) == null ? void 0 : n.decimalSeparator) ?? l.decimalSeparator,
50
+ currencyThousandSeparator: ((S = e.currency) == null ? void 0 : S.thousandSeparator) ?? l.thousandSeparator
51
+ };
52
+ d.seedBlockUrlConfig(t, p);
53
+ });
54
+ }
55
+ const _ = () => {
56
+ const i = D(), r = E(), { getCompiledEmail: m, getTemplateData: d } = T(), { compileHtml: s } = C();
17
57
  return {
18
58
  prepareTemplateDetails: async () => {
19
- const { html: t, ampHtml: o = "", ampErrors: p = [] } = await a({
59
+ const { html: t, ampHtml: o = "", ampErrors: e = [] } = await m({
20
60
  minimize: !0,
21
61
  resetDataSavedFlag: !1
22
- }), { html: u, css: d, syncModulesIds: g = [] } = await m();
23
- e.selectedUnsubscribePages.length && await e.fetchTemplates();
24
- const { compiledHtml: c, stats: s, appliedRules: S } = r(t), b = i.getSelectedDynamicContentList, f = A();
62
+ }), { html: p, css: g, syncModulesIds: f = [] } = await d();
63
+ r.selectedUnsubscribePages.length && await r.fetchTemplates(), F(p);
64
+ const { compiledHtml: u, stats: n, appliedRules: S } = s(t), h = i.getSelectedDynamicContentList, A = b();
25
65
  return console.debug("HTML Compilation Stats:", {
26
- originalSize: s.originalSize,
27
- compiledSize: s.compiledSize,
28
- reduction: `${s.reductionPercentage.toFixed(2)}%`,
66
+ originalSize: n.originalSize,
67
+ compiledSize: n.compiledSize,
68
+ reduction: `${n.reductionPercentage.toFixed(2)}%`,
29
69
  appliedRules: S,
30
- executionTime: `${s.executionTime.toFixed(2)}ms`
70
+ executionTime: `${n.executionTime.toFixed(2)}ms`
31
71
  }), {
32
- dynamicContentList: b,
33
- compiledHtml: c,
34
- rawHtml: u,
35
- css: d,
72
+ dynamicContentList: h,
73
+ compiledHtml: u,
74
+ rawHtml: p,
75
+ css: g,
36
76
  ampHtml: o,
37
- ampErrors: p,
38
- modules: g.map(Number),
77
+ ampErrors: e,
78
+ modules: f.map(Number),
39
79
  recommendation: {
40
- campaignUrls: f.recommendationCampaignUrls,
80
+ campaignUrls: A.recommendationCampaignUrls,
41
81
  configs: {}
42
82
  },
43
83
  unsubscribe: {
44
- status: e.unsubscribePagesStatus,
45
- config: x(c, e.selectedUnsubscribePages)
84
+ status: r.unsubscribePagesStatus,
85
+ config: U(u, r.selectedUnsubscribePages)
46
86
  }
47
87
  };
48
88
  }
49
89
  };
50
90
  };
51
91
  export {
52
- I as useTemplatePreparation
92
+ _ as useTemplatePreparation
53
93
  };
@@ -0,0 +1,19 @@
1
+ const r = (t) => {
2
+ const e = -t.getTimezoneOffset(), o = e >= 0 ? "+" : "-", n = Math.abs(e), s = Math.floor(n / 60), i = n % 60;
3
+ return i === 0 ? `UTC${o}${s}` : `UTC${o}${s}:${String(i).padStart(2, "0")}`;
4
+ }, a = () => {
5
+ var e;
6
+ const { timeZone: t } = new Intl.DateTimeFormat().resolvedOptions();
7
+ return ((e = t.split("/").pop()) == null ? void 0 : e.replace(/_/g, " ")) ?? t;
8
+ }, c = (t, e = !1) => {
9
+ const o = t.toLocaleTimeString([], {
10
+ hour: "2-digit",
11
+ hour12: !1,
12
+ minute: "2-digit",
13
+ second: "2-digit"
14
+ });
15
+ return e ? `${o} (${r(t)} ${a()})` : o;
16
+ };
17
+ export {
18
+ c as formatLocalTime
19
+ };