@useinsider/guido 3.21.2-beta.45bb425 → 3.21.2-beta.4b0fed7

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.
@@ -1,3 +1,4 @@
1
+ import type { LegacyVariable } from './types';
1
2
  export declare function extractTitleText(block: Element): string;
2
3
  /**
3
4
  * Fallback for legacy configs that carry no `p_recommendation_title` variable:
@@ -7,6 +8,25 @@ export declare function extractTitleText(block: Element): string;
7
8
  * @returns True when the legacy block renders a visible title
8
9
  */
9
10
  export declare function hasVisibleTitle(block: Element): boolean;
11
+ /**
12
+ * A rendered title container with no text showed the user no title, whatever the config's `hidden` flag says.
13
+ * @param block - The legacy recommendation block element
14
+ * @returns True when the legacy block renders an empty title container
15
+ */
16
+ export declare function hasEmptyTitle(block: Element): boolean;
17
+ /**
18
+ * Reads which price the legacy card renders first. Prices sharing a `positionIdx` are ordered by this.
19
+ * @param block - The legacy recommendation block element
20
+ * @returns True only when both prices render and the original price comes first
21
+ */
22
+ export declare function isOldPriceFirst(block: Element): boolean;
23
+ /**
24
+ * Legacy keeps the text color and the name's trim toggle in the rendered `<p>`, not in the config theme.
25
+ * @param variables - The legacy composition variables
26
+ * @param block - The legacy recommendation block element
27
+ * @returns The variables, with `textColor` / `textTrimming` filled from the rendered HTML where the theme lacks them
28
+ */
29
+ export declare function withRenderedTextTheme(variables: LegacyVariable[] | undefined, block: Element): LegacyVariable[] | undefined;
10
30
  /**
11
31
  * Card background lives on either the block (`bgcolor`/`style`) or per-card
12
32
  * cells (`.product-card`). Returns empty string when no background is set —
@@ -65,6 +65,7 @@ export declare class RecommendationBlock extends Block {
65
65
  */
66
66
  onDelete(node: ImmutableHtmlNode): void;
67
67
  private _ensureMobileFitRule;
68
+ private _ensureTextTrimCss;
68
69
  private _syncHeightBound;
69
70
  /**
70
71
  * Warns (dark advisory toaster) when the design holds more than one live
@@ -121,14 +121,8 @@ export declare class RecommendationBlockControl extends CommonControl {
121
121
  private _fetchBlockData;
122
122
  private _isPanelOn;
123
123
  /**
124
- * Applies smart defaults for newly dropped blocks.
125
- *
126
- * For new blocks (config still matches hardcoded defaults), validates that
127
- * the default currency and algorithm are available from the API response.
128
- * If not, falls back to the first available option.
129
- *
130
- * Saved templates with user-customized config are left unchanged because
131
- * their values won't match the hardcoded defaults.
124
+ * Falls back to the first available option when the block's currency or locale is not offered (a new block on
125
+ * the hard-coded default, or a block copied from another account). The algorithm falls back only on new blocks.
132
126
  */
133
127
  private _applySmartDefaults;
134
128
  /**
@@ -2,9 +2,10 @@
2
2
  * Maps legacy algorithm strategy keys (used by templates authored against the
3
3
  * old recommendation system) to the new keys used by `RecommendationFeedSourceMaps`.
4
4
  *
5
+ * `viewedTogether` and `purchasedTogether` map to `mostPopular`: their feed sources (ids 11, 12) need a
6
+ * product id and are excluded from the algorithm dropdown (`EXCLUDED_ALGORITHM_IDS`).
7
+ *
5
8
  * Renames are matched by feed-source id:
6
- * - `viewedTogether` → `similarViewed` (id 11, path `viewed-together`)
7
- * - `purchasedTogether` → `similarBought` (id 12, path `purchased-together`)
8
9
  * - `trending` → `trendingProducts` (id 40, path `trending`)
9
10
  * - `mostValuable` → `mostValuableOfPartner` (id 46, path `most-valuable`)
10
11
  * - `topSellers` → `mostPurchased` (id 62, path `top-sellers`)
@@ -1,4 +1,3 @@
1
- import type { TemplateData } from '@@/Types/actions-api';
2
1
  import type { SavedTemplateDetails } from '@@/Types/stripo';
3
2
  /**
4
3
  * Collects every unsubscribe page id referenced by the unsubscribe blocks
@@ -45,7 +44,7 @@ export declare function getHtmlReferencedUnsubscribePages(html: string): number[
45
44
  */
46
45
  declare function hydrateRecommendationStoreFromRawHtml(rawHtml: string): Promise<void>;
