@useinsider/guido 3.1.1 → 3.2.0-beta.1949a28

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 (104) hide show
  1. package/README.md +1 -0
  2. package/dist/@types/config/schemas.js +66 -54
  3. package/dist/components/Guido.vue.js +4 -4
  4. package/dist/components/Guido.vue2.js +91 -81
  5. package/dist/components/organisms/email-preview/desktop-preview/EmailSizeIndicator.vue.js +7 -7
  6. package/dist/components/organisms/email-preview/desktop-preview/EmailSizeIndicator.vue2.js +12 -20
  7. package/dist/components/organisms/header/EditorActions.vue.js +2 -2
  8. package/dist/components/organisms/header/EditorActions.vue2.js +51 -36
  9. package/dist/components/organisms/header/RightSlot.vue.js +10 -10
  10. package/dist/components/organisms/header/RightSlot.vue2.js +16 -13
  11. package/dist/components/organisms/save-as-template/SaveAsTemplateDrawer.vue2.js +18 -17
  12. package/dist/composables/useActionsApi.js +4 -4
  13. package/dist/composables/useFullStoryBridge.js +14 -0
  14. package/dist/composables/useHtmlCompiler.js +23 -21
  15. package/dist/composables/useHtmlValidator.js +40 -38
  16. package/dist/composables/usePreviewMode.js +20 -16
  17. package/dist/composables/useSave.js +23 -15
  18. package/dist/composables/useStripo.js +52 -47
  19. package/dist/composables/validators/useLiquidValidator.js +42 -0
  20. package/dist/config/compiler/liquidCompilerRules.js +15 -0
  21. package/dist/config/compiler/recommendationCompilerRules.js +162 -43
  22. package/dist/config/compiler/unsubscribeCompilerRules.js +37 -37
  23. package/dist/config/compiler/utils/recommendationCompilerUtils.js +52 -46
  24. package/dist/config/i18n/en/tooltips.json.js +2 -1
  25. package/dist/config/migrator/checkboxMigrator.js +5 -3
  26. package/dist/config/migrator/radioButtonMigrator.js +66 -44
  27. package/dist/config/migrator/recommendationMigrator.js +1 -1
  28. package/dist/enums/extensions/recommendationBlock.js +14 -11
  29. package/dist/enums/recommendation.js +2 -2
  30. package/dist/extensions/Blocks/CouponBlock/template.js +24 -13
  31. package/dist/extensions/Blocks/Items/controls/price/singlePrice.js +38 -38
  32. package/dist/extensions/Blocks/Items/enums/productEnums.js +19 -7
  33. package/dist/extensions/Blocks/RadioButton/template.js +1 -1
  34. package/dist/extensions/Blocks/Recommendation/block.js +1 -1
  35. package/dist/extensions/Blocks/Recommendation/constants/controlIds.js +1 -1
  36. package/dist/extensions/Blocks/Recommendation/constants/selectors.js +27 -11
  37. package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +185 -172
  38. package/dist/extensions/Blocks/Recommendation/controls/customAttribute/index.js +21 -18
  39. package/dist/extensions/Blocks/Recommendation/controls/customAttribute/textTrim.js +99 -0
  40. package/dist/extensions/Blocks/Recommendation/controls/main/algorithm.js +6 -6
  41. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +3 -1
  42. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +95 -93
  43. package/dist/extensions/Blocks/Recommendation/controls/name/textTrim.js +27 -57
  44. package/dist/extensions/Blocks/Recommendation/controls/shared/textTrimCssRules.js +14 -0
  45. package/dist/extensions/Blocks/Recommendation/controls/spacing/index.js +75 -73
  46. package/dist/extensions/Blocks/Recommendation/settingsPanel.js +18 -17
  47. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +29 -25
  48. package/dist/extensions/Blocks/Recommendation/templates/grid/elementRenderer.js +7 -5
  49. package/dist/extensions/Blocks/Recommendation/templates/grid/template.js +30 -29
  50. package/dist/extensions/Blocks/Recommendation/templates/index.js +7 -7
  51. package/dist/extensions/Blocks/Recommendation/templates/list/elementRenderer.js +3 -1
  52. package/dist/extensions/Blocks/Recommendation/templates/list/template.js +21 -21
  53. package/dist/extensions/Blocks/Recommendation/templates/utils.js +57 -50
  54. package/dist/extensions/Blocks/Recommendation/utils/filterUtil.js +17 -14
  55. package/dist/extensions/Blocks/Recommendation/utils/tagName.js +6 -6
  56. package/dist/extensions/Blocks/Unsubscribe/block.js +11 -11
  57. package/dist/extensions/Blocks/Unsubscribe/settingsPanel.js +16 -17
  58. package/dist/extensions/DynamicContent/dynamic-content.js +17 -12
  59. package/dist/guido.css +1 -1
  60. package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js +324 -218
  61. package/dist/package.json.js +1 -1
  62. package/dist/services/recommendationApi.js +15 -15
  63. package/dist/services/stripoApi.js +9 -9
  64. package/dist/services/templateLibraryApi.js +48 -46
  65. package/dist/src/@types/config/index.d.ts +1 -1
  66. package/dist/src/@types/config/schemas.d.ts +28 -0
  67. package/dist/src/@types/config/types.d.ts +3 -1
  68. package/dist/src/@types/generic.d.ts +0 -1
  69. package/dist/src/@types/save-as-template.d.ts +1 -0
  70. package/dist/src/composables/useActionsApi.d.ts +1 -1
  71. package/dist/src/composables/useConfig.d.ts +12 -0
  72. package/dist/src/composables/useFullStoryBridge.d.ts +11 -0
  73. package/dist/src/composables/validators/useLiquidValidator.d.ts +3 -0
  74. package/dist/src/config/compiler/liquidCompilerRules.d.ts +2 -0
  75. package/dist/src/config/compiler/utils/recommendationCompilerUtils.d.ts +1 -1
  76. package/dist/src/enums/extensions/recommendationBlock.d.ts +3 -0
  77. package/dist/src/extensions/Blocks/CouponBlock/template.d.ts +2 -0
  78. package/dist/src/extensions/Blocks/RadioButton/template.d.ts +1 -1
  79. package/dist/src/extensions/Blocks/Recommendation/constants/controlIds.d.ts +1 -0
  80. package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +1 -1
  81. package/dist/src/extensions/Blocks/Recommendation/constants/selectors.d.ts +5 -0
  82. package/dist/src/extensions/Blocks/Recommendation/controls/cardComposition/index.d.ts +5 -0
  83. package/dist/src/extensions/Blocks/Recommendation/controls/customAttribute/index.d.ts +3 -0
  84. package/dist/src/extensions/Blocks/Recommendation/controls/customAttribute/textTrim.d.ts +35 -0
  85. package/dist/src/extensions/Blocks/Recommendation/controls/name/textTrim.d.ts +3 -20
  86. package/dist/src/extensions/Blocks/Recommendation/controls/shared/textTrimCssRules.d.ts +29 -0
  87. package/dist/src/extensions/Blocks/Recommendation/templates/grid/template.d.ts +4 -4
  88. package/dist/src/extensions/Blocks/Recommendation/templates/list/template.d.ts +3 -3
  89. package/dist/src/extensions/Blocks/Recommendation/templates/utils.d.ts +20 -3
  90. package/dist/src/services/templateLibraryApi.d.ts +1 -1
  91. package/dist/src/stores/config.d.ts +108 -0
  92. package/dist/src/stores/preview.d.ts +3 -0
  93. package/dist/src/utils/genericUtil.d.ts +1 -1
  94. package/dist/src/utils/htmlCompiler.d.ts +2 -1
  95. package/dist/static/styles/base.css.js +7 -2
  96. package/dist/static/styles/components/button.css.js +16 -9
  97. package/dist/static/styles/components/loader.css.js +4 -0
  98. package/dist/static/styles/components/narrow-panel.css.js +52 -0
  99. package/dist/stores/preview.js +4 -3
  100. package/dist/utils/genericUtil.js +42 -20
  101. package/dist/utils/htmlCompiler.js +48 -41
  102. package/dist/utils/templatePreparation.js +36 -25
  103. package/dist/utils/tooltipUtils.js +4 -5
  104. package/package.json +4 -4
