@fogg/bug-reporter 1.0.2 → 1.0.3
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 +93 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +93 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1562,6 +1562,87 @@ function createSelectionOverlay() {
|
|
|
1562
1562
|
document.body.appendChild(overlay);
|
|
1563
1563
|
});
|
|
1564
1564
|
}
|
|
1565
|
+
function rectsIntersect(a, b) {
|
|
1566
|
+
return !(a.left + a.width <= b.left || b.left + b.width <= a.left || a.top + a.height <= b.top || b.top + b.height <= a.top);
|
|
1567
|
+
}
|
|
1568
|
+
function intersectsCrossOriginIframe(selection) {
|
|
1569
|
+
const iframes = Array.from(document.querySelectorAll("iframe"));
|
|
1570
|
+
for (const iframe of iframes) {
|
|
1571
|
+
const rect = iframe.getBoundingClientRect();
|
|
1572
|
+
if (rect.width <= 0 || rect.height <= 0) {
|
|
1573
|
+
continue;
|
|
1574
|
+
}
|
|
1575
|
+
if (!rectsIntersect(selection, {
|
|
1576
|
+
left: rect.left,
|
|
1577
|
+
top: rect.top,
|
|
1578
|
+
width: rect.width,
|
|
1579
|
+
height: rect.height
|
|
1580
|
+
})) {
|
|
1581
|
+
continue;
|
|
1582
|
+
}
|
|
1583
|
+
try {
|
|
1584
|
+
if (!iframe.contentWindow || !iframe.contentDocument) {
|
|
1585
|
+
return true;
|
|
1586
|
+
}
|
|
1587
|
+
void iframe.contentDocument.location.href;
|
|
1588
|
+
} catch (e) {
|
|
1589
|
+
return true;
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
return false;
|
|
1593
|
+
}
|
|
1594
|
+
async function captureWithDisplayMedia(selection) {
|
|
1595
|
+
var _a;
|
|
1596
|
+
if (!((_a = navigator.mediaDevices) == null ? void 0 : _a.getDisplayMedia)) {
|
|
1597
|
+
throw new BugReporterError("CAPTURE_ERROR", "This page contains iframe content that needs screen-capture permission.");
|
|
1598
|
+
}
|
|
1599
|
+
let stream = null;
|
|
1600
|
+
const video = document.createElement("video");
|
|
1601
|
+
video.muted = true;
|
|
1602
|
+
video.playsInline = true;
|
|
1603
|
+
try {
|
|
1604
|
+
stream = await navigator.mediaDevices.getDisplayMedia({
|
|
1605
|
+
video: true,
|
|
1606
|
+
audio: false
|
|
1607
|
+
});
|
|
1608
|
+
video.srcObject = stream;
|
|
1609
|
+
await video.play();
|
|
1610
|
+
if (!video.videoWidth || !video.videoHeight) {
|
|
1611
|
+
await new Promise((resolve) => {
|
|
1612
|
+
video.onloadedmetadata = () => resolve();
|
|
1613
|
+
});
|
|
1614
|
+
}
|
|
1615
|
+
if (!video.videoWidth || !video.videoHeight) {
|
|
1616
|
+
throw new BugReporterError("CAPTURE_ERROR", "Could not read screen-capture frame.");
|
|
1617
|
+
}
|
|
1618
|
+
const scaleX = video.videoWidth / window.innerWidth;
|
|
1619
|
+
const scaleY = video.videoHeight / window.innerHeight;
|
|
1620
|
+
const sx = Math.max(0, Math.round(selection.left * scaleX));
|
|
1621
|
+
const sy = Math.max(0, Math.round(selection.top * scaleY));
|
|
1622
|
+
const sw = Math.max(1, Math.round(selection.width * scaleX));
|
|
1623
|
+
const sh = Math.max(1, Math.round(selection.height * scaleY));
|
|
1624
|
+
const canvas = document.createElement("canvas");
|
|
1625
|
+
canvas.width = sw;
|
|
1626
|
+
canvas.height = sh;
|
|
1627
|
+
const context = canvas.getContext("2d");
|
|
1628
|
+
if (!context) {
|
|
1629
|
+
throw new BugReporterError("CAPTURE_ERROR", "Canvas 2D context unavailable.");
|
|
1630
|
+
}
|
|
1631
|
+
context.drawImage(video, sx, sy, sw, sh, 0, 0, sw, sh);
|
|
1632
|
+
return await canvasToBlob(canvas);
|
|
1633
|
+
} catch (error) {
|
|
1634
|
+
if (error instanceof BugReporterError) {
|
|
1635
|
+
throw error;
|
|
1636
|
+
}
|
|
1637
|
+
if (error instanceof DOMException && error.name === "NotAllowedError") {
|
|
1638
|
+
throw new BugReporterError("PERMISSION_DENIED", "Permission denied for screen capture.", error);
|
|
1639
|
+
}
|
|
1640
|
+
throw new BugReporterError("CAPTURE_ERROR", "Fallback screen capture failed.", error);
|
|
1641
|
+
} finally {
|
|
1642
|
+
stream == null ? void 0 : stream.getTracks().forEach((track) => track.stop());
|
|
1643
|
+
video.srcObject = null;
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1565
1646
|
function canvasToBlob(canvas) {
|
|
1566
1647
|
return new Promise((resolve, reject) => {
|
|
1567
1648
|
canvas.toBlob((blob) => {
|
|
@@ -1578,6 +1659,9 @@ async function captureScreenshotArea(options) {
|
|
|
1578
1659
|
const masked = applyMasking(options.maskSelectors);
|
|
1579
1660
|
const textChanges = scrubText(document.body, options.redactTextPatterns);
|
|
1580
1661
|
try {
|
|
1662
|
+
if (intersectsCrossOriginIframe(selection)) {
|
|
1663
|
+
return await captureWithDisplayMedia(selection);
|
|
1664
|
+
}
|
|
1581
1665
|
const baseCanvas = await html2canvas__default.default(document.documentElement, {
|
|
1582
1666
|
useCORS: true,
|
|
1583
1667
|
scrollX: -window.scrollX,
|
|
@@ -1603,6 +1687,15 @@ async function captureScreenshotArea(options) {
|
|
|
1603
1687
|
context.drawImage(baseCanvas, sx, sy, sw, sh, 0, 0, sw, sh);
|
|
1604
1688
|
return await canvasToBlob(cropped);
|
|
1605
1689
|
} catch (error) {
|
|
1690
|
+
if (!intersectsCrossOriginIframe(selection)) {
|
|
1691
|
+
try {
|
|
1692
|
+
return await captureWithDisplayMedia(selection);
|
|
1693
|
+
} catch (fallbackError) {
|
|
1694
|
+
if (fallbackError instanceof BugReporterError) {
|
|
1695
|
+
throw fallbackError;
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1606
1699
|
if (error instanceof BugReporterError) {
|
|
1607
1700
|
throw error;
|
|
1608
1701
|
}
|