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