@mushi-mushi/web 1.7.6 → 1.7.8
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/index.cjs +68 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +68 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3658,18 +3658,18 @@ function createScreenshotCapture(options = {}) {
|
|
|
3658
3658
|
const url = URL.createObjectURL(blob);
|
|
3659
3659
|
return new Promise((resolve) => {
|
|
3660
3660
|
img.onload = () => {
|
|
3661
|
-
ctx.drawImage(img, 0, 0, width, height);
|
|
3662
|
-
URL.revokeObjectURL(url);
|
|
3663
3661
|
try {
|
|
3664
|
-
|
|
3665
|
-
|
|
3662
|
+
ctx.drawImage(img, 0, 0, width, height);
|
|
3663
|
+
URL.revokeObjectURL(url);
|
|
3664
|
+
resolve(canvas.toDataURL("image/jpeg", 0.7));
|
|
3666
3665
|
} catch {
|
|
3667
|
-
|
|
3666
|
+
URL.revokeObjectURL(url);
|
|
3667
|
+
resolve(buildDegradedScreenshot(width, height));
|
|
3668
3668
|
}
|
|
3669
3669
|
};
|
|
3670
3670
|
img.onerror = () => {
|
|
3671
3671
|
URL.revokeObjectURL(url);
|
|
3672
|
-
resolve(
|
|
3672
|
+
resolve(buildDegradedScreenshot(width, height));
|
|
3673
3673
|
};
|
|
3674
3674
|
img.src = url;
|
|
3675
3675
|
});
|
|
@@ -3690,6 +3690,8 @@ var DEFAULT_REDACT_SELECTORS = [
|
|
|
3690
3690
|
];
|
|
3691
3691
|
function buildPrivacySafeDocument(privacy) {
|
|
3692
3692
|
const clone = document.documentElement.cloneNode(true);
|
|
3693
|
+
clone.querySelector("#mushi-mushi-widget")?.remove();
|
|
3694
|
+
stripTaintSources(clone);
|
|
3693
3695
|
const redactSelectors = privacy?.redactSelectors !== void 0 ? privacy.redactSelectors : DEFAULT_REDACT_SELECTORS;
|
|
3694
3696
|
for (const selector of redactSelectors) {
|
|
3695
3697
|
for (const el of safeQueryAll(clone, selector)) {
|
|
@@ -3728,6 +3730,46 @@ function redactElement(el) {
|
|
|
3728
3730
|
el.setAttribute("data-mushi-redacted", "true");
|
|
3729
3731
|
while (el.firstChild) el.removeChild(el.firstChild);
|
|
3730
3732
|
}
|
|
3733
|
+
function stripTaintSources(root) {
|
|
3734
|
+
const pageOrigin = typeof location !== "undefined" ? location.origin : "";
|
|
3735
|
+
for (const el of root.querySelectorAll("img, video, iframe, object, embed, picture")) {
|
|
3736
|
+
el.remove();
|
|
3737
|
+
}
|
|
3738
|
+
for (const link of root.querySelectorAll('link[rel="stylesheet"], link[as="style"]')) {
|
|
3739
|
+
const href = link.getAttribute("href");
|
|
3740
|
+
if (!href || isCrossOriginUrl(href, pageOrigin)) link.remove();
|
|
3741
|
+
}
|
|
3742
|
+
for (const script of root.querySelectorAll("script")) {
|
|
3743
|
+
script.remove();
|
|
3744
|
+
}
|
|
3745
|
+
}
|
|
3746
|
+
function isCrossOriginUrl(raw, pageOrigin) {
|
|
3747
|
+
if (!raw || raw.startsWith("data:") || raw.startsWith("blob:")) return false;
|
|
3748
|
+
try {
|
|
3749
|
+
const resolved = new URL(raw, typeof location !== "undefined" ? location.href : "http://localhost/");
|
|
3750
|
+
return Boolean(pageOrigin) && resolved.origin !== pageOrigin;
|
|
3751
|
+
} catch {
|
|
3752
|
+
return true;
|
|
3753
|
+
}
|
|
3754
|
+
}
|
|
3755
|
+
function buildDegradedScreenshot(width, height) {
|
|
3756
|
+
const canvas = document.createElement("canvas");
|
|
3757
|
+
const ctx = canvas.getContext("2d");
|
|
3758
|
+
if (!ctx) return null;
|
|
3759
|
+
canvas.width = width;
|
|
3760
|
+
canvas.height = height;
|
|
3761
|
+
ctx.fillStyle = "#111827";
|
|
3762
|
+
ctx.fillRect(0, 0, width, height);
|
|
3763
|
+
ctx.fillStyle = "#e5e7eb";
|
|
3764
|
+
ctx.font = "13px system-ui, sans-serif";
|
|
3765
|
+
ctx.fillText("Screenshot: layout captured (external media stripped)", 16, 28);
|
|
3766
|
+
ctx.fillText(`${width}\xD7${height}px`, 16, 48);
|
|
3767
|
+
try {
|
|
3768
|
+
return canvas.toDataURL("image/jpeg", 0.7);
|
|
3769
|
+
} catch {
|
|
3770
|
+
return null;
|
|
3771
|
+
}
|
|
3772
|
+
}
|
|
3731
3773
|
function maskElement(el) {
|
|
3732
3774
|
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
|
|
3733
3775
|
el.value = "";
|
|
@@ -4779,7 +4821,7 @@ function createProactiveManager(config = {}) {
|
|
|
4779
4821
|
|
|
4780
4822
|
// src/version.ts
|
|
4781
4823
|
var MUSHI_SDK_PACKAGE = "@mushi-mushi/web";
|
|
4782
|
-
var MUSHI_SDK_VERSION = "1.7.
|
|
4824
|
+
var MUSHI_SDK_VERSION = "1.7.7" ;
|
|
4783
4825
|
|
|
4784
4826
|
// src/mushi.ts
|
|
4785
4827
|
var instance = null;
|
|
@@ -4960,13 +5002,30 @@ function createInstance(config) {
|
|
|
4960
5002
|
});
|
|
4961
5003
|
let detachAutoBreadcrumbs = null;
|
|
4962
5004
|
detachAutoBreadcrumbs = installAutoBreadcrumbs(breadcrumbs);
|
|
5005
|
+
async function takeScreenshotWithoutChrome() {
|
|
5006
|
+
if (!screenshotCap) return null;
|
|
5007
|
+
const panelWasVisible = widget.getIsOpen();
|
|
5008
|
+
if (panelWasVisible) widget.hidePanel();
|
|
5009
|
+
const host = document.getElementById("mushi-mushi-widget");
|
|
5010
|
+
const prevVisibility = host?.style.visibility ?? "";
|
|
5011
|
+
if (host) host.style.visibility = "hidden";
|
|
5012
|
+
await new Promise((resolve) => {
|
|
5013
|
+
requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
|
|
5014
|
+
});
|
|
5015
|
+
try {
|
|
5016
|
+
return await screenshotCap.take();
|
|
5017
|
+
} finally {
|
|
5018
|
+
if (host) host.style.visibility = prevVisibility;
|
|
5019
|
+
if (panelWasVisible) widget.showPanel();
|
|
5020
|
+
}
|
|
5021
|
+
}
|
|
4963
5022
|
async function autoCaptureScreenshot(when) {
|
|
4964
5023
|
const mode = activeConfig.capture?.screenshot;
|
|
4965
5024
|
if (!screenshotCap || mode === "off" || pendingScreenshot) return;
|
|
4966
5025
|
if (when === "open" && mode !== "auto") return;
|
|
4967
5026
|
if (when === "submit" && mode !== "on-report" && mode !== "auto") return;
|
|
4968
5027
|
log.debug("Auto-capturing screenshot", { when, mode });
|
|
4969
|
-
pendingScreenshot = await
|
|
5028
|
+
pendingScreenshot = await takeScreenshotWithoutChrome();
|
|
4970
5029
|
widget.setScreenshotAttached(pendingScreenshot !== null);
|
|
4971
5030
|
}
|
|
4972
5031
|
widget = new MushiWidget(bootstrapConfig.widget, {
|
|
@@ -4996,7 +5055,7 @@ function createInstance(config) {
|
|
|
4996
5055
|
onScreenshotRequest: async () => {
|
|
4997
5056
|
if (!screenshotCap || activeConfig.capture?.screenshot === "off") return;
|
|
4998
5057
|
log.debug("Taking screenshot");
|
|
4999
|
-
pendingScreenshot = await
|
|
5058
|
+
pendingScreenshot = await takeScreenshotWithoutChrome();
|
|
5000
5059
|
widget.setScreenshotAttached(pendingScreenshot !== null);
|
|
5001
5060
|
},
|
|
5002
5061
|
onScreenshotRemove: () => {
|