@useinsider/guido 3.20.1-beta.19f951a → 3.20.1-beta.5e7765e
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,42 +1,41 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import { useToaster as
|
|
5
|
-
import { ToasterTypeOptions as
|
|
1
|
+
var A = Object.defineProperty;
|
|
2
|
+
var y = (c, o, e) => o in c ? A(c, o, { enumerable: !0, configurable: !0, writable: !0, value: e }) : c[o] = e;
|
|
3
|
+
var g = (c, o, e) => y(c, typeof o != "symbol" ? o + "" : o, e);
|
|
4
|
+
import { useToaster as T } from "../../../composables/useToaster.js";
|
|
5
|
+
import { ToasterTypeOptions as I } from "../../../enums/toaster.js";
|
|
6
6
|
import { PAGE_TYPES as h } from "../../../enums/unsubscribe.js";
|
|
7
|
-
import { useEditorStore as
|
|
8
|
-
import { useUnsubscribeStore as
|
|
9
|
-
import { Block as
|
|
10
|
-
import { getDefaultTemplate as
|
|
11
|
-
import { UNSUBSCRIBE_BLOCK_SELECTOR as
|
|
12
|
-
import { parsePageList as
|
|
13
|
-
const
|
|
7
|
+
import { useEditorStore as L } from "../../../stores/editor.js";
|
|
8
|
+
import { useUnsubscribeStore as a } from "../../../stores/unsubscribe.js";
|
|
9
|
+
import { Block as C, BlockCompositionType as v, ContextActionType as S, ModificationDescription as u, BlockType as N } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
|
|
10
|
+
import { getDefaultTemplate as U } from "./template.js";
|
|
11
|
+
import { UNSUBSCRIBE_BLOCK_SELECTOR as B, DATA_ATTRIBUTES as n, UNSUBSCRIBE_EVENTS as m } from "./utils/constants.js";
|
|
12
|
+
import { parsePageList as f } from "./utils/utils.js";
|
|
13
|
+
const R = "unsubscribe-block", E = 'a[data-unsubscribe-link="true"]', D = "{{ins-unsubscribe-link}}", w = "https://academy.insiderone.com/docs/adding-unsubscribe-pages-into-emails", P = "Removing the unsubscribe text leaves an empty block, but an active unsubscribe link is required. Undo your last action to restore the text, or delete the unsubscribe block entirely.", x = {
|
|
14
14
|
[h.GLOBAL_UNSUBSCRIBE]: "{{ins-global-unsubscribe-link}}",
|
|
15
15
|
[h.SUBSCRIPTION_PREFERENCE_CENTER]: "{{ins-preferences-unsubscribe-link}}"
|
|
16
|
-
},
|
|
17
|
-
|
|
16
|
+
}, G = 3;
|
|
17
|
+
let d = null, p = null;
|
|
18
|
+
class j extends C {
|
|
18
19
|
constructor() {
|
|
19
20
|
super();
|
|
20
|
-
|
|
21
|
-
a(this, "cancelEventListener", null);
|
|
22
|
-
a(this, "currentNode");
|
|
21
|
+
g(this, "currentNode");
|
|
23
22
|
// Per-block "did this instance have a link last time we saw it?" tracking.
|
|
24
23
|
// Keyed by the stable `data-unsubscribe-block-id` we assign, because
|
|
25
24
|
// ImmutableHtmlNode instances are recreated on every document mutation and
|
|
26
25
|
// can't be used as Map keys directly. A singleton boolean here would be
|
|
27
26
|
// polluted across blocks since Stripo fires onDocumentChanged per-instance.
|
|
28
|
-
|
|
27
|
+
g(this, "linkStateByBlockId", /* @__PURE__ */ new Map());
|
|
29
28
|
// Per-block prepend retry counter for the leading text guard (SD-143097).
|
|
30
|
-
|
|
29
|
+
g(this, "guardAttemptsByBlockId", /* @__PURE__ */ new Map());
|
|
31
30
|
}
|
|
32
31
|
getId() {
|
|
33
|
-
return
|
|
32
|
+
return R;
|
|
34
33
|
}
|
|
35
34
|
getIcon() {
|
|
36
35
|
return "unsubscribe-icon";
|
|
37
36
|
}
|
|
38
37
|
getBlockCompositionType() {
|
|
39
|
-
return
|
|
38
|
+
return v.BLOCK;
|
|
40
39
|
}
|
|
41
40
|
getName() {
|
|
42
41
|
return this.api.translate("Unsubscribe Block");
|
|
@@ -45,16 +44,16 @@ class W extends T {
|
|
|
45
44
|
return this.api.translate("Unsubscribe Block Description");
|
|
46
45
|
}
|
|
47
46
|
getTemplate() {
|
|
48
|
-
return
|
|
47
|
+
return U();
|
|
49
48
|
}
|
|
50
49
|
getContextActionsIds() {
|
|
51
|
-
return [
|
|
50
|
+
return [S.MOVE, S.REMOVE];
|
|
52
51
|
}
|
|
53
52
|
onSelect(e) {
|
|
54
|
-
if (this.currentNode = e,
|
|
53
|
+
if (this.currentNode = e, L().isPreviewModeOpen)
|
|
55
54
|
return;
|
|
56
55
|
const t = this._getOrAssignBlockId(e);
|
|
57
|
-
t && this.linkStateByBlockId.set(t, this._hasUnsubscribeLink(e)), this._setupSelectEventListener(), this._setupCancelEventListener(t), !("getAttribute" in e && e.getAttribute("data-migration")) && (this._resetStoreState(), t && (
|
|
56
|
+
t && this.linkStateByBlockId.set(t, this._hasUnsubscribeLink(e)), this._setupSelectEventListener(), this._setupCancelEventListener(t), !("getAttribute" in e && e.getAttribute("data-migration")) && (this._resetStoreState(), t && (a().pendingBlockId = t), this._loadBlockState(e), this._checkExistingBlocks(), this._openDrawer());
|
|
58
57
|
}
|
|
59
58
|
onCreated(e) {
|
|
60
59
|
this._ensureLeadingTextGuard(e);
|
|
@@ -62,7 +61,7 @@ class W extends T {
|
|
|
62
61
|
onDocumentInit() {
|
|
63
62
|
try {
|
|
64
63
|
const e = this.api.getDocumentRoot();
|
|
65
|
-
e && "querySelectorAll" in e && e.querySelectorAll(
|
|
64
|
+
e && "querySelectorAll" in e && e.querySelectorAll(B).forEach((t) => {
|
|
66
65
|
this._ensureLeadingTextGuard(t);
|
|
67
66
|
});
|
|
68
67
|
} catch {
|
|
@@ -73,8 +72,8 @@ class W extends T {
|
|
|
73
72
|
const t = this._getOrAssignBlockId(e);
|
|
74
73
|
if (!t)
|
|
75
74
|
return;
|
|
76
|
-
const
|
|
77
|
-
this.linkStateByBlockId.get(t) === !0 && !
|
|
75
|
+
const i = this._hasUnsubscribeLink(e);
|
|
76
|
+
this.linkStateByBlockId.get(t) === !0 && !i && this._warnLinkRemoved(), this.linkStateByBlockId.set(t, i);
|
|
78
77
|
}
|
|
79
78
|
onDelete(e) {
|
|
80
79
|
this._removeEventListeners(), this._removeBlockTemplatesFromStore(e), this._resetStoreState();
|
|
@@ -95,27 +94,27 @@ class W extends T {
|
|
|
95
94
|
const t = e.querySelector(E);
|
|
96
95
|
if (!t)
|
|
97
96
|
return;
|
|
98
|
-
let
|
|
97
|
+
let i = t, r = i.parent();
|
|
99
98
|
for (; r && "getTagName" in r && r.getTagName().toLowerCase() !== "p"; )
|
|
100
|
-
|
|
99
|
+
i = r, r = r.parent();
|
|
101
100
|
if (!r || !("getTagName" in r) || r.getTagName().toLowerCase() !== "p")
|
|
102
101
|
return;
|
|
103
|
-
const
|
|
104
|
-
if (!!(
|
|
105
|
-
const
|
|
106
|
-
|
|
102
|
+
const s = i.previousSibling();
|
|
103
|
+
if (!!(s && s.getType() === "text" && s.getTextContent())) {
|
|
104
|
+
const b = this._readBlockId(e);
|
|
105
|
+
b && this.guardAttemptsByBlockId.delete(b);
|
|
107
106
|
return;
|
|
108
107
|
}
|
|
109
|
-
const
|
|
110
|
-
if (!
|
|
108
|
+
const k = this._getOrAssignBlockId(e);
|
|
109
|
+
if (!k)
|
|
111
110
|
return;
|
|
112
|
-
const
|
|
113
|
-
if (!(
|
|
114
|
-
this.guardAttemptsByBlockId.set(
|
|
111
|
+
const _ = this.guardAttemptsByBlockId.get(k) ?? 0;
|
|
112
|
+
if (!(_ >= G)) {
|
|
113
|
+
this.guardAttemptsByBlockId.set(k, _ + 1);
|
|
115
114
|
try {
|
|
116
|
-
this.api.getDocumentModifier().modifyHtml(r).prepend(" ").apply(new
|
|
117
|
-
} catch (
|
|
118
|
-
console.warn("[UnsubscribeBlock] Failed to ensure link text guard:",
|
|
115
|
+
this.api.getDocumentModifier().modifyHtml(r).prepend(" ").apply(new u("Ensure unsubscribe link text guard"));
|
|
116
|
+
} catch (b) {
|
|
117
|
+
console.warn("[UnsubscribeBlock] Failed to ensure link text guard:", b);
|
|
119
118
|
}
|
|
120
119
|
}
|
|
121
120
|
}
|
|
@@ -137,13 +136,13 @@ class W extends T {
|
|
|
137
136
|
return t;
|
|
138
137
|
if (!("getAttribute" in e))
|
|
139
138
|
return null;
|
|
140
|
-
const
|
|
139
|
+
const i = this._generateNextBlockId();
|
|
141
140
|
try {
|
|
142
|
-
this.api.getDocumentModifier().modifyHtml(e).setAttribute(n.BLOCK_ID,
|
|
141
|
+
this.api.getDocumentModifier().modifyHtml(e).setAttribute(n.BLOCK_ID, i).apply(new u(`Assign unsubscribe block id ${i}`));
|
|
143
142
|
} catch (r) {
|
|
144
143
|
return console.warn("[UnsubscribeBlock] Failed to assign block id:", r), null;
|
|
145
144
|
}
|
|
146
|
-
return
|
|
145
|
+
return i;
|
|
147
146
|
}
|
|
148
147
|
/**
|
|
149
148
|
* Generates a unique id by scanning the document for the highest existing
|
|
@@ -154,10 +153,10 @@ class W extends T {
|
|
|
154
153
|
let e = 0;
|
|
155
154
|
try {
|
|
156
155
|
const t = this.api.getDocumentRoot();
|
|
157
|
-
t && "querySelectorAll" in t && t.querySelectorAll(
|
|
156
|
+
t && "querySelectorAll" in t && t.querySelectorAll(B).forEach((r) => {
|
|
158
157
|
if ("getAttribute" in r) {
|
|
159
|
-
const
|
|
160
|
-
|
|
158
|
+
const s = r.getAttribute(n.BLOCK_ID), l = s ? parseInt(s) : 0;
|
|
159
|
+
l > e && (e = l);
|
|
161
160
|
}
|
|
162
161
|
});
|
|
163
162
|
} catch {
|
|
@@ -166,14 +165,14 @@ class W extends T {
|
|
|
166
165
|
}
|
|
167
166
|
_warnLinkRemoved() {
|
|
168
167
|
try {
|
|
169
|
-
const { showToaster: e } =
|
|
168
|
+
const { showToaster: e } = T();
|
|
170
169
|
e({
|
|
171
|
-
type:
|
|
172
|
-
message: this.api.translate(
|
|
170
|
+
type: I.Warning,
|
|
171
|
+
message: this.api.translate(P),
|
|
173
172
|
actionButton: {
|
|
174
173
|
text: this.api.translate("Visit Academy"),
|
|
175
174
|
onClick: () => {
|
|
176
|
-
window.open(
|
|
175
|
+
window.open(w, "_blank", "noopener,noreferrer");
|
|
177
176
|
}
|
|
178
177
|
}
|
|
179
178
|
});
|
|
@@ -182,28 +181,28 @@ class W extends T {
|
|
|
182
181
|
}
|
|
183
182
|
}
|
|
184
183
|
_setupSelectEventListener() {
|
|
185
|
-
this._removeSelectEventListener(),
|
|
186
|
-
const t = e, { collectionType:
|
|
187
|
-
this._updateBlock(
|
|
188
|
-
}, document.addEventListener(
|
|
184
|
+
this._removeSelectEventListener(), d = (e) => {
|
|
185
|
+
const t = e, { collectionType: i, selectedPages: r } = t.detail;
|
|
186
|
+
this._updateBlock(i, r.join(","));
|
|
187
|
+
}, document.addEventListener(m.SELECT, d);
|
|
189
188
|
}
|
|
190
189
|
_removeSelectEventListener() {
|
|
191
|
-
|
|
190
|
+
d && (document.removeEventListener(m.SELECT, d), d = null);
|
|
192
191
|
}
|
|
193
192
|
_setupCancelEventListener(e) {
|
|
194
|
-
this._removeCancelEventListener(),
|
|
195
|
-
const { detail:
|
|
196
|
-
((
|
|
197
|
-
}, document.addEventListener(
|
|
193
|
+
this._removeCancelEventListener(), p = (t) => {
|
|
194
|
+
const { detail: i } = t;
|
|
195
|
+
((i == null ? void 0 : i.blockId) ?? null) === e && this._handleCancel();
|
|
196
|
+
}, document.addEventListener(m.CANCEL, p);
|
|
198
197
|
}
|
|
199
198
|
_removeCancelEventListener() {
|
|
200
|
-
|
|
199
|
+
p && (document.removeEventListener(m.CANCEL, p), p = null);
|
|
201
200
|
}
|
|
202
201
|
_handleCancel() {
|
|
203
202
|
try {
|
|
204
203
|
if (!this.currentNode)
|
|
205
204
|
return;
|
|
206
|
-
this.api.getDocumentModifier().modifyHtml(this.currentNode).replaceWith(`<${
|
|
205
|
+
this.api.getDocumentModifier().modifyHtml(this.currentNode).replaceWith(`<${N.EMPTY_CONTAINER}/>`).apply(new u("Removed unsubscribe block due to cancel"));
|
|
207
206
|
} catch (e) {
|
|
208
207
|
console.warn("[UnsubscribeBlock] Failed to remove unsubscribe block:", e);
|
|
209
208
|
}
|
|
@@ -214,32 +213,32 @@ class W extends T {
|
|
|
214
213
|
_updateBlock(e, t) {
|
|
215
214
|
if (!this.currentNode || !("querySelector" in this.currentNode))
|
|
216
215
|
return;
|
|
217
|
-
const
|
|
218
|
-
if (!
|
|
216
|
+
const i = this.currentNode.querySelector(E);
|
|
217
|
+
if (!i)
|
|
219
218
|
return;
|
|
220
219
|
const r = this._getMergeTag(e);
|
|
221
|
-
this.api.getDocumentModifier().modifyHtml(
|
|
220
|
+
this.api.getDocumentModifier().modifyHtml(i).setAttribute("href", r).apply(new u(`Updated unsubscribe link to ${r}`)), this.api.getDocumentModifier().modifyHtml(this.currentNode).setAttribute(n.PAGE_TYPE, e.toString()).setAttribute(n.PAGE_LIST, t).apply(new u("Updated unsubscribe block metadata"));
|
|
222
221
|
}
|
|
223
222
|
_getMergeTag(e) {
|
|
224
|
-
return
|
|
223
|
+
return x[e] ?? D;
|
|
225
224
|
}
|
|
226
225
|
_openDrawer() {
|
|
227
226
|
if (!(this.currentNode && this.currentNode.getAttribute("data-unsubscribe-page-type")))
|
|
228
227
|
try {
|
|
229
|
-
const e =
|
|
228
|
+
const e = a();
|
|
230
229
|
e.typeSelectionDrawerStatus = !0;
|
|
231
230
|
} catch (e) {
|
|
232
231
|
console.error("[UnsubscribeBlock] Failed to open drawer:", e);
|
|
233
232
|
}
|
|
234
233
|
}
|
|
235
234
|
_checkExistingBlocks() {
|
|
236
|
-
const e =
|
|
237
|
-
e.isGlobalUnsubscribeDisabled = !1, e.isSubscriptionPreferencesCenterDisabled = !1, this.api.getDocumentRoot().querySelectorAll(
|
|
238
|
-
if ("getAttribute" in
|
|
239
|
-
const r =
|
|
235
|
+
const e = a();
|
|
236
|
+
e.isGlobalUnsubscribeDisabled = !1, e.isSubscriptionPreferencesCenterDisabled = !1, this.api.getDocumentRoot().querySelectorAll(B).forEach((i) => {
|
|
237
|
+
if ("getAttribute" in i) {
|
|
238
|
+
const r = i.getAttribute(n.PAGE_TYPE);
|
|
240
239
|
if (r) {
|
|
241
|
-
const
|
|
242
|
-
|
|
240
|
+
const s = Number(r);
|
|
241
|
+
s === h.GLOBAL_UNSUBSCRIBE ? e.isGlobalUnsubscribeDisabled = !0 : s === h.SUBSCRIPTION_PREFERENCE_CENTER && (e.isSubscriptionPreferencesCenterDisabled = !0);
|
|
243
242
|
}
|
|
244
243
|
}
|
|
245
244
|
});
|
|
@@ -247,14 +246,14 @@ class W extends T {
|
|
|
247
246
|
async _loadBlockState(e) {
|
|
248
247
|
if (!("getAttribute" in e))
|
|
249
248
|
return;
|
|
250
|
-
const t = e.getAttribute(n.PAGE_TYPE),
|
|
251
|
-
if (!t || !
|
|
249
|
+
const t = e.getAttribute(n.PAGE_TYPE), i = e.getAttribute(n.PAGE_LIST);
|
|
250
|
+
if (!t || !i)
|
|
252
251
|
return;
|
|
253
|
-
const r =
|
|
254
|
-
await r.fetchTemplates(), r.setCollectionWithoutAutoSelection(
|
|
252
|
+
const r = a(), s = Number(t), l = f(i);
|
|
253
|
+
await r.fetchTemplates(), r.setCollectionWithoutAutoSelection(s), r.loadSelectedTemplates(l);
|
|
255
254
|
}
|
|
256
255
|
_resetStoreState() {
|
|
257
|
-
|
|
256
|
+
a().$reset();
|
|
258
257
|
}
|
|
259
258
|
_removeBlockTemplatesFromStore(e) {
|
|
260
259
|
if (!("getAttribute" in e))
|
|
@@ -262,11 +261,11 @@ class W extends T {
|
|
|
262
261
|
const t = e.getAttribute(n.PAGE_LIST);
|
|
263
262
|
if (!t)
|
|
264
263
|
return;
|
|
265
|
-
const
|
|
266
|
-
|
|
264
|
+
const i = a(), r = f(t);
|
|
265
|
+
i.removeUnsubscribePages(r);
|
|
267
266
|
}
|
|
268
267
|
}
|
|
269
268
|
export {
|
|
270
|
-
|
|
271
|
-
|
|
269
|
+
R as UNSUBSCRIBE_BLOCK_ID,
|
|
270
|
+
j as UnsubscribeBlock
|
|
272
271
|
};
|
|
@@ -2,8 +2,6 @@ import type { ImmutableHtmlElementNode, ImmutableHtmlNode } from '@stripoinc/ui-
|
|
|
2
2
|
import { Block, BlockCompositionType } from '@stripoinc/ui-editor-extensions';
|
|
3
3
|
export declare const UNSUBSCRIBE_BLOCK_ID = "unsubscribe-block";
|
|
4
4
|
export declare class UnsubscribeBlock extends Block {
|
|
5
|
-
private selectEventListener;
|
|
6
|
-
private cancelEventListener;
|
|
7
5
|
private currentNode?;
|
|
8
6
|
private linkStateByBlockId;
|
|
9
7
|
private guardAttemptsByBlockId;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@useinsider/guido",
|
|
3
|
-
"version": "3.20.1-beta.
|
|
3
|
+
"version": "3.20.1-beta.5e7765e",
|
|
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",
|