@useinsider/guido 3.12.0-beta.60e4757 → 3.12.0-beta.6d6e76b
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/dist/components/organisms/email-preview/desktop-preview/DesktopPreview.vue.js +1 -1
- package/dist/components/organisms/email-preview/desktop-preview/DesktopPreview.vue2.js +8 -8
- package/dist/components/organisms/email-preview/mobile-preview/ContentView.vue.js +5 -5
- package/dist/components/organisms/email-preview/mobile-preview/ContentView.vue2.js +10 -10
- package/dist/composables/useEmailTemplateApplier.js +46 -32
- package/dist/composables/usePreviewInteractionGuard.js +36 -11
- package/dist/composables/useRecommendationPreview.js +61 -60
- package/dist/extensions/Blocks/Unsubscribe/utils/constants.js +3 -2
- package/dist/guido.css +1 -1
- package/dist/services/stripoApi.js +18 -18
- package/dist/src/composables/usePreviewInteractionGuard.d.ts +1 -1
- package/dist/src/extensions/Blocks/Unsubscribe/utils/constants.d.ts +1 -0
- package/dist/src/stores/dynamic-content.d.ts +17 -0
- package/dist/src/utils/registerUsedDynamicContent.d.ts +13 -0
- package/dist/src/utils/urlSchemes.d.ts +6 -0
- package/dist/static/styles/components/base-input.css.js +6 -7
- package/dist/stores/dynamic-content.js +21 -2
- package/dist/utils/registerUsedDynamicContent.js +23 -0
- package/dist/utils/urlSchemes.js +4 -0
- package/package.json +1 -1
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { defineComponent as u, ref as a, onMounted as p, onBeforeUnmount as l, nextTick as
|
|
2
|
-
import { usePreviewInteractionGuard as
|
|
1
|
+
import { defineComponent as u, ref as a, onMounted as p, onBeforeUnmount as l, nextTick as d } from "vue";
|
|
2
|
+
import { usePreviewInteractionGuard as v } from "../../../../composables/usePreviewInteractionGuard.js";
|
|
3
3
|
import { useTranslations as _ } from "../../../../composables/useTranslations.js";
|
|
4
4
|
import { usePreviewStore as w } from "../../../../stores/preview.js";
|
|
5
5
|
import I from "./DesktopBrowserHeader.vue.js";
|
|
6
6
|
const C = /* @__PURE__ */ u({
|
|
7
7
|
__name: "DesktopPreview",
|
|
8
|
-
setup(
|
|
9
|
-
const i = _(), {
|
|
8
|
+
setup(P) {
|
|
9
|
+
const i = _(), { guardPreviewInteractions: t } = v(), o = a(), r = a(!1), c = w();
|
|
10
10
|
let e = null;
|
|
11
11
|
const f = (m) => {
|
|
12
12
|
t(m.target);
|
|
13
|
-
},
|
|
13
|
+
}, n = () => {
|
|
14
14
|
o.value && (e = new ResizeObserver(() => {
|
|
15
|
-
}), e.observe(o.value),
|
|
16
|
-
|
|
15
|
+
}), e.observe(o.value), d(() => {
|
|
16
|
+
r.value = !0;
|
|
17
17
|
}));
|
|
18
18
|
}, s = () => {
|
|
19
19
|
e == null || e.disconnect();
|
|
20
20
|
};
|
|
21
|
-
return p(
|
|
21
|
+
return p(n), l(s), { __sfc: !0, trans: i, guardPreviewInteractions: t, containerRef: o, isContainerReady: r, previewStore: c, resizeObserver: e, onIframeLoad: f, initIframe: n, cleanIframe: s, DesktopBrowserHeader: I };
|
|
22
22
|
}
|
|
23
23
|
});
|
|
24
24
|
export {
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import e from "./ContentView.vue2.js";
|
|
2
2
|
/* empty css */
|
|
3
3
|
import n from "../../../../_virtual/_plugin-vue2_normalizer.js";
|
|
4
|
-
var
|
|
4
|
+
var o = function() {
|
|
5
5
|
var t = this, s = t._self._c, a = t._self._setupProxy;
|
|
6
6
|
return s("div", { staticClass: "w-1 h-1 b-c-4 d-f f-d-c" }, [s("div", { staticClass: "d-f j-c-s-b a-i-c p-2 h-6-s" }, [s("div", { staticClass: "d-f a-i-c cur-p", on: { click: function(l) {
|
|
7
7
|
return t.$emit("back-to-inbox");
|
|
8
8
|
} } }, [s(a.InIcons, { staticClass: "f-s-3 i-c-7", attrs: { name: "line-chevron-left" } }), s("span", { staticClass: "ml-2 f-s-1 f-w-400 l-h-1 t-c-7" }, [t._v(t._s(a.trans("newsletter.inbox")))])], 1), s("div", { staticClass: "d-f a-i-c" }, [s(a.InIcons, { staticClass: "i-c-52", attrs: { name: "line-chevron-down" } }), s(a.InIcons, { staticClass: "ml-1 i-c-52", attrs: { name: "line-chevron-up" } })], 1)]), s("div", { staticClass: "iframe-wrapper f-g-1 o-h" }, [s("iframe", { ref: "iframeRef", staticClass: "iframe-scaled d-b b-c-4 bor-s-n", attrs: { sandbox: "allow-same-origin allow-popups allow-forms allow-scripts allow-popups-to-escape-sandbox", srcdoc: a.previewStore.previewHtml }, on: { load: a.onLoad } })])]);
|
|
9
|
-
},
|
|
9
|
+
}, i = [], r = /* @__PURE__ */ n(
|
|
10
10
|
e,
|
|
11
|
-
c,
|
|
12
11
|
o,
|
|
12
|
+
i,
|
|
13
13
|
!1,
|
|
14
14
|
null,
|
|
15
|
-
"
|
|
15
|
+
"f255b2bb"
|
|
16
16
|
);
|
|
17
|
-
const d =
|
|
17
|
+
const d = r.exports;
|
|
18
18
|
export {
|
|
19
19
|
d as default
|
|
20
20
|
};
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { defineComponent as
|
|
1
|
+
import { defineComponent as c, ref as a } from "vue";
|
|
2
2
|
import { usePreviewInteractionGuard as f } from "../../../../composables/usePreviewInteractionGuard.js";
|
|
3
3
|
import { useResponsivePreview as p } from "../../../../composables/useResponsivePreview.js";
|
|
4
4
|
import { useTranslations as u } from "../../../../composables/useTranslations.js";
|
|
5
5
|
import { usePreviewStore as v } from "../../../../stores/preview.js";
|
|
6
|
-
import { InIcons as
|
|
7
|
-
const
|
|
6
|
+
import { InIcons as d } from "@useinsider/design-system-vue";
|
|
7
|
+
const b = /* @__PURE__ */ c({
|
|
8
8
|
__name: "ContentView",
|
|
9
9
|
emits: ["back-to-inbox"],
|
|
10
|
-
setup(
|
|
11
|
-
const
|
|
10
|
+
setup(P) {
|
|
11
|
+
const m = u(), r = v(), t = a(), { setupResponsivePreview: n } = p(), { guardPreviewInteractions: s } = f(), i = (e) => {
|
|
12
12
|
["transform", "transform-origin", "height"].forEach((o) => {
|
|
13
13
|
e.documentElement.style.removeProperty(o);
|
|
14
14
|
});
|
|
15
15
|
};
|
|
16
|
-
return { __sfc: !0, trans:
|
|
17
|
-
const e =
|
|
18
|
-
o && (n(e), s(e),
|
|
19
|
-
}, InIcons:
|
|
16
|
+
return { __sfc: !0, trans: m, previewStore: r, iframeRef: t, setupResponsivePreview: n, guardPreviewInteractions: s, clearAMPTransforms: i, onLoad: () => {
|
|
17
|
+
const e = t.value, o = e == null ? void 0 : e.contentDocument;
|
|
18
|
+
o && (n(e), s(e), r.isAMPResponsive && i(o));
|
|
19
|
+
}, InIcons: d };
|
|
20
20
|
}
|
|
21
21
|
});
|
|
22
22
|
export {
|
|
23
|
-
|
|
23
|
+
b as default
|
|
24
24
|
};
|
|
@@ -1,43 +1,57 @@
|
|
|
1
|
-
import { useActionsApi as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import { useActionsApi as d } from "./useActionsApi.js";
|
|
2
|
+
import { useConfig as D } from "./useConfig.js";
|
|
3
|
+
import { useToaster as h } from "./useToaster.js";
|
|
4
|
+
import { useTranslations as E } from "./useTranslations.js";
|
|
5
|
+
import { ToasterTypeOptions as f } from "../enums/toaster.js";
|
|
6
|
+
import { useDynamicContentStore as A } from "../stores/dynamic-content.js";
|
|
7
|
+
import { flattenDynamicContentList as S } from "../utils/genericUtil.js";
|
|
8
|
+
import { extractUsedDynamicContent as O } from "../utils/registerUsedDynamicContent.js";
|
|
9
|
+
import { ref as U } from "vue";
|
|
10
|
+
const w = 250, o = U({}), s = {}, u = /* @__PURE__ */ new Map(), z = () => {
|
|
11
|
+
const { updateHtmlAndCss: c } = d(), { showToaster: m } = h(), y = E(), { template: T } = D(), v = A(), g = (e, t) => {
|
|
12
|
+
const a = y(e);
|
|
13
|
+
return a === e ? t : a;
|
|
14
|
+
}, C = (e) => {
|
|
15
|
+
o.value[e] === void 0 && (o.value = { ...o.value, [e]: "pending" });
|
|
16
|
+
}, l = (e, t, a) => {
|
|
17
|
+
var n;
|
|
18
|
+
o.value = { ...o.value, [e]: "applying" };
|
|
11
19
|
try {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
c(t, a), o.value = { ...o.value, [e]: "applied" };
|
|
21
|
+
try {
|
|
22
|
+
const r = S((n = T.value) == null ? void 0 : n.dynamicContentList), p = O(t, r);
|
|
23
|
+
p.length > 0 && v.registerDynamicContent(p);
|
|
24
|
+
} catch {
|
|
25
|
+
}
|
|
26
|
+
u.get(e) !== t && (u.set(e, t), m({
|
|
27
|
+
type: f.Success,
|
|
28
|
+
message: g("newsletter.ai-template-applied", "Template applied to the editor")
|
|
29
|
+
}));
|
|
30
|
+
} catch (r) {
|
|
31
|
+
o.value = { ...o.value, [e]: "failed" }, m({
|
|
32
|
+
type: f.Error,
|
|
33
|
+
message: r instanceof Error ? r.message : "Failed to apply template"
|
|
20
34
|
});
|
|
21
35
|
}
|
|
22
|
-
},
|
|
23
|
-
const t =
|
|
24
|
-
t && (clearTimeout(t), delete
|
|
36
|
+
}, i = (e) => {
|
|
37
|
+
const t = s[e];
|
|
38
|
+
t && (clearTimeout(t), delete s[e]);
|
|
25
39
|
};
|
|
26
|
-
return { applyStatus:
|
|
27
|
-
t.html && (
|
|
40
|
+
return { applyStatus: o, markPending: C, applyTemplate: (e, t) => {
|
|
41
|
+
t.html && (i(e), l(e, t.html, t.css ?? ""));
|
|
28
42
|
}, applyTemplateDebounced: (e, t) => {
|
|
29
43
|
if (!t.html)
|
|
30
44
|
return;
|
|
31
|
-
|
|
32
|
-
const { html:
|
|
33
|
-
|
|
34
|
-
delete
|
|
35
|
-
},
|
|
45
|
+
i(e);
|
|
46
|
+
const { html: a } = t, n = t.css ?? "";
|
|
47
|
+
s[e] = setTimeout(() => {
|
|
48
|
+
delete s[e], l(e, a, n);
|
|
49
|
+
}, w);
|
|
36
50
|
} };
|
|
37
|
-
},
|
|
38
|
-
Object.values(
|
|
51
|
+
}, G = () => {
|
|
52
|
+
Object.values(s).forEach(clearTimeout), Object.keys(s).forEach((c) => delete s[c]), o.value = {};
|
|
39
53
|
};
|
|
40
54
|
export {
|
|
41
|
-
|
|
42
|
-
|
|
55
|
+
G as resetEmailTemplateApplier,
|
|
56
|
+
z as useEmailTemplateApplier
|
|
43
57
|
};
|
|
@@ -1,17 +1,42 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { URLS as o, MERGE_TAGS as a } from "../enums/unsubscribe.js";
|
|
2
|
+
import { UNSUBSCRIBE_LINK_SELECTOR as i } from "../extensions/Blocks/Unsubscribe/utils/constants.js";
|
|
3
|
+
import { BASE_SAFE_URL_SCHEMES as u } from "../utils/urlSchemes.js";
|
|
4
|
+
const E = ["click", "auxclick"], d = [
|
|
5
|
+
...Object.values(a),
|
|
6
|
+
o.UNSUBSCRIBE_URL,
|
|
7
|
+
o.PREFERENCES_URL
|
|
8
|
+
], l = (e) => {
|
|
9
|
+
if (e.matches(i))
|
|
10
|
+
return !0;
|
|
11
|
+
const r = e.getAttribute("href") ?? "";
|
|
12
|
+
return d.some((t) => r.includes(t));
|
|
13
|
+
}, S = [...u, "tel:", "sms:"], f = (e) => {
|
|
14
|
+
const r = (e.getAttribute("href") ?? "").trim();
|
|
15
|
+
return r === "" || r.startsWith("#") || r.startsWith("{{") ? !1 : S.includes(e.protocol);
|
|
16
|
+
}, m = (e) => {
|
|
17
|
+
var t, n;
|
|
18
|
+
const r = (n = (t = e.target) == null ? void 0 : t.closest) == null ? void 0 : n.call(t, "a");
|
|
19
|
+
if (r) {
|
|
20
|
+
if (l(r) || !f(r)) {
|
|
21
|
+
e.preventDefault(), e.stopPropagation();
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
r.setAttribute("target", "_blank"), r.setAttribute("rel", "noopener noreferrer");
|
|
25
|
+
}
|
|
26
|
+
}, R = (e) => {
|
|
27
|
+
e.preventDefault(), e.stopPropagation();
|
|
28
|
+
}, s = /* @__PURE__ */ new WeakSet(), c = "guidoPreviewGuarded", g = () => ({ guardPreviewInteractions: (r) => {
|
|
4
29
|
try {
|
|
5
|
-
const
|
|
6
|
-
if (!
|
|
30
|
+
const t = r.contentDocument;
|
|
31
|
+
if (!t || s.has(t))
|
|
7
32
|
return;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
});
|
|
11
|
-
} catch (
|
|
12
|
-
console.warn("[usePreviewInteractionGuard] Could not guard preview iframe:",
|
|
33
|
+
delete t.documentElement.dataset[c], E.forEach((n) => {
|
|
34
|
+
t.addEventListener(n, m, !0);
|
|
35
|
+
}), t.addEventListener("submit", R, !0), s.add(t), t.documentElement.dataset[c] = "true";
|
|
36
|
+
} catch (t) {
|
|
37
|
+
console.warn("[usePreviewInteractionGuard] Could not guard preview iframe:", t);
|
|
13
38
|
}
|
|
14
39
|
} });
|
|
15
40
|
export {
|
|
16
|
-
|
|
41
|
+
g as usePreviewInteractionGuard
|
|
17
42
|
};
|
|
@@ -1,111 +1,112 @@
|
|
|
1
|
-
import { BLOCK_ROOT_SELECTOR as
|
|
2
|
-
import { useRecommendationExtensionStore as
|
|
3
|
-
import { formatPrice as
|
|
4
|
-
|
|
1
|
+
import { BLOCK_ROOT_SELECTOR as f, CURRENCY_ATTR as A, CONTAINER_SELECTOR as O } from "../extensions/Blocks/Recommendation/constants/selectors.js";
|
|
2
|
+
import { useRecommendationExtensionStore as C } from "../extensions/Blocks/Recommendation/store/recommendation.js";
|
|
3
|
+
import { formatPrice as _ } from "../extensions/Blocks/Recommendation/utils/priceFormatter.js";
|
|
4
|
+
import { BASE_SAFE_URL_SCHEMES as R } from "../utils/urlSchemes.js";
|
|
5
|
+
const S = `${f}[recommendation-id]`, h = ".product-old-price", T = /\{\{(?:reco_)?(\d+_\d+_[a-zA-Z0-9_.]+)\}\}/g, b = new RegExp(
|
|
5
6
|
"\\{%\\s*if\\s+([\\s\\S]+?)\\s*%\\}([\\s\\S]*?)(?:\\{%\\s*else\\s*%\\}([\\s\\S]*?))?\\{%\\s*endif\\s*%\\}",
|
|
6
7
|
"g"
|
|
7
8
|
);
|
|
8
|
-
function
|
|
9
|
+
function L(e) {
|
|
9
10
|
return e.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
10
11
|
}
|
|
11
|
-
function
|
|
12
|
-
var
|
|
13
|
-
const
|
|
14
|
-
return
|
|
12
|
+
function g(e) {
|
|
13
|
+
var c;
|
|
14
|
+
const i = (c = e.replace(/[\u0000-\u0020]+/g, "").toLowerCase().match(/^([a-z][a-z0-9+.-]*):/)) == null ? void 0 : c[1];
|
|
15
|
+
return i && !R.includes(`${i}:`) ? "" : e;
|
|
15
16
|
}
|
|
16
17
|
function N(e) {
|
|
17
|
-
const t = e.getAttribute(
|
|
18
|
+
const t = e.getAttribute(A.CURRENCY) || "USD", i = e.getAttribute(A.DECIMAL_SEPARATOR) || ".", c = e.getAttribute(A.THOUSAND_SEPARATOR) || ",";
|
|
18
19
|
return {
|
|
19
20
|
code: t,
|
|
20
|
-
symbol: e.getAttribute(
|
|
21
|
-
alignment: e.getAttribute(
|
|
22
|
-
decimalCount: parseInt(e.getAttribute(
|
|
23
|
-
decimalSeparator:
|
|
24
|
-
thousandSeparator:
|
|
21
|
+
symbol: e.getAttribute(A.SYMBOL) || t,
|
|
22
|
+
alignment: e.getAttribute(A.ALIGNMENT) === "0" ? "before" : "after",
|
|
23
|
+
decimalCount: parseInt(e.getAttribute(A.DECIMAL_COUNT) || "2") || 2,
|
|
24
|
+
decimalSeparator: i,
|
|
25
|
+
thousandSeparator: c
|
|
25
26
|
};
|
|
26
27
|
}
|
|
27
|
-
function
|
|
28
|
+
function E(e, t) {
|
|
28
29
|
return (e == null ? void 0 : e[t]) ?? Object.values(e ?? {})[0] ?? 0;
|
|
29
30
|
}
|
|
30
|
-
function
|
|
31
|
-
const
|
|
32
|
-
return
|
|
31
|
+
function $(e, t) {
|
|
32
|
+
const i = E(e.original_price, t), c = E(e.price, t), n = i > 0 ? Math.round((i - c) / i * 100) : 0;
|
|
33
|
+
return n > 0 ? `${n}%` : "0%";
|
|
33
34
|
}
|
|
34
|
-
function P(e, t,
|
|
35
|
-
|
|
36
|
-
const r = (m) => `${
|
|
37
|
-
e.set(r("name"),
|
|
38
|
-
e.set(r(`product_attribute.${m}`), String(
|
|
35
|
+
function P(e, t, i, c, n, a) {
|
|
36
|
+
c.forEach((o, s) => {
|
|
37
|
+
const r = (m) => `${i}_${s}_${m}`, u = _({ price: E(o.price, n.code), currency: n }), l = _({ price: E(o.original_price, n.code), currency: n }), d = $(o, n.code);
|
|
38
|
+
e.set(r("name"), o.name ?? ""), e.set(r("image_url"), g(o.image_url ?? "")), e.set(r("url"), g(o.url ?? "")), e.set(r("item_id"), o.item_id ?? ""), e.set(r("currency"), ""), e.set(r("price"), u), e.set(r("original_price"), l), e.set(r("discount"), d), e.set(r("omnibus_price"), l), e.set(r("omnibus_discount"), d), a && u === l && t.add(`${i}_${s}`), Object.entries(o.product_attributes ?? {}).forEach(([m, p]) => {
|
|
39
|
+
e.set(r(`product_attribute.${m}`), String(p)), e.set(r(m), String(p));
|
|
39
40
|
});
|
|
40
41
|
});
|
|
41
42
|
}
|
|
42
|
-
function
|
|
43
|
-
const
|
|
44
|
-
if (!
|
|
43
|
+
function z(e, t) {
|
|
44
|
+
const i = e.match(/^(.+?)\s*(!=|==)\s*"([^"]*)"$/);
|
|
45
|
+
if (!i)
|
|
45
46
|
return !0;
|
|
46
|
-
const [,
|
|
47
|
-
return
|
|
47
|
+
const [, c, n, a] = i, o = t.get(c.trim()) ?? "";
|
|
48
|
+
return n === "!=" ? o !== a : o === a;
|
|
48
49
|
}
|
|
49
|
-
function
|
|
50
|
+
function w(e, t) {
|
|
50
51
|
return e.replace(
|
|
51
|
-
|
|
52
|
-
(
|
|
52
|
+
b,
|
|
53
|
+
(i, c, n, a) => c.split(/\s+and\s+/).every((s) => z(s.trim(), t)) ? n : a ?? ""
|
|
53
54
|
);
|
|
54
55
|
}
|
|
55
|
-
function
|
|
56
|
+
function D(e) {
|
|
56
57
|
let t = e;
|
|
57
58
|
for (; t.children.length === 1; )
|
|
58
59
|
[t] = t.children;
|
|
59
60
|
return t;
|
|
60
61
|
}
|
|
61
|
-
function
|
|
62
|
-
var
|
|
62
|
+
function I(e, t) {
|
|
63
|
+
var o;
|
|
63
64
|
if (!t.size)
|
|
64
65
|
return e;
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
const r = Number(
|
|
66
|
+
const i = e.replaceAll("{%", "<!--{%").replaceAll("%}", "%}-->"), c = new DOMParser().parseFromString(i, "text/html");
|
|
67
|
+
c.querySelectorAll(S).forEach((s) => {
|
|
68
|
+
const r = Number(s.getAttribute("recommendation-id"));
|
|
68
69
|
if (!Number.isFinite(r))
|
|
69
70
|
return;
|
|
70
|
-
const u =
|
|
71
|
-
(u.length ? Array.from(u) : [
|
|
72
|
-
d.querySelectorAll(
|
|
73
|
-
t.has(`${r}_${
|
|
71
|
+
const u = s.querySelectorAll(O);
|
|
72
|
+
(u.length ? Array.from(u) : [s]).forEach((d) => {
|
|
73
|
+
d.querySelectorAll(h).forEach((m, p) => {
|
|
74
|
+
t.has(`${r}_${p}`) && (D(m).textContent = "");
|
|
74
75
|
});
|
|
75
76
|
});
|
|
76
77
|
});
|
|
77
|
-
const
|
|
78
|
-
return ((
|
|
79
|
-
` : "") +
|
|
78
|
+
const n = (o = e.match(/<!DOCTYPE[^>]*>/i)) == null ? void 0 : o[0];
|
|
79
|
+
return ((n ? `${n}
|
|
80
|
+
` : "") + c.documentElement.outerHTML).replaceAll("<!--{%", "{%").replaceAll("%}-->", "%}").replaceAll("<!--{%", "{%").replaceAll("%}-->", "%}");
|
|
80
81
|
}
|
|
81
|
-
function
|
|
82
|
+
function y(e) {
|
|
82
83
|
if (!e || !e.includes("recommendation-block-v2"))
|
|
83
84
|
return e;
|
|
84
|
-
const t =
|
|
85
|
-
if (
|
|
85
|
+
const t = C(), i = new DOMParser().parseFromString(e, "text/html"), c = Array.from(i.querySelectorAll(S)), n = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Set();
|
|
86
|
+
if (c.forEach((s) => {
|
|
86
87
|
var l;
|
|
87
|
-
const r = Number(
|
|
88
|
+
const r = Number(s.getAttribute("recommendation-id"));
|
|
88
89
|
if (!Number.isFinite(r))
|
|
89
90
|
return;
|
|
90
91
|
const u = ((l = t.blockStates[r]) == null ? void 0 : l.recommendationProducts) ?? [];
|
|
91
92
|
u.length && P(
|
|
92
|
-
|
|
93
|
+
n,
|
|
93
94
|
a,
|
|
94
95
|
r,
|
|
95
96
|
u,
|
|
96
|
-
N(
|
|
97
|
-
|
|
97
|
+
N(s),
|
|
98
|
+
s.getAttribute("hide-price") === "true"
|
|
98
99
|
);
|
|
99
|
-
}), !
|
|
100
|
+
}), !n.size)
|
|
100
101
|
return e;
|
|
101
|
-
let
|
|
102
|
-
return
|
|
103
|
-
|
|
104
|
-
(
|
|
105
|
-
),
|
|
102
|
+
let o = I(e, a);
|
|
103
|
+
return o = o.replace(
|
|
104
|
+
T,
|
|
105
|
+
(s, r) => n.has(r) ? L(n.get(r)) : s
|
|
106
|
+
), o = w(o, n), o;
|
|
106
107
|
}
|
|
107
|
-
const q = () => ({ substituteRecommendationPreview:
|
|
108
|
+
const q = () => ({ substituteRecommendationPreview: y });
|
|
108
109
|
export {
|
|
109
|
-
|
|
110
|
+
y as substituteRecommendationPreview,
|
|
110
111
|
q as useRecommendationPreview
|
|
111
112
|
};
|
|
@@ -5,9 +5,10 @@ const s = {
|
|
|
5
5
|
PAGE_TYPE: "data-unsubscribe-page-type",
|
|
6
6
|
PAGE_LIST: "data-unsubscribe-page-list",
|
|
7
7
|
BLOCK_ID: "data-unsubscribe-block-id"
|
|
8
|
-
}, c = ".unsubscribe-block-v2";
|
|
8
|
+
}, c = ".unsubscribe-block-v2", u = 'a[data-unsubscribe-link="true"], a.unsubscribe-link';
|
|
9
9
|
export {
|
|
10
10
|
b as DATA_ATTRIBUTES,
|
|
11
11
|
c as UNSUBSCRIBE_BLOCK_SELECTOR,
|
|
12
|
-
s as UNSUBSCRIBE_EVENTS
|
|
12
|
+
s as UNSUBSCRIBE_EVENTS,
|
|
13
|
+
u as UNSUBSCRIBE_LINK_SELECTOR
|
|
13
14
|
};
|
package/dist/guido.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-73199fa4] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-195ab6d4]{position:relative;display:inline-block}.new-tag[data-v-195ab6d4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-195ab6d4] .guido__view-option-selection-desktop svg,[data-v-195ab6d4] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-195ab6d4] .in-segments-wrapper__button_selected,[data-v-195ab6d4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-195ab6d4] .in-tooltip-wrapper__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-d405ca59]{position:relative;display:inline-block}.new-tag[data-v-d405ca59]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-d405ca59] .guido__verion-history-view-option-selection-desktop svg,[data-v-d405ca59] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-d405ca59] .in-segments-wrapper__button_selected,[data-v-d405ca59] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-d405ca59] .in-tooltip-wrapper__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-6e711fd7]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-50dac6de]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-50dac6de]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-50dac6de]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-91a26acd]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-91a26acd]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-91a26acd]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-91a26acd]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-91a26acd]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-
|
|
1
|
+
.gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-73199fa4] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-195ab6d4]{position:relative;display:inline-block}.new-tag[data-v-195ab6d4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-195ab6d4] .guido__view-option-selection-desktop svg,[data-v-195ab6d4] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-195ab6d4] .in-segments-wrapper__button_selected,[data-v-195ab6d4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-195ab6d4] .in-tooltip-wrapper__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-d405ca59]{position:relative;display:inline-block}.new-tag[data-v-d405ca59]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-d405ca59] .guido__verion-history-view-option-selection-desktop svg,[data-v-d405ca59] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-d405ca59] .in-segments-wrapper__button_selected,[data-v-d405ca59] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-d405ca59] .in-tooltip-wrapper__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-6e711fd7]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-50dac6de]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-50dac6de]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-50dac6de]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-91a26acd]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-91a26acd]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-91a26acd]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-91a26acd]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-91a26acd]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-cf946232]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-cf946232]{min-height:504px}.iframe-wrapper[data-v-f255b2bb]{width:258px}.iframe-scaled[data-v-f255b2bb]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-6bcaca8a] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-f16f20f8] .vueperslides__bullets{pointer-events:none!important}[data-v-f16f20f8] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-bb3cca55] .vueperslides__bullets{pointer-events:none!important}[data-v-bb3cca55] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-b09e80c4] .vueperslides__bullets{pointer-events:none!important}[data-v-b09e80c4] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-9bdef600] .vueperslides__parallax-wrapper{padding-bottom:110px!important}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import { useHttp as
|
|
2
|
-
import { useToaster as
|
|
3
|
-
import { MAX_DEFAULT_TEMPLATE_ID as
|
|
4
|
-
import { useBlankTemplate as
|
|
5
|
-
const
|
|
6
|
-
|
|
1
|
+
import { useHttp as m } from "../composables/useHttp.js";
|
|
2
|
+
import { useToaster as y } from "../composables/useToaster.js";
|
|
3
|
+
import { MAX_DEFAULT_TEMPLATE_ID as f } from "../enums/defaults.js";
|
|
4
|
+
import { useBlankTemplate as g } from "./blankTemplate.js";
|
|
5
|
+
const l = () => ({
|
|
6
|
+
id: 0,
|
|
7
|
+
stripoId: 0,
|
|
8
|
+
unsubscriptionPreferencePages: []
|
|
9
|
+
}), D = () => {
|
|
10
|
+
const { get: s, post: u } = m(), { handleError: r } = y(), { getBlankTemplate: n } = g();
|
|
7
11
|
return {
|
|
8
12
|
getToken: async () => {
|
|
9
13
|
try {
|
|
@@ -26,13 +30,13 @@ const D = () => {
|
|
|
26
30
|
},
|
|
27
31
|
getDefaultTemplate: async () => {
|
|
28
32
|
try {
|
|
29
|
-
const t = new URLSearchParams(window.location.search), e = t.get("default-template"),
|
|
30
|
-
if (!i && !
|
|
31
|
-
return await
|
|
32
|
-
const
|
|
33
|
-
return !a || typeof a != "object" || !("html" in a) || !("css" in a) ? await
|
|
33
|
+
const t = new URLSearchParams(window.location.search), e = t.get("default-template"), p = t.get("master"), o = e ? parseInt(e) : 0, i = o >= 1 && o <= f ? o : 0;
|
|
34
|
+
if (!i && !p)
|
|
35
|
+
return await n();
|
|
36
|
+
const d = `/stripo/default-template/${i}`, { data: c } = await s(d), a = typeof c == "string" ? JSON.parse(c) : c;
|
|
37
|
+
return !a || typeof a != "object" || !("html" in a) || !("css" in a) ? await n() : a;
|
|
34
38
|
} catch (t) {
|
|
35
|
-
return r(t, "Failed to fetch default template"),
|
|
39
|
+
return r(t, "Failed to fetch default template"), n();
|
|
36
40
|
}
|
|
37
41
|
},
|
|
38
42
|
getSyncModulesStatus: async () => {
|
|
@@ -53,13 +57,9 @@ const D = () => {
|
|
|
53
57
|
getSyncModule: async (t) => {
|
|
54
58
|
try {
|
|
55
59
|
const { data: e } = await s(`/stripo/stripo-modules/${t}/get`);
|
|
56
|
-
return e;
|
|
60
|
+
return Array.isArray(e == null ? void 0 : e.unsubscriptionPreferencePages) ? e : l();
|
|
57
61
|
} catch (e) {
|
|
58
|
-
return r(e, "Failed to get sync module"),
|
|
59
|
-
id: 0,
|
|
60
|
-
stripoId: 0,
|
|
61
|
-
unsubscriptionPreferencePages: []
|
|
62
|
-
};
|
|
62
|
+
return r(e, "Failed to get sync module"), l();
|
|
63
63
|
}
|
|
64
64
|
},
|
|
65
65
|
setSyncModuleUnsubscriptionPages: async (t) => {
|
|
@@ -9,3 +9,4 @@ export declare const DATA_ATTRIBUTES: {
|
|
|
9
9
|
readonly BLOCK_ID: "data-unsubscribe-block-id";
|
|
10
10
|
};
|
|
11
11
|
export declare const UNSUBSCRIBE_BLOCK_SELECTOR = ".unsubscribe-block-v2";
|
|
12
|
+
export declare const UNSUBSCRIBE_LINK_SELECTOR = "a[data-unsubscribe-link=\"true\"], a.unsubscribe-link";
|
|
@@ -36,4 +36,21 @@ export declare const useDynamicContentStore: import("pinia").StoreDefinition<"gu
|
|
|
36
36
|
}[];
|
|
37
37
|
}, {
|
|
38
38
|
setSelectedDynamicContent(dynamicContent: DynamicContent): void;
|
|
39
|
+
/**
|
|
40
|
+
* Bulk, append-only registration for dynamic content used by an
|
|
41
|
+
* AI-applied template (see useEmailTemplateApplier). Unlike
|
|
42
|
+
* `setSelectedDynamicContent`, this does NOT touch
|
|
43
|
+
* `selectedDynamicContent` (there is no single "active" picker
|
|
44
|
+
* selection here) — it only grows `selectedDynamicContentList`. The
|
|
45
|
+
* getter already removes duplicates, so a re-registration of the same
|
|
46
|
+
* entries (e.g. a re-apply) is harmless.
|
|
47
|
+
*
|
|
48
|
+
* `items` typically come straight from the host's own dynamic-content
|
|
49
|
+
* catalog (flattened `templateConfig.dynamicContentList`) — shallow-copy
|
|
50
|
+
* each one rather than storing the host's own object references, so
|
|
51
|
+
* Pinia/Vue's reactive conversion of this state can't turn a later
|
|
52
|
+
* in-place mutation of a "selected" item into an accidental write-back
|
|
53
|
+
* into the host's catalog.
|
|
54
|
+
*/
|
|
55
|
+
registerDynamicContent(items: DynamicContent[]): void;
|
|
39
56
|
}>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DynamicContent } from '@@/Types/generic';
|
|
2
|
+
export declare const extractUsedDynamicContent: (html: string, flattenedCatalog: DynamicContent[] | undefined | null) => DynamicContent[];
|
|
3
|
+
/**
|
|
4
|
+
* Dev-diagnostic sibling of `extractUsedDynamicContent`: the clean token names
|
|
5
|
+
* used in `html` that had NO catalog match (so were intentionally NOT
|
|
6
|
+
* registered). Wired into useEmailTemplateApplier's dev-gated `console.debug`
|
|
7
|
+
* so a developer can spot a neo↔guido personalization-vocabulary mismatch
|
|
8
|
+
* (see T-C2 report §8: neo may emit Atrium-schema keys the guido catalog
|
|
9
|
+
* doesn't recognize) in one look, without changing what actually gets
|
|
10
|
+
* registered. Same empty/undefined/null-catalog handling as
|
|
11
|
+
* `extractUsedDynamicContent` — never throws.
|
|
12
|
+
*/
|
|
13
|
+
export declare const getUnmatchedDynamicContentTokens: (html: string, flattenedCatalog: DynamicContent[] | undefined | null) => string[];
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL schemes that are safe to follow from partner-authored email HTML. Shared so a
|
|
3
|
+
* future bypass fix lands in one place — the preview guard and the recommendation
|
|
4
|
+
* sanitizer both gate on it. Stored with the trailing colon to match `anchor.protocol`.
|
|
5
|
+
*/
|
|
6
|
+
export declare const BASE_SAFE_URL_SCHEMES: readonly string[];
|
|
@@ -3,8 +3,12 @@ const n = `.base-input {
|
|
|
3
3
|
border-radius: 4px;
|
|
4
4
|
background-color: var(--guido-color-gray-0);
|
|
5
5
|
align-items: center;
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
/* 40px is a floor, never a cap: \`.base-input\` is shared by every settings field,
|
|
7
|
+
including Stripo's own auto-height inputs (e.g. the link field) that expand on
|
|
8
|
+
focus. A fixed max-height clamped their inner box; keep 40px only as the floor. */
|
|
9
|
+
min-height: 40px;
|
|
10
|
+
height: auto;
|
|
11
|
+
max-height: none;
|
|
8
12
|
box-sizing: content-box;
|
|
9
13
|
outline: none;
|
|
10
14
|
resize: vertical;
|
|
@@ -36,11 +40,6 @@ ue-contenteditable .base-input {
|
|
|
36
40
|
line-height: 24px;
|
|
37
41
|
}
|
|
38
42
|
|
|
39
|
-
/* Image link input is auto-height; lift the fixed 40px cap so it can grow. */
|
|
40
|
-
ue-contenteditable.link-autoheight-contenteditable .base-input {
|
|
41
|
-
max-height: none;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
43
|
ue-icon-component.icon-button.icon-clear-input {
|
|
45
44
|
right: 2px;
|
|
46
45
|
top: 2px;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { removeDuplicatesFromArray as n } from "../utils/arrayUtil.js";
|
|
2
2
|
import { defineStore as a } from "pinia";
|
|
3
|
-
const
|
|
3
|
+
const c = a("guidoDynamicContent", {
|
|
4
4
|
state: () => ({
|
|
5
5
|
selectedDynamicContent: { text: "", value: "" },
|
|
6
6
|
selectedDynamicContentList: []
|
|
@@ -8,6 +8,25 @@ const s = a("guidoDynamicContent", {
|
|
|
8
8
|
actions: {
|
|
9
9
|
setSelectedDynamicContent(t) {
|
|
10
10
|
this.selectedDynamicContent = t, this.selectedDynamicContentList.push(t);
|
|
11
|
+
},
|
|
12
|
+
/**
|
|
13
|
+
* Bulk, append-only registration for dynamic content used by an
|
|
14
|
+
* AI-applied template (see useEmailTemplateApplier). Unlike
|
|
15
|
+
* `setSelectedDynamicContent`, this does NOT touch
|
|
16
|
+
* `selectedDynamicContent` (there is no single "active" picker
|
|
17
|
+
* selection here) — it only grows `selectedDynamicContentList`. The
|
|
18
|
+
* getter already removes duplicates, so a re-registration of the same
|
|
19
|
+
* entries (e.g. a re-apply) is harmless.
|
|
20
|
+
*
|
|
21
|
+
* `items` typically come straight from the host's own dynamic-content
|
|
22
|
+
* catalog (flattened `templateConfig.dynamicContentList`) — shallow-copy
|
|
23
|
+
* each one rather than storing the host's own object references, so
|
|
24
|
+
* Pinia/Vue's reactive conversion of this state can't turn a later
|
|
25
|
+
* in-place mutation of a "selected" item into an accidental write-back
|
|
26
|
+
* into the host's catalog.
|
|
27
|
+
*/
|
|
28
|
+
registerDynamicContent(t) {
|
|
29
|
+
this.selectedDynamicContentList.push(...t.map((e) => ({ ...e })));
|
|
11
30
|
}
|
|
12
31
|
},
|
|
13
32
|
getters: {
|
|
@@ -20,5 +39,5 @@ const s = a("guidoDynamicContent", {
|
|
|
20
39
|
}
|
|
21
40
|
});
|
|
22
41
|
export {
|
|
23
|
-
|
|
42
|
+
c as useDynamicContentStore
|
|
24
43
|
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { DATA_ATTRIBUTE_REGEX as T } from "../enums/html-validator.js";
|
|
2
|
+
const d = /{{([a-zA-Z0-9_.\s]*)}}/gm, h = (n, e) => {
|
|
3
|
+
if (!e || e.length === 0)
|
|
4
|
+
return { matched: [], unmatchedTokens: [] };
|
|
5
|
+
const s = n.replace(T, "$1").match(d);
|
|
6
|
+
if (!s)
|
|
7
|
+
return { matched: [], unmatchedTokens: [] };
|
|
8
|
+
const u = new Map(
|
|
9
|
+
e.map((c) => [c.value.trim().toLowerCase(), c])
|
|
10
|
+
), a = /* @__PURE__ */ new Set(), o = [], m = [];
|
|
11
|
+
return s.forEach((c) => {
|
|
12
|
+
const t = c.slice(2, -2).trim().toLowerCase();
|
|
13
|
+
if (t === "" || a.has(t))
|
|
14
|
+
return;
|
|
15
|
+
a.add(t);
|
|
16
|
+
const r = u.get(t);
|
|
17
|
+
r ? o.push(r) : m.push(t);
|
|
18
|
+
}), { matched: o, unmatchedTokens: m };
|
|
19
|
+
}, E = (n, e) => h(n, e).matched, k = (n, e) => h(n, e).unmatchedTokens;
|
|
20
|
+
export {
|
|
21
|
+
E as extractUsedDynamicContent,
|
|
22
|
+
k as getUnmatchedDynamicContentTokens
|
|
23
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@useinsider/guido",
|
|
3
|
-
"version": "3.12.0-beta.
|
|
3
|
+
"version": "3.12.0-beta.6d6e76b",
|
|
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",
|