47
46
  export declare const useTemplatePreparation: () => {
48
- prepareTemplateDetails: (prefetched?: TemplateData) => Promise<Omit<SavedTemplateDetails, "metadata">>;
47
+ prepareTemplateDetails: () => Promise<Omit<SavedTemplateDetails, "metadata">>;
49
48
  hydrateRecommendationStore: typeof hydrateRecommendationStoreFromRawHtml;
50
49
  };
51
50
  export {};
@@ -1,20 +1,20 @@
1
- import { useActionsApi as E } from "../composables/useActionsApi.js";
2
- import { useConfig as F } from "../composables/useConfig.js";
3
- import { useHtmlCompiler as I } from "../composables/useHtmlCompiler.js";
1
+ import { useActionsApi as D } from "../composables/useActionsApi.js";
2
+ import { useConfig as E } from "../composables/useConfig.js";
3
+ import { useHtmlCompiler as F } from "../composables/useHtmlCompiler.js";
4
4
  import { useRecommendationExtensionStore as b } from "../extensions/Blocks/Recommendation/store/recommendation.js";
5
- import { toBlockUrlConfig as R } from "../extensions/Blocks/Recommendation/utils/blockUrlConfig.js";
5
+ import { toBlockUrlConfig as I } from "../extensions/Blocks/Recommendation/utils/blockUrlConfig.js";
6
6
  import { DATA_ATTRIBUTES as g } from "../extensions/Blocks/Unsubscribe/utils/constants.js";
7
- import { parsePageList as U } from "../extensions/Blocks/Unsubscribe/utils/utils.js";
8
- import { useDynamicContentStore as L } from "../stores/dynamic-content.js";
9
- import { useEditorStore as N } from "../stores/editor.js";
10
- import { useUnsubscribeStore as v } from "../stores/unsubscribe.js";
11
- import { isPlainObject as z } from "./genericUtil.js";
12
- import { assignTrackingIds as M } from "./linkTrackingIds.js";
13
- function O(n) {
7
+ import { parsePageList as R } from "../extensions/Blocks/Unsubscribe/utils/utils.js";
8
+ import { useDynamicContentStore as U } from "../stores/dynamic-content.js";
9
+ import { useEditorStore as L } from "../stores/editor.js";
10
+ import { useUnsubscribeStore as N } from "../stores/unsubscribe.js";
11
+ import { isPlainObject as v } from "./genericUtil.js";
12
+ import { assignTrackingIds as z } from "./linkTrackingIds.js";
13
+ function M(n) {
14
14
  const r = new DOMParser().parseFromString(n, "text/html").querySelectorAll(`[${g.PAGE_LIST}]`), e = [];
15
15
  return r.forEach((i) => {
16
16
  const t = i.getAttribute(g.PAGE_LIST);
17
- t && e.push(...U(t));
17
+ t && e.push(...R(t));
18
18
  }), [...new Set(e)];
19
19
  }
20
20
  async function S(n) {
@@ -35,7 +35,7 @@ async function S(n) {
35
35
  } catch {
36
36
  return;
37
37
  }
38
- z(a) && r.seedBlockUrlConfig(t, R(a));
38
+ v(a) && r.seedBlockUrlConfig(t, I(a));
39
39
  });
40
40
  try {
41
41
  await r.fetchRecommendationCreateData();
@@ -46,40 +46,40 @@ async function S(n) {
46
46
  );
47
47
  }
48
48
  }