@@ -1,25 +1,26 @@
1
- import { useActionsApi as A } from "./useActionsApi.js";
2
- import { useBlocksConfig as F } from "./useBlocksConfig.js";
3
- import { useConfig as D } from "./useConfig.js";
4
- import { useCustomInterfaceAppearance as I } from "./useCustomInterfaceAppearance.js";
5
- import { useStripoEventHandler as P } from "./useStripoEventHandler.js";
6
- import { useToaster as U } from "./useToaster.js";
7
- import { localePatch as R } from "../config/i18n/index.js";
8
- import { displayConditions as H } from "../enums/displayConditions.js";
9
- import { useStripoApi as O } from "../services/stripoApi.js";
10
- import q from "../static/styles/customEditorStyle.css.js";
11
- import { useEditorStore as S } from "../stores/editor.js";
12
- import { dynamicContentToMergeTags as x } from "../utils/genericUtil.js";
13
- import L from "../package.json.js";
14
- const oe = (C, c) => {
15
- const { features: l, template: E } = D(), { handleError: u } = U(), { getToken: h, getCustomFonts: w, getSyncModulesStatus: b } = O(), { handleEvent: k } = P(), { getStripoBlocksConfig: T } = F(), V = async (i, n = [], r = !1) => {
16
- var f, g, y;
17
- const e = S(), { html: m, css: a } = i, { baseBlocks: o, extensions: d } = await T(), p = ((f = l.value) == null ? void 0 : f.displayConditions) ?? !0, B = ((g = l.value) == null ? void 0 : g.modulesDisabled) ?? !1, v = ((y = E.value) == null ? void 0 : y.forceRecreate) ?? !1;
1
+ import { useActionsApi as D } from "./useActionsApi.js";
2
+ import { useBlocksConfig as I } from "./useBlocksConfig.js";
3
+ import { useConfig as P } from "./useConfig.js";
4
+ import { useCustomInterfaceAppearance as U } from "./useCustomInterfaceAppearance.js";
5
+ import { useFullStoryBridge as R } from "./useFullStoryBridge.js";
6
+ import { useStripoEventHandler as q } from "./useStripoEventHandler.js";
7
+ import { useToaster as x } from "./useToaster.js";
8
+ import { localePatch as H } from "../config/i18n/index.js";
9
+ import { displayConditions as O } from "../enums/displayConditions.js";
10
+ import { useStripoApi as j } from "../services/stripoApi.js";
11
+ import L from "../static/styles/customEditorStyle.css.js";
12
+ import { useEditorStore as C } from "../stores/editor.js";
13
+ import { dynamicContentToMergeTags as $ } from "../utils/genericUtil.js";
14
+ import z from "../package.json.js";
15
+ const ae = (E, l) => {
16
+ const { features: c, template: h, isFeatureEnabled: u } = P(), { handleError: m } = x(), { getToken: w, getCustomFonts: b, getSyncModulesStatus: k } = j(), { handleEvent: B } = q(), { getStripoBlocksConfig: T } = I(), V = async (i, r = [], s = !1) => {
17
+ var g, S, y;
18
+ const e = C(), { html: p, css: a } = i, { baseBlocks: o, extensions: d } = await T(), f = ((g = c.value) == null ? void 0 : g.displayConditions) ?? !0, F = ((S = c.value) == null ? void 0 : S.modulesDisabled) ?? !1, v = ((y = h.value) == null ? void 0 : y.forceRecreate) ?? !1;
18
19
  window.UIEditor.initEditor(
19
20
  document.querySelector("#guido-editor"),
20
21
  {
21
- metadata: C,
22
- html: m,
22
+ metadata: E,
23
+ html: p,
23
24
  css: a,
24
25
  forceRecreate: v,
25
26
  locale: "en",
@@ -28,49 +29,53 @@ const oe = (C, c) => {
28
29
  mobileViewButtonSelector: ".guido__view-option-selection-mobile",
29
30
  desktopViewButtonSelector: ".guido__view-option-selection-desktop",
30
31
  codeEditorButtonSelector: "#guido__code-button",
31
- customAppearanceMergetags: !0,
32
+ customAppearanceMergetags: !u("liquidSyntax"),
32
33
  customAppearanceMergetagsBorderColor: "#f1f3fe",
33
34
  customAppearanceMergetagsBackgroundColor: "#f1f3fe",
34
- customViewStyles: q,
35
- conditionsEnabled: p,
36
- customConditionsEnabled: p,
37
- conditionCategories: H,
35
+ customViewStyles: L,
36
+ conditionsEnabled: f,
37
+ customConditionsEnabled: f,
38
+ conditionCategories: O,
38
39
  enableXSSSecurity: !0,
39
- modulesDisabled: B,
40
- syncModulesEnabled: r,
40
+ modulesDisabled: F,
41
+ syncModulesEnabled: s,
41
42
  messageSettingsEnabled: !0,
42
43
  displayGmailAnnotations: !0,
43
44
  displayHiddenPreheader: !1,
44
45
  displayTitle: !1,
45
46
  displayUTM: !1,
46
47
  selectElementAfterDrop: !0,
48
+ allowedScriptSourceDomains: "https://email-static.useinsider.com https://edge.fullstory.com https://rs.fullstory.com",
47
49
  ...o ? { baseBlocks: o } : {},
48
50
  editorFonts: {
49
51
  showDefaultStandardFonts: !0,
50
52
  showDefaultNotStandardFonts: !0,
51
- customFonts: n
53
+ customFonts: r
52
54
  },
53
55
  mergeTags: [
54
56
  {
55
- entries: x(c.preselectedDynamicContentList)
57
+ entries: $(
58
+ l.preselectedDynamicContentList,
59
+ u("liquidSyntax")
60
+ )
56
61
  }
57
62
  ],
58
63
  async onTokenRefreshRequest(t) {
59
64
  try {
60
- const s = await h();
61
- t(s);
62
- } catch (s) {
63
- u(s, "Failed to refresh token");
65
+ const n = await w();
66
+ t(n);
67
+ } catch (n) {
68
+ m(n, "Failed to refresh token");
64
69
  }
65
70
  },
66
71
  onTemplateLoaded() {
67
72
  try {
68
- const { importCss: t } = I(), { activateCustomViewStyles: s, updateTimerInClonedTemplate: M } = A();
69
- t(), s(), M(), c.onReady(), e.isStripoInitialized = !0, e.loadingStatus = !1, setTimeout(() => {
73
+ const { importCss: t } = U(), { activateCustomViewStyles: n, updateTimerInClonedTemplate: M } = D(), { injectFullStory: A } = R();
74
+ t(), n(), A(), M(), l.onReady(), e.isStripoInitialized = !0, e.loadingStatus = !1, setTimeout(() => {
70
75
  e.hasChanges = !1;
71
76
  }, 1e3);
72
77
  } catch (t) {
73
- u(t, "Failed to load custom interface appearance");
78
+ m(t, "Failed to load custom interface appearance");
74
79
  }
75
80
  },
76
81
  onCodeEditorVisibilityChanged(t) {
@@ -85,39 +90,39 @@ const oe = (C, c) => {
85
90
  onDataChanged() {
86
91
  e.hasChanges = !0;
87
92
  },
88
- onEvent: k,
93
+ onEvent: B,
89
94
  ignoreClickOutsideSelectors: [
90
95
  "#guido-dynamic-content-modal",
91
96
  ".in-on-board-wrapper",
92
97
  ".in-drawer__container"
93
98
  ],
94
99
  extensions: d,
95
- localePatch: R
100
+ localePatch: H
96
101
  }
97
102
  );
98
- }, _ = (i) => new Promise((n, r) => {
103
+ }, _ = (i) => new Promise((r, s) => {
99
104
  var d;
100
105
  if (document.getElementById("UiEditorScript")) {
101
- i(), n();
106
+ i(), r();
102
107
  return;
103
108
  }
104
- const e = L.guido, a = `https://email-static.useinsider.com/guido/${(d = e == null ? void 0 : e.stripo) == null ? void 0 : d.version}/UIEditor.js`, o = document.createElement("script");
109
+ const e = z.guido, a = `https://email-static.useinsider.com/guido/${(d = e == null ? void 0 : e.stripo) == null ? void 0 : d.version}/UIEditor.js`, o = document.createElement("script");
105
110
  o.id = "UiEditorScript", o.type = "module", o.src = a, o.onload = () => {
106
- i(), n();
111
+ i(), r();
107
112
  }, o.onerror = () => {
108
- r(new Error(`Failed to load Stripo UIEditor script from S3: ${a}`));
113
+ s(new Error(`Failed to load Stripo UIEditor script from S3: ${a}`));
109
114
  }, document.body.appendChild(o);
110
115
  });
111
116
  return { initPlugin: async (i) => {
112
117
  await _(async () => {
113
- const n = S(), [r, e] = await Promise.all([
114
- w(),
115
- b()
118
+ const r = C(), [s, e] = await Promise.all([
119
+ b(),
120
+ k()
116
121
  ]);
117
- n.syncModulesEnabled = e, await V(i, r, e);
122
+ r.syncModulesEnabled = e, await V(i, s, e);
118
123
  });
119
124
  } };
120
125
  };
121
126
  export {
122
- oe as useStripo
127
+ ae as useStripo
123
128
  };
@@ -0,0 +1,42 @@
1
+ import { ToasterTypeOptions as a } from "../../enums/toaster.js";
2
+ import { base64EncodeWithSpecialChars as u } from "../../utils/base64.js";
3
+ import { useHttp as d } from "../useHttp.js";
4
+ import { useToaster as c } from "../useToaster.js";
5
+ import { useTranslations as p } from "../useTranslations.js";
6
+ const v = () => {
7
+ const { post: i } = d(), { showToaster: e } = c(), s = p();
8
+ return { validateLiquidSyntax: async (o) => {
9
+ try {
10
+ const t = await i("/newsletter/contents/validate-syntax", [{
11
+ identifier: "default",
12
+ syntax: "liquid",
13
+ contents: {
14
+ subject: null,
15
+ preheader: null,
16
+ html: u(o),
17
+ ampHtml: null
18
+ }
19
+ }]);
20
+ if (!Array.isArray(t.data)) {
21
+ const l = t.data;
22
+ return e({
23
+ type: a.Warning,
24
+ message: l.message ?? s("journey-builder.liquid-validation-failed")
25
+ }), !1;
26
+ }
27
+ const [r] = t.data, n = Object.values((r == null ? void 0 : r.errors) ?? {});
28
+ return n.length ? (e({
29
+ type: a.Warning,
30
+ message: n[0].replace(/^line \d+:\s*/, "")
31
+ }), !1) : !0;
32
+ } catch {
33
+ return e({
34
+ type: a.Alert,
35
+ message: s("journey-builder.liquid-validation-failed")
36
+ }), !1;
37
+ }
38
+ } };
39
+ };
40
+ export {
41
+ v as useLiquidValidator
42
+ };
@@ -0,0 +1,15 @@
1
+ import { COUPON_PLACEHOLDER_LIQUID as e, COUPON_PLACEHOLDER_DEFAULT as i } from "../../extensions/Blocks/CouponBlock/template.js";
2
+ const o = [
3
+ {
4
+ id: "liquid-coupon-code",
5
+ description: "Replace legacy coupon placeholder with liquid syntax",
6
+ type: "replace",
7
+ search: i,
8
+ replacement: e,
9
+ replaceAll: !0,
10
+ priority: 50
11
+ }
12
+ ];
13
+ export {
14
+ o as liquidCompilerRules
15
+ };
@@ -1,18 +1,18 @@
1
- import { useRecommendation as f } from "../../composables/useRecommendation.js";
2
- import { DUMMY_IMAGE_MAPPINGS as P, REGEX as m, VerticalOrientation as g, CSS as e, ATTRIBUTES as a, CONDITIONS as A, HTML as h } from "../../enums/recommendation.js";
3
- import { prepareRecommendationBlocks as D } from "./utils/recommendationCompilerUtils.js";
4
- const G = [
1
+ import { useRecommendation as C } from "../../composables/useRecommendation.js";
2
+ import { DUMMY_IMAGE_MAPPINGS as h, REGEX as T, VerticalOrientation as M, CSS as E, ATTRIBUTES as A, CONDITIONS as g, HTML as N } from "../../enums/recommendation.js";
3
+ import { prepareRecommendationBlocks as x } from "./utils/recommendationCompilerUtils.js";
4
+ const w = [
5
5
  {
6
6
  id: "replace-images-with-variable-names",
7
7
  description: "Replacing dummy images with variable names in recommendation module",
8
8
  type: "custom",
9
- processor: (s) => {
10
- let t = s;
11
- return Object.entries(P).forEach(([, l]) => {
12
- Object.entries(l).forEach(([n, o]) => {
13
- t = t.replaceAll(o, `{{${n}}}`);
9
+ processor: (c) => {
10
+ let e = c;
11
+ return Object.entries(h).forEach(([, l]) => {
12
+ Object.entries(l).forEach(([n, s]) => {
13
+ e = e.replaceAll(s, `{{${n}}}`);
14
14
  });
15
- }), t;
15
+ }), e;
16
16
  },
17
17
  priority: 50
18
18
  },
@@ -29,18 +29,18 @@ const G = [
29
29
  id: "add-recommendation-unresponsive-css",
30
30
  description: "Adding recommendation unresponsive css",
31
31
  type: "custom",
32
- processor: (s) => {
33
- const { calculateCardWidth: t, getRecommendationCampaignData: l } = f();
34
- let n = s;
35
- const o = n.match(m.ID);
36
- if (o) {
37
- const d = [];
38
- if (o.forEach((c) => {
39
- const E = /recommendation-id="(.*?)"/i.exec(c), I = E ? E[1].trim() : "", p = l(I);
40
- p.textTrimming && p.orientation === g && d.push(t(p));
41
- }), d.length) {
42
- const c = `width:${Math.min(...d)}px!important;`;
43
- n = n.replace(e.REGULAR_NAME_HEIGHT, `${e.TRIMMED_NAME_HEIGHT} ${c} ${e.ELLIPSIS}`).replace(e.REGULAR_NAME_CONTAINER_HEIGHT, e.TRIMMED_NAME_CONTAINER_CSS).replace(e.RESPONSIVE_NAME_SIZE, `${e.RESPONSIVE_NAME_HEIGHT} ${c} ${e.ELLIPSIS}`).replace(e.RESPONSIVE_NAME_CONTAINER_HEIGHT, e.TRIMMED_RESPONSIVE_NAME_CONTAINER_CSS);
32
+ processor: (c) => {
33
+ const { calculateCardWidth: e, getRecommendationCampaignData: l } = C();
34
+ let n = c;
35
+ const s = n.match(T.ID);
36
+ if (s) {
37
+ const a = [];
38
+ if (s.forEach((i) => {
39
+ const d = /recommendation-id="(.*?)"/i.exec(i), _ = d ? d[1].trim() : "", R = l(_);
40
+ R.textTrimming && R.orientation === M && a.push(e(R));
41
+ }), a.length) {
42
+ const i = `width:${Math.min(...a)}px!important;`;
43
+ n = n.replace(E.REGULAR_NAME_HEIGHT, `${E.TRIMMED_NAME_HEIGHT} ${i} ${E.ELLIPSIS}`).replace(E.REGULAR_NAME_CONTAINER_HEIGHT, E.TRIMMED_NAME_CONTAINER_CSS).replace(E.RESPONSIVE_NAME_SIZE, `${E.RESPONSIVE_NAME_HEIGHT} ${i} ${E.ELLIPSIS}`).replace(E.RESPONSIVE_NAME_CONTAINER_HEIGHT, E.TRIMMED_RESPONSIVE_NAME_CONTAINER_CSS);
44
44
  }
45
45
  }
46
46
  return n;
@@ -51,39 +51,158 @@ const G = [
51
51
  id: "prepare-recommendations",
52
52
  description: "Replacing product data with template variables in recommendation blocks",
53
53
  type: "custom",
54
- processor: (s) => D(s),
54
+ processor: (c) => x(c),
55
55
  priority: 48
56
56
  },
57
57
  {
58
58
  id: "add-discount-conditions",
59
59
  description: "Adding discount conditions to the recommendation block",
60
60
  type: "custom",
61
- processor: (s) => {
62
- let t = s;
63
- const l = t.match(m.ATTRIBUTE_PARAGRAPH), { getRecommendationCampaignData: n } = f();
64
- return l !== null && l.forEach((o) => {
65
- const d = o.match(m.CUSTOM_FIELD);
66
- if (!d)
61
+ processor: (c) => {
62
+ let e = c;
63
+ const l = e.match(T.ATTRIBUTE_PARAGRAPH), { getRecommendationCampaignData: n } = C();
64
+ return l !== null && l.forEach((s) => {
65
+ const a = s.match(T.CUSTOM_FIELD);
66
+ if (!a)
67
67
  return;
68
- const [c] = d, E = c.match(m.CUSTOM_FIELD_INDEXES_PART), I = c.match(m.CUSTOM_FIELD_NAME_PART), p = o.match(m.ATTRIBUTE_PARAGRAPH_START_TAG);
69
- if (!E || !I || !p)
68
+ const [i] = a, d = i.match(T.CUSTOM_FIELD_INDEXES_PART), _ = i.match(T.CUSTOM_FIELD_NAME_PART), R = s.match(T.ATTRIBUTE_PARAGRAPH_START_TAG);
69
+ if (!d || !_ || !R)
70
70
  return;
71
- const [u] = E, [R] = I, [_] = p, T = R.substring(1, R.length - 2), S = _.match(m.COMPOSITION) !== null;
72
- let i = c;
73
- if (S) {
74
- const $ = u.substring(2, u.length - 3), r = n($);
75
- T === a.OMNIBUS_PRICE && (r.priceBeforeTextValue && (i = `${r.priceBeforeTextValue}${i}`), r.priceAfterTextValue && (i = `${i}${r.priceAfterTextValue}`)), T === a.OMNIBUS_DISCOUNT && (r.discountBeforeTextValue && (i = `${r.discountBeforeTextValue}${i}`), r.discountAfterTextValue && (i = `${i}${r.discountAfterTextValue}`));
71
+ const [S] = d, [b] = _, [m] = R, o = b.substring(1, b.length - 2), r = m.match(T.COMPOSITION) !== null;
72
+ let t = i;
73
+ if (r) {
74
+ const I = S.substring(2, S.length - 3), p = n(I);
75
+ o === A.OMNIBUS_PRICE && (p.priceBeforeTextValue && (t = `${p.priceBeforeTextValue}${t}`), p.priceAfterTextValue && (t = `${t}${p.priceAfterTextValue}`)), o === A.OMNIBUS_DISCOUNT && (p.discountBeforeTextValue && (t = `${p.discountBeforeTextValue}${t}`), p.discountAfterTextValue && (t = `${t}${p.discountAfterTextValue}`));
76
76
  }
77
- const N = u.substring(2);
78
- let M = "";
79
- T in A.IF && (M = A.IF[T].replaceAll(`{${a.DISCOUNT}}`, `${N}${a.DISCOUNT}`).replaceAll(`{${a.OMNIBUS_DISCOUNT}}`, `${N}${a.OMNIBUS_DISCOUNT}`).replaceAll(`{${a.OMNIBUS_PRICE}}`, `${N}${a.OMNIBUS_PRICE}`));
80
- const O = `${_}${i}${h.PARAGRAPH_END_TAG}`, C = `${M}${S ? O : o}${A.ELSE}${_}${h.PARAGRAPH_END_TAG}${A.END_IF}`;
81
- t = t.replace(o, C);
82
- }), t;
77
+ const u = S.substring(2);
78
+ let f = "";
79
+ o in g.IF && (f = g.IF[o].replaceAll(`{${A.DISCOUNT}}`, `${u}${A.DISCOUNT}`).replaceAll(`{${A.OMNIBUS_DISCOUNT}}`, `${u}${A.OMNIBUS_DISCOUNT}`).replaceAll(`{${A.OMNIBUS_PRICE}}`, `${u}${A.OMNIBUS_PRICE}`));
80
+ const $ = `${m}${t}${N.PARAGRAPH_END_TAG}`, y = `${f}${r ? $ : s}${g.ELSE}${m}${N.PARAGRAPH_END_TAG}${g.END_IF}`;
81
+ e = e.replace(s, y);
82
+ }), e;
83
83
  },
84
84
  priority: 53
85
+ },
86
+ {
87
+ id: "strip-empty-omnibus-spans",
88
+ description: "Remove empty omnibus text-before and text-after span elements",
89
+ type: "regex",
90
+ pattern: '<span class="omnibus-text-(?:before|after)">\\s*</span>',
91
+ replacement: "",
92
+ flags: "g",
93
+ priority: 54
94
+ },
95
+ {
96
+ id: "strip-recommendation-editor-attributes",
97
+ description: "Strip editor-only attributes from compiled recommendation output",
98
+ type: "custom",
99
+ // Scoped to REC_START/REC_END markers so it cannot strip `product-attr`
100
+ // from Items block elements, which the items compiler rule depends on.
101
+ processor: (c) => {
102
+ const e = /\s+(?:esd-extension-block-id|data-attribute-type|data-visibility|data-text-before|data-text-after|product-attr|composition)="[^"]*"/g;
103
+ return c.replace(
104
+ /<!--REC_START-->([\s\S]*?)<!--REC_END-->/g,
105
+ (l, n) => `<!--REC_START-->${n.replace(e, "")}<!--REC_END-->`
106
+ );
107
+ },
108
+ priority: 55
109
+ },
110
+ {
111
+ id: "strip-unused-recommendation-classes",
112
+ description: "Remove CSS classes not referenced by any style rule from recommendation elements",
113
+ type: "custom",
114
+ processor: (c) => {
115
+ let e = c.replace(
116
+ / class="(?:product-card-segment|attribute-cell|recommendation-attribute-row|product-image|product-name|product-price|product-old-price|product-omnibus-price|product-omnibus-discount|product-button|recommendation-product-row|product-card-wrapper)"/g,
117
+ ""
118
+ );
119
+ return e = e.replaceAll("es-button buy-button", "es-button"), e = e.replaceAll("ins-recommendation-product-container ", ""), e;
120
+ },
121
+ priority: 56
122
+ },
123
+ {
124
+ id: "remove-empty-mobile-layout-artifacts",
125
+ description: "Remove empty mobile container rows and unused mobile layout CSS",
126
+ type: "custom",
127
+ processor: (c) => {
128
+ let e = c;
129
+ return e = e.replace(
130
+ /<tr[^>]*class="ins-recommendation-mobile-row"[^>]*><\/tr>/g,
131
+ ""
132
+ ), /class="[^"]*ins-recommendation-mobile-container/.test(e) || (e = e.replace(
133
+ /\.ins-recommendation-mobile-container\s*\{\s*display\s*:\s*none\s*;?\s*\}/g,
134
+ ""
135
+ ), e = e.replace(
136
+ /@media[^{]*max-width\s*:\s*480px[^{]*\{((?:[^{}]*\{[^{}]*\})*[^{}]*)\}/g,
137
+ (l, n) => {
138
+ const s = n.match(/[^{}]+\{[^{}]*\}/g) || [], a = /ins-recommendation|product-image-cell|button-cell|product-info-cell/;
139
+ return s.every((d) => a.test(d)) ? "" : l;
140
+ }
141
+ )), e;
142
+ },
143
+ priority: 57
144
+ },
145
+ {
146
+ id: "deduplicate-inline-styles",
147
+ description: "Replace repeated inline styles with CSS class references within recommendation blocks",
148
+ type: "custom",
149
+ processor: (c) => {
150
+ const e = c.replace(
151
+ /<a\b[^>]*\bes-button\b[^>]*>/g,
152
+ (o) => o.replace(
153
+ /([;"]color:)([^;"]+)/g,
154
+ (r, t, u) => u.includes("!important") ? r : `${t}${u} !important`
155
+ )
156
+ ), l = /<!--REC_START-->([\s\S]*?)<!--REC_END-->/g, n = / style="([^"]*)"/g, s = /* @__PURE__ */ new Map();
157
+ let a = l.exec(e);
158
+ for (; a !== null; ) {
159
+ let o = n.exec(a[1]);
160
+ for (; o !== null; ) {
161
+ const [, r] = o;
162
+ s.set(r, (s.get(r) || 0) + 1), o = n.exec(a[1]);
163
+ }
164
+ n.lastIndex = 0, a = l.exec(e);
165
+ }
166
+ const i = /* @__PURE__ */ new Map(), d = [];
167
+ let _ = 0;
168
+ if (s.forEach((o, r) => {
169
+ if (o >= 6) {
170
+ const t = `rc${_++}`;
171
+ i.set(r, t), d.push(`.${t}{${r}}`);
172
+ }
173
+ }), i.size === 0) {
174
+ let o = e;
175
+ return o = o.replaceAll("<!--REC_START-->", ""), o = o.replaceAll("<!--REC_END-->", ""), o;
176
+ }
177
+ const R = (o) => o.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), S = (o, r) => `${o.slice(0, -1)} ${r}"`, b = /* @__PURE__ */ new Map();
178
+ i.forEach((o, r) => {
179
+ const t = R(r);
180
+ b.set(r, {
181
+ caseA: new RegExp(`(class="[^"]*")((?:[^>]*?)) style="${t}"`, "g"),
182
+ caseB: new RegExp(` style="${t}"((?:[^>]*?))(class="[^"]*")`, "g")
183
+ });
184
+ });
185
+ let m = e.replace("</style>", `${d.join("")}</style>`);
186
+ return m = m.replace(
187
+ /<!--REC_START-->([\s\S]*?)<!--REC_END-->/g,
188
+ (o, r) => {
189
+ let t = r;
190
+ return i.forEach((u, f) => {
191
+ const $ = b.get(f);
192
+ t = t.replace(
193
+ $.caseA,
194
+ (y, I, p) => S(I, u) + p
195
+ ), t = t.replace(
196
+ $.caseB,
197
+ (y, I, p) => I + S(p, u)
198
+ ), t = t.replaceAll(` style="${f}"`, ` class="${u}"`);
199
+ }), t;
200
+ }
201
+ ), m = m.replaceAll("<!--REC_START-->", ""), m = m.replaceAll("<!--REC_END-->", ""), m;
202
+ },
203
+ priority: 58
85
204
  }
86
205
  ];
87
206
  export {
88
- G as recommendationCompilerRules
207
+ w as recommendationCompilerRules
89
208
  };
@@ -1,41 +1,41 @@
1
- import { usePartner as N } from "../../composables/usePartner.js";
2
- import { LINK_REGEXES as l, LINK_TYPES as S, INSIDER_ID as R, URLS as _ } from "../../enums/unsubscribe.js";
3
- import { parsePageList as U } from "../../extensions/Blocks/Unsubscribe/utils/utils.js";
4
- import { useConfigStore as B } from "../../stores/config.js";
5
- import { useDynamicContentStore as y } from "../../stores/dynamic-content.js";
6
- import { useUnsubscribeStore as L } from "../../stores/unsubscribe.js";
7
- const D = [
1
+ import { usePartner as y } from "../../composables/usePartner.js";
2
+ import { LINK_REGEXES as p, LINK_TYPES as S, INSIDER_ID as m, URLS as R } from "../../enums/unsubscribe.js";
3
+ import { parsePageList as I } from "../../extensions/Blocks/Unsubscribe/utils/utils.js";
4
+ import { useConfigStore as N } from "../../stores/config.js";
5
+ import { useDynamicContentStore as U } from "../../stores/dynamic-content.js";
6
+ import { useUnsubscribeStore as C } from "../../stores/unsubscribe.js";
7
+ const G = [
8
8
  {
9
9
  id: "add-unsubscribe-link-values",
10
10
  description: "Adding unsubscribe link values",
11
11
  type: "custom",
12
12
  processor: (t) => {
13
- const { getPartnerName: i } = N(), c = B(), n = y(), u = L(), a = c.variationId;
13
+ const { getPartnerName: i } = y(), o = N(), s = U(), d = C(), a = o.variationId;
14
14
  if (!a)
15
15
  return t;
16
16
  let e = t;
17
- const r = `/${i()}/email/${a}?user={{iid}}`;
18
- return new DOMParser().parseFromString(e, "text/html").querySelectorAll(".unsubscribe-block-v2[data-unsubscribe-page-list]").forEach((p) => {
19
- var g;
20
- const m = p.getAttribute("data-unsubscribe-page-list");
21
- if (!m)
17
+ const r = `/${i()}/email/${a}?user={{iid}}`, E = new DOMParser().parseFromString(e, "text/html").querySelectorAll(".unsubscribe-block-v2[data-unsubscribe-page-list]");
18
+ let c = !1, l = !1;
19
+ return E.forEach((f) => {
20
+ var b;
21
+ const u = f.getAttribute("data-unsubscribe-page-list");
22
+ if (!u)
22
23
  return;
23
- const I = U(m), d = ((g = u.templates) == null ? void 0 : g.filter(
24
- (o) => I.includes(o.id)
25
- )) ?? [], E = d.some((o) => o.type === S.UNSUBSCRIBE_LINK_TYPE), b = d.some((o) => o.type === S.PREFERENCES_LINK_TYPE), f = p.outerHTML;
26
- let s = f;
27
- (E || b) && n.selectedDynamicContentList.push({
28
- text: R,
29
- value: R,
30
- fallback: ""
31
- }), E && (s = s.replace(
32
- l.GLOBAL_UNSUBSCRIBE_LINK_REGEX,
33
- _.UNSUBSCRIBE_URL + r
34
- )), b && (s = s.replace(
35
- l.PREFERENCES_UNSUBSCRIBE_LINK_REGEX,
36
- _.PREFERENCES_URL + r
37
- )), s = s.replace(l.UNSUBSCRIBE_LINK_REGEX, ""), e = e.replace(f, s);
38
- }), e;
24
+ const _ = I(u), g = ((b = d.templates) == null ? void 0 : b.filter(
25
+ (n) => _.includes(n.id)
26
+ )) ?? [];
27
+ c = c || g.some((n) => n.type === S.UNSUBSCRIBE_LINK_TYPE), l = l || g.some((n) => n.type === S.PREFERENCES_LINK_TYPE);
28
+ }), (c || l) && (s.selectedDynamicContentList.some((u) => u.value === m) || s.selectedDynamicContentList.push({
29
+ text: m,
30
+ value: m,
31
+ fallback: ""
32
+ })), c && (e = e.replace(
33
+ p.GLOBAL_UNSUBSCRIBE_LINK_REGEX,
34
+ R.UNSUBSCRIBE_URL + r
35
+ )), l && (e = e.replace(
36
+ p.PREFERENCES_UNSUBSCRIBE_LINK_REGEX,
37
+ R.PREFERENCES_URL + r
38
+ )), E.length && (e = e.replace(p.UNSUBSCRIBE_LINK_REGEX, "")), e;
39
39
  },
40
40
  priority: 60
41
41
  },
@@ -43,7 +43,7 @@ const D = [
43
43
  id: "remove-data-ogsb-button-styles",
44
44
  description: "Removing styles like [data-ogsb] .es-button.es-button-123 { background: red; }",
45
45
  type: "regex",
46
- pattern: l.DATA_OGSB_BUTTON_CSS_REGEX,
46
+ pattern: p.DATA_OGSB_BUTTON_CSS_REGEX,
47
47
  replacement: "",
48
48
  flags: "g",
49
49
  priority: 61
@@ -61,16 +61,16 @@ const D = [
61
61
  type: "custom",
62
62
  processor: (t) => {
63
63
  let i = t;
64
- const c = i.match(/<a[^>]+>(.*?)<\/a>/gm);
65
- return c && c.forEach((n) => {
66
- if (n.includes("insEmail=1"))
64
+ const o = i.match(/<a[^>]+>(.*?)<\/a>/gm);
65
+ return o && o.forEach((s) => {
66
+ if (s.includes("insEmail=1"))
67
67
  return;
68
- if (n.match(/<a\s+(?:[^>]*?\s+)?href=(["'`”])(.*?)\1\s+(?:[^>]*?\s+)?universal=(["'`”])true\3/gm)) {
69
- const a = n.replace(/href=(["'`”])(.*?)\1/gm, (e) => {
68
+ if (s.match(/<a\s+(?:[^>]*?\s+)?href=(["'`”])(.*?)\1\s+(?:[^>]*?\s+)?universal=(["'`”])true\3/gm)) {
69
+ const a = s.replace(/href=(["'`”])(.*?)\1/gm, (e) => {
70
70
  const r = e.slice(6, e.length - 1).trim();
71
71
  return e.includes("?") || e.includes("#") ? r.slice(-1) === "&" ? e.replace(r, `${r}insEmail=1`) : e.replace(r, `${r}&insEmail=1`) : e.replace(r, `${r}?insEmail=1`);
72
72
  });
73
- i = i.replace(n, a);
73
+ i = i.replace(s, a);
74
74
  }
75
75
  }), i;
76
76
  },
@@ -78,5 +78,5 @@ const D = [
78
78
  }
79
79
  ];
80
80
  export {
81
- D as unsubscribeCompilerRules
81
+ G as unsubscribeCompilerRules
82
82
  };