coupon-shield 0.3.11
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/LICENSE +21 -0
- package/README.md +62 -0
- package/dist/auto.js +305 -0
- package/dist/bundle-tmp/auto.js +28 -0
- package/dist/bundle-tmp/core.js +286 -0
- package/dist/bundle-tmp/global.js +6 -0
- package/dist/bundle-tmp/version.js +2 -0
- package/dist/couponshield.js +295 -0
- package/dist/esm/core.js +286 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/version.js +2 -0
- package/dist/honey-detect.d.ts +22 -0
- package/dist/honey-detect.js +295 -0
- package/dist/index.js +115 -0
- package/dist/types/core.d.ts +20 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/version.d.ts +1 -0
- package/package.json +29 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Cooper Reid
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Coupon Shield
|
|
2
|
+
Tool for eComm merchants to detect, warn and prevent a customer from shopping using a shady coupon browser extension (Honey, Capital One Shopping, Rakuten).
|
|
3
|
+
<br /><br />View the [Demo video here 🎥](https://youtu.be/Em9Fjil8Xds).
|
|
4
|
+
|
|
5
|
+
<img width="1307" height="561" alt="image" src="https://github.com/user-attachments/assets/33b2554b-fc90-4b4b-b917-4ed088664200" />
|
|
6
|
+
|
|
7
|
+
## Easy install (no-JS)
|
|
8
|
+
This will automatically listen for Honey and show a default warning to the user to disable the extension as shown above).
|
|
9
|
+
|
|
10
|
+
Install this at the very top of the `<head>` in your webpage to ensure it runs prior to Honey.
|
|
11
|
+
[jsDelivr package page](https://www.jsdelivr.com/package/npm/coupon-shield).
|
|
12
|
+
```html
|
|
13
|
+
<script src="https://cdn.jsdelivr.net/npm/coupon-shield@latest/dist/auto.min.js"></script>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Custom Usage (Browser Global)
|
|
17
|
+
|
|
18
|
+
```html
|
|
19
|
+
<script src="https://cdn.jsdelivr.net/npm/coupon-shield@latest/dist/couponshield.js"></script>
|
|
20
|
+
<script>
|
|
21
|
+
window.couponShield.listen((warn, el, vendor) => {
|
|
22
|
+
// Decide how you want to handle this. Native warn function allows you to tell the user to disable Honey.
|
|
23
|
+
// vendor is "honey", "Capital One Shopping", or "Rakuten"
|
|
24
|
+
warn("You must disable the Honey extension to continue.");
|
|
25
|
+
});
|
|
26
|
+
</script>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Custom Usage (ESM)
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
npm install coupon-shield
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
import { listen } from "coupon-shield";
|
|
37
|
+
|
|
38
|
+
listen((warn, el, vendor) => {
|
|
39
|
+
// Decide how you want to handle this. Native warn function allows you to tell the user to disable Honey.
|
|
40
|
+
// vendor is "honey", "Capital One Shopping", or "Rakuten"
|
|
41
|
+
warn("You must disable the Honey extension to continue.");
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Advanced Options
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
window.couponShield.listen((warn, el, vendor) => {
|
|
49
|
+
// removeHoney defaults to true (element is auto-removed).
|
|
50
|
+
// Set removeHoney to false if you want to keep the Honey element for some reason.
|
|
51
|
+
// vendor is "honey", "Capital One Shopping", or "Rakuten"
|
|
52
|
+
}, { removeHoney: false });
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```js
|
|
56
|
+
window.couponShield.listen((warn) => {
|
|
57
|
+
// Stop observing if nothing is detected within 10 seconds.
|
|
58
|
+
}, { unbindAfterSeconds: 10 });
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Inspiration
|
|
62
|
+
[MegaLag exposed Honey as a scam](https://www.youtube.com/watch?v=wwB3FmbcC88)
|
package/dist/auto.js
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
(function() {
|
|
2
|
+
// dist/bundle-tmp/version.js
|
|
3
|
+
var VERSION = "0.3.11";
|
|
4
|
+
|
|
5
|
+
// dist/bundle-tmp/core.js
|
|
6
|
+
var __assign = function() {
|
|
7
|
+
__assign = Object.assign || function(t) {
|
|
8
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
9
|
+
s = arguments[i];
|
|
10
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
11
|
+
t[p] = s[p];
|
|
12
|
+
}
|
|
13
|
+
return t;
|
|
14
|
+
};
|
|
15
|
+
return __assign.apply(this, arguments);
|
|
16
|
+
};
|
|
17
|
+
var version = VERSION;
|
|
18
|
+
var DEFAULT_Z_NEAR_MAX = 214748e4;
|
|
19
|
+
var UUIDISH_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
20
|
+
var TARGET_SELECTOR = "div";
|
|
21
|
+
var OVERLAY_STYLE_ID = "simple-overlay-styles";
|
|
22
|
+
function showOverlay(message) {
|
|
23
|
+
if (typeof document === "undefined")
|
|
24
|
+
return function() {
|
|
25
|
+
};
|
|
26
|
+
if (!document.getElementById(OVERLAY_STYLE_ID)) {
|
|
27
|
+
var style = document.createElement("style");
|
|
28
|
+
style.id = OVERLAY_STYLE_ID;
|
|
29
|
+
style.textContent = ".simple-overlay{position:fixed;inset:0;background:rgba(0,0,0,0.6);z-index:2147483647;display:flex;align-items:center;justify-content:center;pointer-events:all;}.simple-overlay-message{background:#ffffff;padding:16px 20px;border-radius:8px;font-size:14px;max-width:80%;text-align:center;box-shadow:0 10px 30px rgba(0,0,0,0.3);}";
|
|
30
|
+
document.head.appendChild(style);
|
|
31
|
+
}
|
|
32
|
+
var overlay = document.createElement("div");
|
|
33
|
+
overlay.className = "simple-overlay";
|
|
34
|
+
var messageEl = document.createElement("div");
|
|
35
|
+
messageEl.className = "simple-overlay-message";
|
|
36
|
+
messageEl.innerHTML = message;
|
|
37
|
+
overlay.appendChild(messageEl);
|
|
38
|
+
if (document.body) {
|
|
39
|
+
document.body.appendChild(overlay);
|
|
40
|
+
}
|
|
41
|
+
var prevOverflow = document.body ? document.body.style.overflow : "";
|
|
42
|
+
if (document.body)
|
|
43
|
+
document.body.style.overflow = "hidden";
|
|
44
|
+
return function hideOverlay() {
|
|
45
|
+
overlay.remove();
|
|
46
|
+
if (document.body)
|
|
47
|
+
document.body.style.overflow = prevOverflow;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function parseZIndex(cs, el) {
|
|
51
|
+
var computed = parseInt(cs.zIndex, 10);
|
|
52
|
+
if (isFinite(computed))
|
|
53
|
+
return computed;
|
|
54
|
+
var inline = parseInt(el.style.zIndex, 10);
|
|
55
|
+
return isFinite(inline) ? inline : null;
|
|
56
|
+
}
|
|
57
|
+
function getDataGuidAttribute(el) {
|
|
58
|
+
for (var i = 0; i < el.attributes.length; i += 1) {
|
|
59
|
+
var attr = el.attributes[i];
|
|
60
|
+
if (!attr)
|
|
61
|
+
continue;
|
|
62
|
+
if (attr.name.indexOf("data-") === 0) {
|
|
63
|
+
var suffix = attr.name.slice(5);
|
|
64
|
+
if (UUIDISH_RE.test(suffix) && attr.value === "true") {
|
|
65
|
+
return attr.name;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
function hasNearMaxZIndex(el, zNearMax, debug) {
|
|
72
|
+
var inlineZ = parseInt(el.style.zIndex, 10);
|
|
73
|
+
if (!isFinite(inlineZ) || inlineZ < zNearMax) {
|
|
74
|
+
var cs_1 = getComputedStyle(el);
|
|
75
|
+
var z_1 = parseZIndex(cs_1, el);
|
|
76
|
+
if (z_1 === null || z_1 < zNearMax) {
|
|
77
|
+
if (debug)
|
|
78
|
+
console.log("+++ reject: z-index", z_1, cs_1.zIndex, el.style.zIndex, el);
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
if (cs_1.display === "none") {
|
|
82
|
+
if (debug)
|
|
83
|
+
console.log("+++ reject: display none", el);
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
var cs = getComputedStyle(el);
|
|
89
|
+
var z = parseZIndex(cs, el);
|
|
90
|
+
if (z === null || z < zNearMax) {
|
|
91
|
+
if (debug)
|
|
92
|
+
console.log("+++ reject: z-index", z, cs.zIndex, el.style.zIndex, el);
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
if (cs.display === "none") {
|
|
96
|
+
if (debug)
|
|
97
|
+
console.log("+++ reject: display none", el);
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
var VENDOR_MATCHERS = [
|
|
103
|
+
{
|
|
104
|
+
name: "honey",
|
|
105
|
+
matches: function(el, zNearMax, uuidGate, debug) {
|
|
106
|
+
if (!hasNearMaxZIndex(el, zNearMax, debug))
|
|
107
|
+
return false;
|
|
108
|
+
if (!el.id) {
|
|
109
|
+
if (debug)
|
|
110
|
+
console.log("+++ reject: no id", el);
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
if (uuidGate && !UUIDISH_RE.test(el.id)) {
|
|
114
|
+
if (debug)
|
|
115
|
+
console.log("+++ reject: uuid", el.id);
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
if (el.shadowRoot) {
|
|
119
|
+
if (debug)
|
|
120
|
+
console.log("+++ reject: shadowRoot", el);
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: "Capital One Shopping",
|
|
128
|
+
matches: function(el, zNearMax, _uuidGate, debug) {
|
|
129
|
+
if (!hasNearMaxZIndex(el, zNearMax, debug))
|
|
130
|
+
return false;
|
|
131
|
+
var dataGuid = getDataGuidAttribute(el);
|
|
132
|
+
if (!dataGuid) {
|
|
133
|
+
if (debug)
|
|
134
|
+
console.log("+++ reject: no data guid", el);
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
if (el.shadowRoot) {
|
|
138
|
+
if (debug)
|
|
139
|
+
console.log("+++ reject: shadowRoot", el);
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
if (debug)
|
|
143
|
+
console.log("+++ match capitalone", dataGuid, el);
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: "Rakuten",
|
|
149
|
+
matches: function(el, _zNearMax, _uuidGate, debug) {
|
|
150
|
+
if (!el.shadowRoot) {
|
|
151
|
+
if (debug)
|
|
152
|
+
console.log("+++ reject: no shadowRoot", el);
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
var style = el.shadowRoot.querySelector("style#rr-style-content");
|
|
156
|
+
if (!style) {
|
|
157
|
+
if (debug)
|
|
158
|
+
console.log("+++ reject: no rr-style-content", el);
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
];
|
|
165
|
+
function getVendorForDiv(el, zNearMax, uuidGate, debug) {
|
|
166
|
+
for (var i = 0; i < VENDOR_MATCHERS.length; i += 1) {
|
|
167
|
+
var matcher = VENDOR_MATCHERS[i];
|
|
168
|
+
if (matcher.matches(el, zNearMax, uuidGate, debug)) {
|
|
169
|
+
if (debug)
|
|
170
|
+
console.log("+++ match", matcher.name, el);
|
|
171
|
+
return matcher.name;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (debug)
|
|
175
|
+
console.log("+++ reject: no vendor match", el);
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
function scanElement(el, seen, zNearMax, uuidGate, debug, handleMatch) {
|
|
179
|
+
var _a;
|
|
180
|
+
if (el instanceof HTMLDivElement && el.matches(TARGET_SELECTOR)) {
|
|
181
|
+
var vendor = getVendorForDiv(el, zNearMax, uuidGate, debug);
|
|
182
|
+
if (seen.indexOf(el) === -1 && vendor) {
|
|
183
|
+
seen.push(el);
|
|
184
|
+
handleMatch(el, vendor);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
var divs = (_a = el.querySelectorAll) === null || _a === void 0 ? void 0 : _a.call(el, TARGET_SELECTOR);
|
|
188
|
+
if (!divs)
|
|
189
|
+
return;
|
|
190
|
+
for (var i = 0; i < divs.length; i += 1) {
|
|
191
|
+
var d = divs[i];
|
|
192
|
+
var vendor = getVendorForDiv(d, zNearMax, uuidGate, debug);
|
|
193
|
+
if (seen.indexOf(d) === -1 && vendor) {
|
|
194
|
+
seen.push(d);
|
|
195
|
+
handleMatch(d, vendor);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
function startHoneyOverlayObserver(options) {
|
|
200
|
+
var _a, _b, _c, _d, _e;
|
|
201
|
+
if (options === void 0) {
|
|
202
|
+
options = {};
|
|
203
|
+
}
|
|
204
|
+
var seen = [];
|
|
205
|
+
var zNearMax = (_a = options.zNearMax) !== null && _a !== void 0 ? _a : DEFAULT_Z_NEAR_MAX;
|
|
206
|
+
var uuidGate = (_b = options.uuidGate) !== null && _b !== void 0 ? _b : true;
|
|
207
|
+
var debug = (_c = options.debug) !== null && _c !== void 0 ? _c : false;
|
|
208
|
+
var removeHoney = (_d = options.removeHoney) !== null && _d !== void 0 ? _d : true;
|
|
209
|
+
var unbindAfterSeconds = options.unbindAfterSeconds;
|
|
210
|
+
var warn = function(message) {
|
|
211
|
+
return showOverlay(message);
|
|
212
|
+
};
|
|
213
|
+
var onMatch = (_e = options.onMatch) !== null && _e !== void 0 ? _e : (function() {
|
|
214
|
+
});
|
|
215
|
+
var matched = false;
|
|
216
|
+
var unbindTimer;
|
|
217
|
+
var handleMatch = function(el, vendor) {
|
|
218
|
+
matched = true;
|
|
219
|
+
if (typeof unbindTimer === "number") {
|
|
220
|
+
clearTimeout(unbindTimer);
|
|
221
|
+
unbindTimer = void 0;
|
|
222
|
+
}
|
|
223
|
+
if (removeHoney && el.parentNode)
|
|
224
|
+
el.parentNode.removeChild(el);
|
|
225
|
+
if (removeHoney) {
|
|
226
|
+
onMatch(warn, void 0, vendor);
|
|
227
|
+
} else {
|
|
228
|
+
onMatch(warn, el, vendor);
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
var mo = new MutationObserver(function(mutations) {
|
|
232
|
+
for (var _i = 0, mutations_1 = mutations; _i < mutations_1.length; _i++) {
|
|
233
|
+
var m = mutations_1[_i];
|
|
234
|
+
if (debug && document.body && (m.target === document.body || m.target instanceof Node && document.body.contains(m.target))) {
|
|
235
|
+
console.log("+++ body mutation", m.type, m.target);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
for (var _a2 = 0, mutations_2 = mutations; _a2 < mutations_2.length; _a2++) {
|
|
239
|
+
var m = mutations_2[_a2];
|
|
240
|
+
if (m.type === "childList") {
|
|
241
|
+
if (m.addedNodes.length) {
|
|
242
|
+
for (var i = 0; i < m.addedNodes.length; i += 1) {
|
|
243
|
+
var node = m.addedNodes[i];
|
|
244
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
245
|
+
scanElement(node, seen, zNearMax, uuidGate, debug, handleMatch);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (m.target instanceof Element) {
|
|
250
|
+
scanElement(m.target, seen, zNearMax, uuidGate, debug, handleMatch);
|
|
251
|
+
}
|
|
252
|
+
} else if (m.type === "attributes") {
|
|
253
|
+
if (m.target instanceof Element) {
|
|
254
|
+
scanElement(m.target, seen, zNearMax, uuidGate, debug, handleMatch);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
mo.observe(document.documentElement, {
|
|
260
|
+
subtree: true,
|
|
261
|
+
childList: true,
|
|
262
|
+
attributes: true,
|
|
263
|
+
attributeFilter: ["style", "class", "id"]
|
|
264
|
+
});
|
|
265
|
+
scanElement(document.documentElement, seen, zNearMax, uuidGate, debug, handleMatch);
|
|
266
|
+
if (typeof unbindAfterSeconds === "number" && unbindAfterSeconds > 0) {
|
|
267
|
+
unbindTimer = window.setTimeout(function() {
|
|
268
|
+
if (!matched) {
|
|
269
|
+
mo.disconnect();
|
|
270
|
+
}
|
|
271
|
+
}, unbindAfterSeconds * 1e3);
|
|
272
|
+
}
|
|
273
|
+
return {
|
|
274
|
+
stop: function() {
|
|
275
|
+
mo.disconnect();
|
|
276
|
+
if (typeof unbindTimer === "number") {
|
|
277
|
+
clearTimeout(unbindTimer);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
function listen(onMatch, options) {
|
|
283
|
+
if (options === void 0) {
|
|
284
|
+
options = {};
|
|
285
|
+
}
|
|
286
|
+
return startHoneyOverlayObserver(__assign(__assign({}, options), { onMatch: onMatch }));
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// dist/bundle-tmp/auto.js
|
|
290
|
+
function buildAutoModalHtml(vendor) {
|
|
291
|
+
var query = encodeURIComponent("Why is the " + vendor + " browser extension shady, and how can i uninstall it?");
|
|
292
|
+
var helpUrl = "http://chatgpt.com/?q=" + query;
|
|
293
|
+
return '<div class="modal" role="dialog" aria-modal="true" aria-labelledby="honey-modal-title"><h2 id="honey-modal-title"><span style="font-weight:400;">This site can\u2019t proceed with </span><strong>' + vendor + '</strong><span style="font-weight:400;"> Extension enabled</span></h2><div style="display:flex;gap:8px;flex-wrap:wrap;margin:8px 0 12px 0;align-items:stretch;"><a href="' + helpUrl + '" target="_blank" rel="noopener noreferrer" style="display:flex;align-items:center;justify-content:center;text-align:center;min-height:52px;padding:10px 12px;background:#e6eef7;color:#0b1b2b;text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:3px;border-radius:6px;flex:1 1 240px;">Please disable it to continue your checkout. \u26D4\uFE0F</a><a href="https://www.youtube.com/watch?v=wwB3FmbcC88" target="_blank" rel="noopener noreferrer" style="display:flex;align-items:center;justify-content:center;text-align:center;min-height:52px;padding:10px 12px;background:#e6eef7;color:#0b1b2b;text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:3px;border-radius:6px;flex:1 1 240px;">Here is why \uD83C\uDFA5</a></div></div>';
|
|
294
|
+
}
|
|
295
|
+
if (typeof window !== "undefined") {
|
|
296
|
+
window.couponShield = window.couponShield || {};
|
|
297
|
+
window.couponShield.listen = listen;
|
|
298
|
+
window.couponShield.version = version;
|
|
299
|
+
window.couponShieldHandle = window.couponShield.listen(function(warn, _el, vendor) {
|
|
300
|
+
var vendorName = vendor || "honey";
|
|
301
|
+
var vendorLabel = vendorName.charAt(0).toUpperCase() + vendorName.slice(1);
|
|
302
|
+
warn(buildAutoModalHtml(vendorLabel));
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
})();
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { listen, version } from "./core";
|
|
2
|
+
function buildAutoModalHtml(vendor) {
|
|
3
|
+
var query = encodeURIComponent("Why is the " + vendor + " browser extension shady, and how can i uninstall it?");
|
|
4
|
+
var helpUrl = "http://chatgpt.com/?q=" + query;
|
|
5
|
+
return ('<div class="modal" role="dialog" aria-modal="true" aria-labelledby="honey-modal-title">' +
|
|
6
|
+
'<h2 id="honey-modal-title">' +
|
|
7
|
+
'<span style="font-weight:400;">This site can’t proceed with </span>' +
|
|
8
|
+
"<strong>" +
|
|
9
|
+
vendor +
|
|
10
|
+
'</strong><span style="font-weight:400;"> Extension enabled</span>' +
|
|
11
|
+
"</h2>" +
|
|
12
|
+
'<div style="display:flex;gap:8px;flex-wrap:wrap;margin:8px 0 12px 0;align-items:stretch;">' +
|
|
13
|
+
'<a href="' +
|
|
14
|
+
helpUrl +
|
|
15
|
+
'" target="_blank" rel="noopener noreferrer" style="display:flex;align-items:center;justify-content:center;text-align:center;min-height:52px;padding:10px 12px;background:#e6eef7;color:#0b1b2b;text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:3px;border-radius:6px;flex:1 1 240px;">Please disable it to continue your checkout. ⛔️</a>' +
|
|
16
|
+
'<a href="https://www.youtube.com/watch?v=wwB3FmbcC88" target="_blank" rel="noopener noreferrer" style="display:flex;align-items:center;justify-content:center;text-align:center;min-height:52px;padding:10px 12px;background:#e6eef7;color:#0b1b2b;text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:3px;border-radius:6px;flex:1 1 240px;">Here is why 🎥</a>' +
|
|
17
|
+
"</div></div>");
|
|
18
|
+
}
|
|
19
|
+
if (typeof window !== "undefined") {
|
|
20
|
+
window.couponShield = window.couponShield || {};
|
|
21
|
+
window.couponShield.listen = listen;
|
|
22
|
+
window.couponShield.version = version;
|
|
23
|
+
window.couponShieldHandle = window.couponShield.listen(function (warn, _el, vendor) {
|
|
24
|
+
var vendorName = vendor || "honey";
|
|
25
|
+
var vendorLabel = vendorName.charAt(0).toUpperCase() + vendorName.slice(1);
|
|
26
|
+
warn(buildAutoModalHtml(vendorLabel));
|
|
27
|
+
});
|
|
28
|
+
}
|