49
- const Z = () => {
50
- const n = L(), c = N(), o = v(), { getCompiledEmail: r, getTemplateData: e, updateHtmlAndCss: i } = E(), { compileHtml: t, compileAmpHtml: m } = I(), { isFeatureEnabled: a } = F();
49
+ const Y = () => {
50
+ const n = U(), c = L(), o = N(), { getCompiledEmail: r, getTemplateData: e, updateHtmlAndCss: i } = D(), { compileHtml: t, compileAmpHtml: m } = F(), { isFeatureEnabled: a } = E();
51
51
  return {
52
- prepareTemplateDetails: async (h) => {
53
- let { html: s, css: u, syncModulesIds: y = [] } = h ?? await e();
52
+ prepareTemplateDetails: async () => {
53
+ let { html: s, css: u, syncModulesIds: h = [] } = await e();
54
54
  if (a("linkTrackingIds"))
55
55
  try {
56
- const { html: d, changed: x, nextSeq: D } = M(s, c.trackIdSessionFloor);
57
- c.trackIdSessionFloor = D, x && (s = d, await i(d, u));
56
+ const { html: d, changed: P, nextSeq: x } = z(s, c.trackIdSessionFloor);
57
+ c.trackIdSessionFloor = x, P && (s = d, await i(d, u));
58
58
  } catch (d) {
59
59
  console.error("Tracking-id step failed, saving anyway:", d);
60
60
  }
61
- const { html: T, ampHtml: p = "", ampErrors: A = [] } = await r({
61
+ const { html: y, ampHtml: p = "", ampErrors: T = [] } = await r({
62
62
  minimize: !0,
63
63
  resetDataSavedFlag: !1
64
64
  });
65
65
  o.selectedUnsubscribePages.length && await o.fetchTemplates(), await S(s);
66
- const { compiledHtml: w, stats: l, appliedRules: C } = t(T), H = p && m(p).compiledHtml, k = n.getSelectedDynamicContentList, P = b(), f = O(s);
66
+ const { compiledHtml: A, stats: l, appliedRules: w } = t(y), C = p && m(p).compiledHtml, H = n.getSelectedDynamicContentList, k = b(), f = M(s);
67
67
  return console.debug("HTML Compilation Stats:", {
68
68
  originalSize: l.originalSize,
69
69
  compiledSize: l.compiledSize,
70
70
  reduction: `${l.reductionPercentage.toFixed(2)}%`,
71
- appliedRules: C,
71
+ appliedRules: w,
72
72
  executionTime: `${l.executionTime.toFixed(2)}ms`
73
73
  }), {
74
- dynamicContentList: k,
75
- compiledHtml: w,
74
+ dynamicContentList: H,
75
+ compiledHtml: A,
76
76
  rawHtml: s,
77
77
  css: u,
78
- ampHtml: H,
79
- ampErrors: A,
80
- modules: y.map(Number),
78
+ ampHtml: C,
79
+ ampErrors: T,
80
+ modules: h.map(Number),
81
81
  recommendation: {
82
- campaignUrls: P.recommendationCampaignUrls,
82
+ campaignUrls: k.recommendationCampaignUrls,
83
83
  configs: {}
84
84
  },
85
85
  unsubscribe: {
@@ -94,6 +94,6 @@ const Z = () => {
94
94
  };
95
95
  };
96
96
  export {
97
- O as getHtmlReferencedUnsubscribePages,
98
- Z as useTemplatePreparation
97
+ M as getHtmlReferencedUnsubscribePages,
98
+ Y as useTemplatePreparation
99
99
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useinsider/guido",
3
- "version": "3.21.2-beta.45bb425",
3
+ "version": "3.21.2-beta.4b0fed7",
4
4
  "description": "Guido is a Vue + TypeScript wrapper for Email Plugin. Easily embed the email editor in your Vue applications.",
5
5
  "main": "./dist/guido.umd.cjs",
6
6
  "module": "./dist/library.js",
@@ -1,22 +0,0 @@
1
- import { useToaster as i } from "../useToaster.js";
2
- import { useTranslations as m } from "../useTranslations.js";
3
- import { ToasterTypeOptions as c } from "../../enums/toaster.js";
4
- const u = "newsletter.multiple-html-designs-detected", r = `(?:[^>"']|"[^"]*"|'[^']*')*`, a = "style|script|noscript|xmp|iframe|noembed|noframes|textarea|title", T = /<html(?=[\s>/])/gi, A = new RegExp(
5
- `<!--[\\s\\S]*?-->|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>|<(${a})(?=[\\s/>])${r}>[\\s\\S]*?</\\1\\s*>|<([a-zA-Z][\\w:-]*)${r}>`,
6
- "gi"
7
- ), p = (e) => Array.from(e.matchAll(A)).filter(([, , t]) => (t == null ? void 0 : t.toLowerCase()) === "html").length, g = () => {
8
- const { showToaster: e } = i(), t = m();
9
- return { validateSingleHtmlDocument: (o, l = !1) => {
10
- var n;
11
- if ((((n = o.match(T)) == null ? void 0 : n.length) ?? 0) < 2)
12
- return !0;
13
- const s = p(o);
14
- return s <= 1 ? !0 : (console.debug("guido:save:blocked", { reason: "multiple-html-documents", htmlRootCount: s }), l || e({
15
- type: c.Warning,
16
- message: t(u)
17
- }), !1);
18
- } };
19
- };
20
- export {
21
- g as useHtmlDocumentCountValidator
22
- };
@@ -1,3 +0,0 @@
1
- export declare const useHtmlDocumentCountValidator: () => {
2
- validateSingleHtmlDocument: (rawHtml: string, silent?: boolean) => boolean;
3
- };