@useinsider/guido 3.6.0 → 3.7.0-beta.509616e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/dist/components/Guido.vue.js +1 -1
- package/dist/components/Guido.vue2.js +75 -72
- package/dist/components/organisms/header/EditorActions.vue.js +1 -1
- package/dist/components/organisms/header/EditorActions.vue2.js +6 -6
- package/dist/components/organisms/header/LeftSlot.vue.js +5 -5
- package/dist/components/organisms/header/LeftSlot.vue2.js +9 -9
- package/dist/composables/useActionsApi.js +16 -15
- package/dist/composables/useHtmlCompiler.js +40 -22
- package/dist/composables/useRecommendation.js +34 -33
- package/dist/enums/toaster.js +1 -1
- package/dist/extensions/Blocks/Recommendation/block.js +35 -16
- package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +127 -123
- package/dist/extensions/Blocks/Recommendation/controls/main/index.js +51 -47
- package/dist/extensions/Blocks/Recommendation/controls/main/layoutOrientation.js +12 -11
- package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +46 -46
- package/dist/extensions/Blocks/Recommendation/store/recommendation.js +13 -9
- package/dist/extensions/Blocks/Recommendation/templates/grid/elementRenderer.js +35 -29
- package/dist/extensions/Blocks/Recommendation/templates/grid/template.js +28 -28
- package/dist/extensions/Blocks/Recommendation/templates/list/elementRenderer.js +8 -8
- package/dist/extensions/Blocks/Recommendation/templates/utils.js +56 -49
- package/dist/extensions/Blocks/Recommendation/useRecommendationBlockWarning.js +16 -0
- package/dist/extensions/Blocks/Recommendation/utils/partnerCustomizations.js +21 -0
- package/dist/extensions/Blocks/Recommendation/utils/priceFormatter.js +17 -17
- package/dist/extensions/Blocks/Recommendation/utils/recommendationBlockCount.js +9 -0
- package/dist/guido.css +1 -1
- package/dist/src/components/Guido.vue.d.ts +1 -0
- package/dist/src/composables/useHtmlCompiler.d.ts +1 -0
- package/dist/src/enums/toaster.d.ts +2 -1
- package/dist/src/extensions/Blocks/Recommendation/block.d.ts +13 -0
- package/dist/src/extensions/Blocks/Recommendation/block.test.d.ts +1 -0
- package/dist/src/extensions/Blocks/Recommendation/templates/grid/elementRenderer.d.ts +7 -0
- package/dist/src/extensions/Blocks/Recommendation/templates/index.d.ts +1 -1
- package/dist/src/extensions/Blocks/Recommendation/templates/utils.d.ts +8 -0
- package/dist/src/extensions/Blocks/Recommendation/templates/utils.test.d.ts +1 -0
- package/dist/src/extensions/Blocks/Recommendation/useRecommendationBlockWarning.d.ts +12 -0
- package/dist/src/extensions/Blocks/Recommendation/utils/partnerCustomizations.d.ts +7 -0
- package/dist/src/extensions/Blocks/Recommendation/utils/priceFormatter.test.d.ts +1 -0
- package/dist/src/extensions/Blocks/Recommendation/utils/recommendationBlockCount.d.ts +28 -0
- package/dist/src/extensions/Blocks/Recommendation/utils/recommendationBlockCount.test.d.ts +1 -0
- package/dist/src/utils/ampErrorFilter.d.ts +2 -0
- package/dist/src/utils/ampErrorFilter.test.d.ts +1 -0
- package/dist/src/utils/templatePreparation.d.ts +16 -0
- package/dist/src/utils/templatePreparation.test.d.ts +1 -0
- package/dist/utils/ampErrorFilter.js +8 -0
- package/dist/utils/templatePreparation.js +59 -58
- package/package.json +1 -1
|
@@ -17,4 +17,11 @@ export declare const DEFAULT_CELL_PADDING = "0 5px";
|
|
|
17
17
|
* Used by controls to reliably select direct children for spacing adjustments
|
|
18
18
|
*/
|
|
19
19
|
export declare const ATTRIBUTE_CELL_CLASS = "attribute-cell";
|
|
20
|
+
/**
|
|
21
|
+
* Builds an empty filler cell used to pad incomplete rows (productsPerRow >
|
|
22
|
+
* number of products). Without fillers, table-layout:fixed redistributes the
|
|
23
|
+
* width among fewer cells and stretches them. Shared by the template and the
|
|
24
|
+
* card-composition control so both render identical filler markup.
|
|
25
|
+
*/
|
|
26
|
+
export declare function buildFillerCell(columnWidth: string, padding?: string): string;
|
|
20
27
|
export declare const gridElementRenderer: ElementRenderer;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { RecommendationProduct } from '@@/Types/recommendation';
|
|
8
8
|
import { type Orientation, type PrepareProductRowsOptions } from './utils';
|
|
9
|
-
export { DEFAULTS, DEFAULT_CARD_COMPOSITION, DEFAULT_CARD_VISIBILITY, getDefaultProducts, spacer, sanitizeImageUrl, createBlockTemplate, type Orientation, type PrepareProductRowsOptions, type ElementRenderer, type ProductCardGetter, } from './utils';
|
|
9
|
+
export { DEFAULTS, DEFAULT_CARD_COMPOSITION, DEFAULT_CARD_VISIBILITY, getDefaultProducts, spacer, sanitizeImageUrl, createBlockTemplate, toDisplayableAttributeValue, type Orientation, type PrepareProductRowsOptions, type ElementRenderer, type ProductCardGetter, } from './utils';
|
|
10
10
|
/**
|
|
11
11
|
* Unified function to prepare product rows for any layout.
|
|
12
12
|
* Delegates to the appropriate layout-specific implementation.
|
|
@@ -5,6 +5,14 @@ import { ATTR_PRODUCT_IMAGE, ATTR_PRODUCT_NAME, ATTR_PRODUCT_PRICE, ATTR_PRODUCT
|
|
|
5
5
|
* e.g., "rating_star" → "Rating Star"
|
|
6
6
|
*/
|
|
7
7
|
export declare function toDisplayName(attrName: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Reduces a raw product-attribute value to a displayable scalar string.
|
|
10
|
+
* Array-type attributes (filter types `Strings`/`Numbers`) are substituted with
|
|
11
|
+
* their last item by the email renderer at send time, so we mirror that here to
|
|
12
|
+
* keep the editor preview consistent with what is actually sent.
|
|
13
|
+
* Returns undefined when there is no displayable string/number.
|
|
14
|
+
*/
|
|
15
|
+
export declare function toDisplayableAttributeValue(value: unknown): string | undefined;
|
|
8
16
|
/**
|
|
9
17
|
* Checks whether an attribute is a default (top-level) product attribute
|
|
10
18
|
* vs a custom product attribute (nested under `product_attributes`).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { QueryableRoot } from './utils/recommendationBlockCount';
|
|
2
|
+
/**
|
|
3
|
+
* Advisory shown when a design ends up with more than one recommendation block,
|
|
4
|
+
* since multiple blocks can slow campaign delivery. Driven from the block
|
|
5
|
+
* lifecycle (`onCreated` for direct drop / duplicate, counting the editor's
|
|
6
|
+
* document root). `onCreated` also fires for a reco block that arrives inside a
|
|
7
|
+
* saved structure (SD-143028), so that case is covered without a separate
|
|
8
|
+
* `module_dropped` re-check.
|
|
9
|
+
*/
|
|
10
|
+
export declare const useRecommendationBlockWarning: () => {
|
|
11
|
+
warnIfMultipleBlocks: (root: QueryableRoot) => void;
|
|
12
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the extra recommendation feed query params for an account, if any.
|
|
3
|
+
* Accounts without customizations get an empty object.
|
|
4
|
+
* @param partnerName Account subdomain (`config.partner.name`)
|
|
5
|
+
* @param strategy Recommendation strategy key of the block
|
|
6
|
+
*/
|
|
7
|
+
export declare function getPartnerRecommendationParams(partnerName: string, strategy: string): Record<string, string>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Counts *live* recommendation blocks in a document.
|
|
3
|
+
*
|
|
4
|
+
* Deleting a recommendation block strips its inner content but leaves an empty
|
|
5
|
+
* `.recommendation-block-v2` container shell behind — present in every document
|
|
6
|
+
* representation the editor exposes (`getDocumentRoot`, `getDocumentRootHtmlNode`
|
|
7
|
+
* and even `getTemplateData`). A raw class count therefore over-reports after a
|
|
8
|
+
* delete→add cycle (SD-143028). The product row (`.recommendation-product-row`)
|
|
9
|
+
* is present on every live block from drop time (the default template ships
|
|
10
|
+
* product rows, both grid and list layouts) and is removed from a deleted
|
|
11
|
+
* block's leftover shell, so filtering by it cleanly separates live blocks from
|
|
12
|
+
* ghosts without reading any store.
|
|
13
|
+
*/
|
|
14
|
+
export declare const RECOMMENDATION_BLOCK_SELECTOR = ".recommendation-block-v2";
|
|
15
|
+
export declare const RECOMMENDATION_PRODUCT_ROW_SELECTOR = ".recommendation-product-row";
|
|
16
|
+
interface QueryableNode {
|
|
17
|
+
querySelector(selector: string): unknown;
|
|
18
|
+
}
|
|
19
|
+
export interface QueryableRoot {
|
|
20
|
+
querySelectorAll(selector: string): Iterable<QueryableNode>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Counts the live recommendation blocks reachable from `root`. Works on the
|
|
24
|
+
* editor's `ImmutableHtmlNode` document root (the `onCreated` drop / duplicate
|
|
25
|
+
* paths) and on any DOM-like root exposing `querySelectorAll`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function countLiveRecommendationBlocks(root: QueryableRoot): number;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,4 +1,20 @@
|
|
|
1
1
|
import type { SavedTemplateDetails } from '@@/Types/stripo';
|
|
2
|
+
/**
|
|
3
|
+
* Collects every unsubscribe page id referenced by the unsubscribe blocks
|
|
4
|
+
* present in the email HTML, deduped.
|
|
5
|
+
*
|
|
6
|
+
* The email's unsubscribe link is variation-scoped on the backend, which
|
|
7
|
+
* resolves the page to render from the page ids the FE persists for that
|
|
8
|
+
* variation. Those ids must reflect the blocks actually in the email — not a
|
|
9
|
+
* UI-only selection store — otherwise a block that entered the editor by any
|
|
10
|
+
* path other than the page-selection UI (e.g. a dropped saved module) sends an
|
|
11
|
+
* empty association and the backend falls back to the default page.
|
|
12
|
+
*
|
|
13
|
+
* Read from raw editor HTML: the `data-unsubscribe-page-list` attribute lives
|
|
14
|
+
* on the block node there (the save-time sync-module extractor relies on the
|
|
15
|
+
* same source), so it is reliably present regardless of how the block was added.
|
|
16
|
+
*/
|
|
17
|
+
export declare function getHtmlReferencedUnsubscribePages(html: string): number[];
|
|
2
18
|
export declare const useTemplatePreparation: () => {
|
|
3
19
|
prepareTemplateDetails: () => Promise<Omit<SavedTemplateDetails, "metadata">>;
|
|
4
20
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
import { useActionsApi as
|
|
2
|
-
import { useHtmlCompiler as
|
|
3
|
-
import { DEFAULT_CURRENCY as
|
|
1
|
+
import { useActionsApi as P } from "../composables/useActionsApi.js";
|
|
2
|
+
import { useHtmlCompiler as w } from "../composables/useHtmlCompiler.js";
|
|
3
|
+
import { DEFAULT_CURRENCY as l, DEFAULT_NODE_CONFIG as i } from "../extensions/Blocks/Recommendation/constants/defaultConfig.js";
|
|
4
4
|
import { useRecommendationExtensionStore as b } from "../extensions/Blocks/Recommendation/store/recommendation.js";
|
|
5
|
-
import { DATA_ATTRIBUTES as
|
|
6
|
-
import { parsePageList as
|
|
7
|
-
import { useDynamicContentStore as
|
|
8
|
-
import { useUnsubscribeStore as
|
|
9
|
-
function
|
|
10
|
-
const
|
|
11
|
-
return
|
|
12
|
-
const a =
|
|
13
|
-
a &&
|
|
14
|
-
}),
|
|
5
|
+
import { DATA_ATTRIBUTES as h } from "../extensions/Blocks/Unsubscribe/utils/constants.js";
|
|
6
|
+
import { parsePageList as E } from "../extensions/Blocks/Unsubscribe/utils/utils.js";
|
|
7
|
+
import { useDynamicContentStore as H } from "../stores/dynamic-content.js";
|
|
8
|
+
import { useUnsubscribeStore as U } from "../stores/unsubscribe.js";
|
|
9
|
+
function F(s) {
|
|
10
|
+
const o = new DOMParser().parseFromString(s, "text/html").querySelectorAll(`[${h.PAGE_LIST}]`), t = [];
|
|
11
|
+
return o.forEach((n) => {
|
|
12
|
+
const a = n.getAttribute(h.PAGE_LIST);
|
|
13
|
+
a && t.push(...E(a));
|
|
14
|
+
}), [...new Set(t)];
|
|
15
15
|
}
|
|
16
|
-
async function
|
|
17
|
-
const m = new DOMParser().parseFromString(
|
|
16
|
+
async function R(s) {
|
|
17
|
+
const m = new DOMParser().parseFromString(s, "text/html").querySelectorAll(".recommendation-block-v2");
|
|
18
18
|
if (m.length === 0)
|
|
19
19
|
return;
|
|
20
|
-
const
|
|
20
|
+
const o = b();
|
|
21
21
|
m.forEach((t) => {
|
|
22
|
-
var
|
|
23
|
-
const
|
|
24
|
-
if (!Number.isFinite(
|
|
22
|
+
var c, p, g, f, r;
|
|
23
|
+
const n = t.getAttribute("recommendation-id"), a = n ? Number(n) : NaN;
|
|
24
|
+
if (!Number.isFinite(a))
|
|
25
25
|
return;
|
|
26
|
-
const
|
|
27
|
-
if (!
|
|
26
|
+
const d = t.getAttribute("esd-ext-config");
|
|
27
|
+
if (!d)
|
|
28
28
|
return;
|
|
29
29
|
let e;
|
|
30
30
|
try {
|
|
31
|
-
e = JSON.parse(
|
|
31
|
+
e = JSON.parse(d);
|
|
32
32
|
} catch {
|
|
33
33
|
return;
|
|
34
34
|
}
|
|
35
35
|
if (!e || typeof e != "object" || Array.isArray(e))
|
|
36
36
|
return;
|
|
37
|
-
const
|
|
38
|
-
strategy: e.strategy ??
|
|
39
|
-
language: e.language ??
|
|
40
|
-
size: e.size ??
|
|
37
|
+
const y = {
|
|
38
|
+
strategy: e.strategy ?? i.strategy,
|
|
39
|
+
language: e.language ?? i.language,
|
|
40
|
+
size: e.size ?? i.size,
|
|
41
41
|
// Spread the default arrays so each block gets a fresh reference
|
|
42
42
|
// instead of sharing the singleton in DEFAULT_NODE_CONFIG.
|
|
43
|
-
productIds: e.productIds ?? [...
|
|
44
|
-
filters: e.filters ?? [...
|
|
45
|
-
shuffleProducts: e.shuffleProducts ??
|
|
46
|
-
currencyCode: ((
|
|
47
|
-
currencyAlignment: ((
|
|
48
|
-
currencyDecimalCount: ((
|
|
49
|
-
currencyDecimalSeparator: ((
|
|
50
|
-
currencyThousandSeparator: ((
|
|
43
|
+
productIds: e.productIds ?? [...i.productIds],
|
|
44
|
+
filters: e.filters ?? [...i.filters],
|
|
45
|
+
shuffleProducts: e.shuffleProducts ?? i.shuffleProducts,
|
|
46
|
+
currencyCode: ((c = e.currency) == null ? void 0 : c.code) ?? l.code,
|
|
47
|
+
currencyAlignment: ((p = e.currency) == null ? void 0 : p.alignment) ?? l.alignment,
|
|
48
|
+
currencyDecimalCount: ((g = e.currency) == null ? void 0 : g.decimalCount) ?? l.decimalCount,
|
|
49
|
+
currencyDecimalSeparator: ((f = e.currency) == null ? void 0 : f.decimalSeparator) ?? l.decimalSeparator,
|
|
50
|
+
currencyThousandSeparator: ((r = e.currency) == null ? void 0 : r.thousandSeparator) ?? l.thousandSeparator
|
|
51
51
|
};
|
|
52
|
-
|
|
52
|
+
o.seedBlockUrlConfig(a, y);
|
|
53
53
|
});
|
|
54
54
|
try {
|
|
55
|
-
await
|
|
55
|
+
await o.fetchRecommendationCreateData();
|
|
56
56
|
} catch (t) {
|
|
57
57
|
console.warn(
|
|
58
58
|
"Recommendation reference data pre-load failed; validator will skip the availability check.",
|
|
@@ -60,42 +60,43 @@ async function U(i) {
|
|
|
60
60
|
);
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
|
-
const
|
|
64
|
-
const
|
|
63
|
+
const v = () => {
|
|
64
|
+
const s = H(), u = U(), { getCompiledEmail: m, getTemplateData: o } = P(), { compileHtml: t, compileAmpHtml: n } = w();
|
|
65
65
|
return {
|
|
66
66
|
prepareTemplateDetails: async () => {
|
|
67
|
-
const { html:
|
|
67
|
+
const { html: d, ampHtml: e = "", ampErrors: y = [] } = await m({
|
|
68
68
|
minimize: !0,
|
|
69
69
|
resetDataSavedFlag: !1
|
|
70
|
-
}), { html:
|
|
71
|
-
|
|
72
|
-
const { compiledHtml:
|
|
70
|
+
}), { html: c, css: p, syncModulesIds: g = [] } = await o();
|
|
71
|
+
u.selectedUnsubscribePages.length && await u.fetchTemplates(), await R(c);
|
|
72
|
+
const { compiledHtml: f, stats: r, appliedRules: A } = t(d), C = e && n(e).compiledHtml, T = s.getSelectedDynamicContentList, D = b(), S = F(c);
|
|
73
73
|
return console.debug("HTML Compilation Stats:", {
|
|
74
|
-
originalSize:
|
|
75
|
-
compiledSize:
|
|
76
|
-
reduction: `${
|
|
77
|
-
appliedRules:
|
|
78
|
-
executionTime: `${
|
|
74
|
+
originalSize: r.originalSize,
|
|
75
|
+
compiledSize: r.compiledSize,
|
|
76
|
+
reduction: `${r.reductionPercentage.toFixed(2)}%`,
|
|
77
|
+
appliedRules: A,
|
|
78
|
+
executionTime: `${r.executionTime.toFixed(2)}ms`
|
|
79
79
|
}), {
|
|
80
|
-
dynamicContentList:
|
|
81
|
-
compiledHtml:
|
|
82
|
-
rawHtml:
|
|
83
|
-
css:
|
|
84
|
-
ampHtml:
|
|
85
|
-
ampErrors:
|
|
86
|
-
modules:
|
|
80
|
+
dynamicContentList: T,
|
|
81
|
+
compiledHtml: f,
|
|
82
|
+
rawHtml: c,
|
|
83
|
+
css: p,
|
|
84
|
+
ampHtml: C,
|
|
85
|
+
ampErrors: y,
|
|
86
|
+
modules: g.map(Number),
|
|
87
87
|
recommendation: {
|
|
88
|
-
campaignUrls:
|
|
88
|
+
campaignUrls: D.recommendationCampaignUrls,
|
|
89
89
|
configs: {}
|
|
90
90
|
},
|
|
91
91
|
unsubscribe: {
|
|
92
|
-
status:
|
|
93
|
-
config:
|
|
92
|
+
status: S.length > 0,
|
|
93
|
+
config: S
|
|
94
94
|
}
|
|
95
95
|
};
|
|
96
96
|
}
|
|
97
97
|
};
|
|
98
98
|
};
|
|
99
99
|
export {
|
|
100
|
-
|
|
100
|
+
F as getHtmlReferencedUnsubscribePages,
|
|
101
|
+
v as useTemplatePreparation
|
|
101
102
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@useinsider/guido",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.7.0-beta.509616e",
|
|
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",
|