@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.js
CHANGED
|
@@ -1538,6 +1538,87 @@ function createSelectionOverlay() {
|
|
|
1538
1538
|
document.body.appendChild(overlay);
|
|
1539
1539
|
});
|
|
1540
1540
|
}
|
|
1541
|
+
function rectsIntersect(a, b) {
|
|
1542
|
+
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);
|
|
1543
|
+
}
|
|
1544
|
+
function intersectsCrossOriginIframe(selection) {
|
|
1545
|
+
const iframes = Array.from(document.querySelectorAll("iframe"));
|
|
1546
|
+
for (const iframe of iframes) {
|
|
1547
|
+
const rect = iframe.getBoundingClientRect();
|
|
1548
|
+
if (rect.width <= 0 || rect.height <= 0) {
|
|
1549
|
+
continue;
|
|
1550
|
+
}
|
|
1551
|
+
if (!rectsIntersect(selection, {
|
|
1552
|
+
left: rect.left,
|
|
1553
|
+
top: rect.top,
|
|
1554
|
+
width: rect.width,
|
|
1555
|
+
height: rect.height
|
|
1556
|
+
})) {
|
|
1557
|
+
continue;
|
|
1558
|
+
}
|
|
1559
|
+
try {
|
|
1560
|
+
if (!iframe.contentWindow || !iframe.contentDocument) {
|
|
1561
|
+
return true;
|
|
1562
|
+
}
|
|
1563
|
+
void iframe.contentDocument.location.href;
|
|
1564
|
+
} catch (e) {
|
|
1565
|
+
return true;
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
return false;
|
|
1569
|
+
}
|
|
1570
|
+
async function captureWithDisplayMedia(selection) {
|
|
1571
|
+
var _a;
|
|
1572
|
+
if (!((_a = navigator.mediaDevices) == null ? void 0 : _a.getDisplayMedia)) {
|
|
1573
|
+
throw new BugReporterError("CAPTURE_ERROR", "This page contains iframe content that needs screen-capture permission.");
|
|
1574
|
+
}
|
|
1575
|
+
let stream = null;
|
|
1576
|
+
const video = document.createElement("video");
|
|
1577
|
+
video.muted = true;
|
|
1578
|
+
video.playsInline = true;
|
|
1579
|
+
try {
|
|
1580
|
+
stream = await navigator.mediaDevices.getDisplayMedia({
|
|
1581
|
+
video: true,
|
|
1582
|
+
audio: false
|
|
1583
|
+
});
|
|
1584
|
+
video.srcObject = stream;
|
|
1585
|
+
await video.play();
|
|
1586
|
+
if (!video.videoWidth || !video.videoHeight) {
|
|
1587
|
+
await new Promise((resolve) => {
|
|
1588
|
+
video.onloadedmetadata = () => resolve();
|
|
1589
|
+
});
|
|
1590
|
+
}
|
|
1591
|
+
if (!video.videoWidth || !video.videoHeight) {
|
|
1592
|
+
throw new BugReporterError("CAPTURE_ERROR", "Could not read screen-capture frame.");
|
|
1593
|
+
}
|
|
1594
|
+
const scaleX = video.videoWidth / window.innerWidth;
|
|
1595
|
+
const scaleY = video.videoHeight / window.innerHeight;
|
|
1596
|
+
const sx = Math.max(0, Math.round(selection.left * scaleX));
|
|
1597
|
+
const sy = Math.max(0, Math.round(selection.top * scaleY));
|
|
1598
|
+
const sw = Math.max(1, Math.round(selection.width * scaleX));
|
|
1599
|
+
const sh = Math.max(1, Math.round(selection.height * scaleY));
|
|
1600
|
+
const canvas = document.createElement("canvas");
|
|
1601
|
+
canvas.width = sw;
|
|
1602
|
+
canvas.height = sh;
|
|
1603
|
+
const context = canvas.getContext("2d");
|
|
1604
|
+
if (!context) {
|
|
1605
|
+
throw new BugReporterError("CAPTURE_ERROR", "Canvas 2D context unavailable.");
|
|
1606
|
+
}
|
|
1607
|
+
context.drawImage(video, sx, sy, sw, sh, 0, 0, sw, sh);
|
|
1608
|
+
return await canvasToBlob(canvas);
|
|
1609
|
+
} catch (error) {
|
|
1610
|
+
if (error instanceof BugReporterError) {
|
|
1611
|
+
throw error;
|
|
1612
|
+
}
|
|
1613
|
+
if (error instanceof DOMException && error.name === "NotAllowedError") {
|
|
1614
|
+
throw new BugReporterError("PERMISSION_DENIED", "Permission denied for screen capture.", error);
|
|
1615
|
+
}
|
|
1616
|
+
throw new BugReporterError("CAPTURE_ERROR", "Fallback screen capture failed.", error);
|
|
1617
|
+
} finally {
|
|
1618
|
+
stream == null ? void 0 : stream.getTracks().forEach((track) => track.stop());
|
|
1619
|
+
video.srcObject = null;
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1541
1622
|
function canvasToBlob(canvas) {
|
|
1542
1623
|
return new Promise((resolve, reject) => {
|
|
1543
1624
|
canvas.toBlob((blob) => {
|
|
@@ -1554,6 +1635,9 @@ async function captureScreenshotArea(options) {
|
|
|
1554
1635
|
const masked = applyMasking(options.maskSelectors);
|
|
1555
1636
|
const textChanges = scrubText(document.body, options.redactTextPatterns);
|
|
1556
1637
|
try {
|
|
1638
|
+
if (intersectsCrossOriginIframe(selection)) {
|
|
1639
|
+
return await captureWithDisplayMedia(selection);
|
|
1640
|
+
}
|
|
1557
1641
|
const baseCanvas = await html2canvas(document.documentElement, {
|
|
1558
1642
|
useCORS: true,
|
|
1559
1643
|
scrollX: -window.scrollX,
|
|
@@ -1579,6 +1663,15 @@ async function captureScreenshotArea(options) {
|
|
|
1579
1663
|
context.drawImage(baseCanvas, sx, sy, sw, sh, 0, 0, sw, sh);
|
|
1580
1664
|
return await canvasToBlob(cropped);
|
|
1581
1665
|
} catch (error) {
|
|
1666
|
+
if (!intersectsCrossOriginIframe(selection)) {
|
|
1667
|
+
try {
|
|
1668
|
+
return await captureWithDisplayMedia(selection);
|
|
1669
|
+
} catch (fallbackError) {
|
|
1670
|
+
if (fallbackError instanceof BugReporterError) {
|
|
1671
|
+
throw fallbackError;
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1582
1675
|
if (error instanceof BugReporterError) {
|
|
1583
1676
|
throw error;
|
|
1584
1677
|
}
|