@fogg/bug-reporter 1.0.0 → 1.0.1
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/README.md +30 -0
- package/dist/index.cjs +112 -87
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +112 -87
- package/dist/index.js.map +1 -1
- package/dist/{recording-ML63ZQ6A.cjs → recording-DZREYVVL.cjs} +6 -4
- package/dist/recording-DZREYVVL.cjs.map +1 -0
- package/dist/{recording-YSR6IORT.js → recording-QOCPVR5Y.js} +6 -4
- package/dist/recording-QOCPVR5Y.js.map +1 -0
- package/dist/{screenshot-FRAZAS6B.cjs → screenshot-AWRHVVWJ.cjs} +5 -4
- package/dist/screenshot-AWRHVVWJ.cjs.map +1 -0
- package/dist/{screenshot-F4W72WRK.js → screenshot-I2T6BTZB.js} +5 -4
- package/dist/screenshot-I2T6BTZB.js.map +1 -0
- package/package.json +1 -1
- package/dist/recording-ML63ZQ6A.cjs.map +0 -1
- package/dist/recording-YSR6IORT.js.map +0 -1
- package/dist/screenshot-F4W72WRK.js.map +0 -1
- package/dist/screenshot-FRAZAS6B.cjs.map +0 -1
|
@@ -13,7 +13,8 @@ function pickMimeType() {
|
|
|
13
13
|
return "video/webm";
|
|
14
14
|
}
|
|
15
15
|
async function startScreenRecording(options) {
|
|
16
|
-
|
|
16
|
+
var _a;
|
|
17
|
+
if (!((_a = navigator.mediaDevices) == null ? void 0 : _a.getDisplayMedia)) {
|
|
17
18
|
throw new chunk6TCI6T2U_cjs.BugReporterError("RECORDING_ERROR", "Screen recording is not supported by this browser.");
|
|
18
19
|
}
|
|
19
20
|
let stream;
|
|
@@ -46,8 +47,9 @@ async function startScreenRecording(options) {
|
|
|
46
47
|
rejectPromise = reject;
|
|
47
48
|
});
|
|
48
49
|
const tickInterval = window.setInterval(() => {
|
|
50
|
+
var _a2;
|
|
49
51
|
tickSeconds += 1;
|
|
50
|
-
options.onTick
|
|
52
|
+
(_a2 = options.onTick) == null ? void 0 : _a2.call(options, tickSeconds);
|
|
51
53
|
}, 1e3);
|
|
52
54
|
const hardStop = window.setTimeout(() => {
|
|
53
55
|
if (recorder.state !== "inactive") {
|
|
@@ -116,5 +118,5 @@ async function startScreenRecording(options) {
|
|
|
116
118
|
}
|
|
117
119
|
|
|
118
120
|
exports.startScreenRecording = startScreenRecording;
|
|
119
|
-
//# sourceMappingURL=recording-
|
|
120
|
-
//# sourceMappingURL=recording-
|
|
121
|
+
//# sourceMappingURL=recording-DZREYVVL.cjs.map
|
|
122
|
+
//# sourceMappingURL=recording-DZREYVVL.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/recording.ts"],"names":["BugReporterError","_a"],"mappings":"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","file":"recording-DZREYVVL.cjs","sourcesContent":["import { BugReporterError } from \"../types\";\n\nexport type RecordingResult = {\n blob: Blob;\n mimeType: string;\n durationMs: number;\n};\n\nexport type ActiveRecording = {\n stop: () => void;\n cancel: () => void;\n promise: Promise<RecordingResult>;\n};\n\ntype StartRecordingOptions = {\n maxSeconds: number;\n maxBytes: number;\n onTick?: (seconds: number) => void;\n};\n\nfunction pickMimeType(): string {\n const candidates = [\"video/webm;codecs=vp9\", \"video/webm;codecs=vp8\", \"video/webm\"];\n for (const candidate of candidates) {\n if (typeof MediaRecorder !== \"undefined\" && MediaRecorder.isTypeSupported(candidate)) {\n return candidate;\n }\n }\n return \"video/webm\";\n}\n\nexport async function startScreenRecording(options: StartRecordingOptions): Promise<ActiveRecording> {\n if (!navigator.mediaDevices?.getDisplayMedia) {\n throw new BugReporterError(\"RECORDING_ERROR\", \"Screen recording is not supported by this browser.\");\n }\n\n let stream: MediaStream;\n try {\n stream = await navigator.mediaDevices.getDisplayMedia({\n video: true,\n audio: false\n });\n } catch (error) {\n throw new BugReporterError(\"PERMISSION_DENIED\", \"Permission denied for screen recording.\", error);\n }\n\n const mimeType = pickMimeType();\n let recorder: MediaRecorder;\n try {\n recorder = new MediaRecorder(stream, { mimeType });\n } catch (error) {\n stream.getTracks().forEach((track) => track.stop());\n throw new BugReporterError(\"RECORDING_ERROR\", \"Could not initialize MediaRecorder.\", error);\n }\n\n const chunks: Blob[] = [];\n const startedAt = Date.now();\n let latestSize = 0;\n let tickSeconds = 0;\n let completed = false;\n let isCancelled = false;\n\n let resolvePromise: (value: RecordingResult) => void;\n let rejectPromise: (reason?: unknown) => void;\n\n const promise = new Promise<RecordingResult>((resolve, reject) => {\n resolvePromise = resolve;\n rejectPromise = reject;\n });\n\n const tickInterval = window.setInterval(() => {\n tickSeconds += 1;\n options.onTick?.(tickSeconds);\n }, 1000);\n\n const hardStop = window.setTimeout(() => {\n if (recorder.state !== \"inactive\") {\n recorder.stop();\n }\n }, options.maxSeconds * 1000);\n\n const teardown = () => {\n if (completed) {\n return;\n }\n completed = true;\n window.clearInterval(tickInterval);\n window.clearTimeout(hardStop);\n stream.getTracks().forEach((track) => track.stop());\n };\n\n recorder.addEventListener(\"dataavailable\", (event) => {\n if (!event.data || event.data.size === 0) {\n return;\n }\n chunks.push(event.data);\n latestSize += event.data.size;\n if (latestSize > options.maxBytes) {\n isCancelled = true;\n recorder.stop();\n rejectPromise(\n new BugReporterError(\n \"VALIDATION_ERROR\",\n `Recording exceeds max size (${Math.round(options.maxBytes / 1024 / 1024)}MB).`\n )\n );\n }\n });\n\n recorder.addEventListener(\"error\", (event) => {\n teardown();\n rejectPromise(new BugReporterError(\"RECORDING_ERROR\", \"Recording failed.\", event));\n });\n\n recorder.addEventListener(\"stop\", () => {\n teardown();\n if (isCancelled) {\n return;\n }\n const blob = new Blob(chunks, { type: mimeType });\n resolvePromise({\n blob,\n mimeType,\n durationMs: Date.now() - startedAt\n });\n });\n\n recorder.start(300);\n\n return {\n stop: () => {\n if (recorder.state !== \"inactive\") {\n recorder.stop();\n }\n },\n cancel: () => {\n isCancelled = true;\n if (recorder.state !== \"inactive\") {\n recorder.stop();\n }\n teardown();\n rejectPromise(new BugReporterError(\"ABORTED\", \"Recording cancelled by user.\"));\n },\n promise\n };\n}\n"]}
|
|
@@ -11,7 +11,8 @@ function pickMimeType() {
|
|
|
11
11
|
return "video/webm";
|
|
12
12
|
}
|
|
13
13
|
async function startScreenRecording(options) {
|
|
14
|
-
|
|
14
|
+
var _a;
|
|
15
|
+
if (!((_a = navigator.mediaDevices) == null ? void 0 : _a.getDisplayMedia)) {
|
|
15
16
|
throw new BugReporterError("RECORDING_ERROR", "Screen recording is not supported by this browser.");
|
|
16
17
|
}
|
|
17
18
|
let stream;
|
|
@@ -44,8 +45,9 @@ async function startScreenRecording(options) {
|
|
|
44
45
|
rejectPromise = reject;
|
|
45
46
|
});
|
|
46
47
|
const tickInterval = window.setInterval(() => {
|
|
48
|
+
var _a2;
|
|
47
49
|
tickSeconds += 1;
|
|
48
|
-
options.onTick
|
|
50
|
+
(_a2 = options.onTick) == null ? void 0 : _a2.call(options, tickSeconds);
|
|
49
51
|
}, 1e3);
|
|
50
52
|
const hardStop = window.setTimeout(() => {
|
|
51
53
|
if (recorder.state !== "inactive") {
|
|
@@ -114,5 +116,5 @@ async function startScreenRecording(options) {
|
|
|
114
116
|
}
|
|
115
117
|
|
|
116
118
|
export { startScreenRecording };
|
|
117
|
-
//# sourceMappingURL=recording-
|
|
118
|
-
//# sourceMappingURL=recording-
|
|
119
|
+
//# sourceMappingURL=recording-QOCPVR5Y.js.map
|
|
120
|
+
//# sourceMappingURL=recording-QOCPVR5Y.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/recording.ts"],"names":["_a"],"mappings":"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","file":"recording-QOCPVR5Y.js","sourcesContent":["import { BugReporterError } from \"../types\";\n\nexport type RecordingResult = {\n blob: Blob;\n mimeType: string;\n durationMs: number;\n};\n\nexport type ActiveRecording = {\n stop: () => void;\n cancel: () => void;\n promise: Promise<RecordingResult>;\n};\n\ntype StartRecordingOptions = {\n maxSeconds: number;\n maxBytes: number;\n onTick?: (seconds: number) => void;\n};\n\nfunction pickMimeType(): string {\n const candidates = [\"video/webm;codecs=vp9\", \"video/webm;codecs=vp8\", \"video/webm\"];\n for (const candidate of candidates) {\n if (typeof MediaRecorder !== \"undefined\" && MediaRecorder.isTypeSupported(candidate)) {\n return candidate;\n }\n }\n return \"video/webm\";\n}\n\nexport async function startScreenRecording(options: StartRecordingOptions): Promise<ActiveRecording> {\n if (!navigator.mediaDevices?.getDisplayMedia) {\n throw new BugReporterError(\"RECORDING_ERROR\", \"Screen recording is not supported by this browser.\");\n }\n\n let stream: MediaStream;\n try {\n stream = await navigator.mediaDevices.getDisplayMedia({\n video: true,\n audio: false\n });\n } catch (error) {\n throw new BugReporterError(\"PERMISSION_DENIED\", \"Permission denied for screen recording.\", error);\n }\n\n const mimeType = pickMimeType();\n let recorder: MediaRecorder;\n try {\n recorder = new MediaRecorder(stream, { mimeType });\n } catch (error) {\n stream.getTracks().forEach((track) => track.stop());\n throw new BugReporterError(\"RECORDING_ERROR\", \"Could not initialize MediaRecorder.\", error);\n }\n\n const chunks: Blob[] = [];\n const startedAt = Date.now();\n let latestSize = 0;\n let tickSeconds = 0;\n let completed = false;\n let isCancelled = false;\n\n let resolvePromise: (value: RecordingResult) => void;\n let rejectPromise: (reason?: unknown) => void;\n\n const promise = new Promise<RecordingResult>((resolve, reject) => {\n resolvePromise = resolve;\n rejectPromise = reject;\n });\n\n const tickInterval = window.setInterval(() => {\n tickSeconds += 1;\n options.onTick?.(tickSeconds);\n }, 1000);\n\n const hardStop = window.setTimeout(() => {\n if (recorder.state !== \"inactive\") {\n recorder.stop();\n }\n }, options.maxSeconds * 1000);\n\n const teardown = () => {\n if (completed) {\n return;\n }\n completed = true;\n window.clearInterval(tickInterval);\n window.clearTimeout(hardStop);\n stream.getTracks().forEach((track) => track.stop());\n };\n\n recorder.addEventListener(\"dataavailable\", (event) => {\n if (!event.data || event.data.size === 0) {\n return;\n }\n chunks.push(event.data);\n latestSize += event.data.size;\n if (latestSize > options.maxBytes) {\n isCancelled = true;\n recorder.stop();\n rejectPromise(\n new BugReporterError(\n \"VALIDATION_ERROR\",\n `Recording exceeds max size (${Math.round(options.maxBytes / 1024 / 1024)}MB).`\n )\n );\n }\n });\n\n recorder.addEventListener(\"error\", (event) => {\n teardown();\n rejectPromise(new BugReporterError(\"RECORDING_ERROR\", \"Recording failed.\", event));\n });\n\n recorder.addEventListener(\"stop\", () => {\n teardown();\n if (isCancelled) {\n return;\n }\n const blob = new Blob(chunks, { type: mimeType });\n resolvePromise({\n blob,\n mimeType,\n durationMs: Date.now() - startedAt\n });\n });\n\n recorder.start(300);\n\n return {\n stop: () => {\n if (recorder.state !== \"inactive\") {\n recorder.stop();\n }\n },\n cancel: () => {\n isCancelled = true;\n if (recorder.state !== \"inactive\") {\n recorder.stop();\n }\n teardown();\n rejectPromise(new BugReporterError(\"ABORTED\", \"Recording cancelled by user.\"));\n },\n promise\n };\n}\n"]}
|
|
@@ -19,6 +19,7 @@ function resetMasking(masked) {
|
|
|
19
19
|
});
|
|
20
20
|
}
|
|
21
21
|
function scrubText(root, patterns) {
|
|
22
|
+
var _a, _b;
|
|
22
23
|
if (!patterns.length) {
|
|
23
24
|
return [];
|
|
24
25
|
}
|
|
@@ -27,12 +28,12 @@ function scrubText(root, patterns) {
|
|
|
27
28
|
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
|
|
28
29
|
while (walker.nextNode()) {
|
|
29
30
|
const text = walker.currentNode;
|
|
30
|
-
let replaced = text.textContent
|
|
31
|
+
let replaced = (_a = text.textContent) != null ? _a : "";
|
|
31
32
|
for (const regex of regexes) {
|
|
32
33
|
replaced = replaced.replace(regex, "[redacted]");
|
|
33
34
|
}
|
|
34
35
|
if (replaced !== text.textContent) {
|
|
35
|
-
walkers.push({ node: text, previous: text.textContent
|
|
36
|
+
walkers.push({ node: text, previous: (_b = text.textContent) != null ? _b : "" });
|
|
36
37
|
text.textContent = replaced;
|
|
37
38
|
}
|
|
38
39
|
}
|
|
@@ -174,5 +175,5 @@ async function captureScreenshotArea(options) {
|
|
|
174
175
|
}
|
|
175
176
|
|
|
176
177
|
exports.captureScreenshotArea = captureScreenshotArea;
|
|
177
|
-
//# sourceMappingURL=screenshot-
|
|
178
|
-
//# sourceMappingURL=screenshot-
|
|
178
|
+
//# sourceMappingURL=screenshot-AWRHVVWJ.cjs.map
|
|
179
|
+
//# sourceMappingURL=screenshot-AWRHVVWJ.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/screenshot.ts"],"names":["BugReporterError"],"mappings":"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","file":"screenshot-AWRHVVWJ.cjs","sourcesContent":["import { BugReporterError } from \"../types\";\n\ntype CaptureOptions = {\n maskSelectors: string[];\n redactTextPatterns: Array<string | RegExp>;\n};\n\ntype SelectionRect = {\n left: number;\n top: number;\n width: number;\n height: number;\n};\n\nfunction applyMasking(selectors: string[]): Array<{ element: HTMLElement; previous: string }> {\n const masked: Array<{ element: HTMLElement; previous: string }> = [];\n for (const selector of selectors) {\n document.querySelectorAll<HTMLElement>(selector).forEach((element) => {\n masked.push({ element, previous: element.style.filter });\n element.style.filter = \"blur(12px)\";\n });\n }\n return masked;\n}\n\nfunction resetMasking(masked: Array<{ element: HTMLElement; previous: string }>): void {\n masked.forEach(({ element, previous }) => {\n element.style.filter = previous;\n });\n}\n\nfunction scrubText(root: HTMLElement, patterns: Array<string | RegExp>): Array<{ node: Text; previous: string }> {\n if (!patterns.length) {\n return [];\n }\n\n const walkers: Array<{ node: Text; previous: string }> = [];\n const regexes = patterns.map((pattern) => (typeof pattern === \"string\" ? new RegExp(pattern, \"g\") : pattern));\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);\n while (walker.nextNode()) {\n const text = walker.currentNode as Text;\n let replaced = text.textContent ?? \"\";\n for (const regex of regexes) {\n replaced = replaced.replace(regex, \"[redacted]\");\n }\n if (replaced !== text.textContent) {\n walkers.push({ node: text, previous: text.textContent ?? \"\" });\n text.textContent = replaced;\n }\n }\n return walkers;\n}\n\nfunction restoreText(changed: Array<{ node: Text; previous: string }>): void {\n changed.forEach(({ node, previous }) => {\n node.textContent = previous;\n });\n}\n\nfunction createSelectionOverlay(): Promise<SelectionRect> {\n return new Promise((resolve, reject) => {\n const overlay = document.createElement(\"div\");\n overlay.setAttribute(\"data-bug-reporter-overlay\", \"true\");\n overlay.style.position = \"fixed\";\n overlay.style.inset = \"0\";\n overlay.style.background = \"rgba(0,0,0,0.35)\";\n overlay.style.cursor = \"crosshair\";\n overlay.style.zIndex = \"2147483647\";\n\n const box = document.createElement(\"div\");\n box.style.position = \"fixed\";\n box.style.border = \"2px solid #ffffff\";\n box.style.background = \"rgba(27, 116, 228, 0.2)\";\n box.style.pointerEvents = \"none\";\n box.style.display = \"none\";\n overlay.appendChild(box);\n\n const cleanup = () => {\n overlay.removeEventListener(\"mousedown\", onMouseDown);\n overlay.removeEventListener(\"mousemove\", onMouseMove);\n overlay.removeEventListener(\"mouseup\", onMouseUp);\n window.removeEventListener(\"keydown\", onKeyDown);\n overlay.remove();\n };\n\n let startX = 0;\n let startY = 0;\n let isDragging = false;\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n cleanup();\n reject(new BugReporterError(\"ABORTED\", \"Screenshot capture cancelled.\"));\n }\n };\n\n const onMouseDown = (event: MouseEvent) => {\n isDragging = true;\n startX = event.clientX;\n startY = event.clientY;\n box.style.display = \"block\";\n box.style.left = `${startX}px`;\n box.style.top = `${startY}px`;\n box.style.width = \"0px\";\n box.style.height = \"0px\";\n };\n\n const onMouseMove = (event: MouseEvent) => {\n if (!isDragging) {\n return;\n }\n const left = Math.min(startX, event.clientX);\n const top = Math.min(startY, event.clientY);\n const width = Math.abs(startX - event.clientX);\n const height = Math.abs(startY - event.clientY);\n box.style.left = `${left}px`;\n box.style.top = `${top}px`;\n box.style.width = `${width}px`;\n box.style.height = `${height}px`;\n };\n\n const onMouseUp = (event: MouseEvent) => {\n if (!isDragging) {\n return;\n }\n isDragging = false;\n const left = Math.min(startX, event.clientX);\n const top = Math.min(startY, event.clientY);\n const width = Math.abs(startX - event.clientX);\n const height = Math.abs(startY - event.clientY);\n cleanup();\n if (width < 8 || height < 8) {\n reject(new BugReporterError(\"CAPTURE_ERROR\", \"Selection area is too small.\"));\n return;\n }\n resolve({ left, top, width, height });\n };\n\n overlay.addEventListener(\"mousedown\", onMouseDown);\n overlay.addEventListener(\"mousemove\", onMouseMove);\n overlay.addEventListener(\"mouseup\", onMouseUp);\n window.addEventListener(\"keydown\", onKeyDown);\n document.body.appendChild(overlay);\n });\n}\n\nfunction canvasToBlob(canvas: HTMLCanvasElement): Promise<Blob> {\n return new Promise((resolve, reject) => {\n canvas.toBlob((blob) => {\n if (!blob) {\n reject(new BugReporterError(\"CAPTURE_ERROR\", \"Failed to build screenshot blob.\"));\n return;\n }\n resolve(blob);\n }, \"image/png\");\n });\n}\n\nexport async function captureScreenshotArea(options: CaptureOptions): Promise<Blob> {\n const selection = await createSelectionOverlay();\n const masked = applyMasking(options.maskSelectors);\n const textChanges = scrubText(document.body, options.redactTextPatterns);\n\n try {\n const { default: html2canvas } = await import(\"html2canvas\");\n const baseCanvas = await html2canvas(document.documentElement, {\n useCORS: true,\n scrollX: -window.scrollX,\n scrollY: -window.scrollY,\n backgroundColor: null,\n logging: false,\n windowWidth: document.documentElement.scrollWidth,\n windowHeight: document.documentElement.scrollHeight\n });\n\n const scaleX = baseCanvas.width / window.innerWidth;\n const scaleY = baseCanvas.height / window.innerHeight;\n\n const sx = Math.round(selection.left * scaleX);\n const sy = Math.round(selection.top * scaleY);\n const sw = Math.round(selection.width * scaleX);\n const sh = Math.round(selection.height * scaleY);\n\n const cropped = document.createElement(\"canvas\");\n cropped.width = sw;\n cropped.height = sh;\n\n const context = cropped.getContext(\"2d\");\n if (!context) {\n throw new BugReporterError(\"CAPTURE_ERROR\", \"Canvas 2D context unavailable.\");\n }\n\n context.drawImage(baseCanvas, sx, sy, sw, sh, 0, 0, sw, sh);\n return await canvasToBlob(cropped);\n } catch (error) {\n if (error instanceof BugReporterError) {\n throw error;\n }\n throw new BugReporterError(\"CAPTURE_ERROR\", \"Screenshot capture failed.\", error);\n } finally {\n resetMasking(masked);\n restoreText(textChanges);\n }\n}\n"]}
|
|
@@ -17,6 +17,7 @@ function resetMasking(masked) {
|
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
19
|
function scrubText(root, patterns) {
|
|
20
|
+
var _a, _b;
|
|
20
21
|
if (!patterns.length) {
|
|
21
22
|
return [];
|
|
22
23
|
}
|
|
@@ -25,12 +26,12 @@ function scrubText(root, patterns) {
|
|
|
25
26
|
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
|
|
26
27
|
while (walker.nextNode()) {
|
|
27
28
|
const text = walker.currentNode;
|
|
28
|
-
let replaced = text.textContent
|
|
29
|
+
let replaced = (_a = text.textContent) != null ? _a : "";
|
|
29
30
|
for (const regex of regexes) {
|
|
30
31
|
replaced = replaced.replace(regex, "[redacted]");
|
|
31
32
|
}
|
|
32
33
|
if (replaced !== text.textContent) {
|
|
33
|
-
walkers.push({ node: text, previous: text.textContent
|
|
34
|
+
walkers.push({ node: text, previous: (_b = text.textContent) != null ? _b : "" });
|
|
34
35
|
text.textContent = replaced;
|
|
35
36
|
}
|
|
36
37
|
}
|
|
@@ -172,5 +173,5 @@ async function captureScreenshotArea(options) {
|
|
|
172
173
|
}
|
|
173
174
|
|
|
174
175
|
export { captureScreenshotArea };
|
|
175
|
-
//# sourceMappingURL=screenshot-
|
|
176
|
-
//# sourceMappingURL=screenshot-
|
|
176
|
+
//# sourceMappingURL=screenshot-I2T6BTZB.js.map
|
|
177
|
+
//# sourceMappingURL=screenshot-I2T6BTZB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/screenshot.ts"],"names":[],"mappings":"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","file":"screenshot-I2T6BTZB.js","sourcesContent":["import { BugReporterError } from \"../types\";\n\ntype CaptureOptions = {\n maskSelectors: string[];\n redactTextPatterns: Array<string | RegExp>;\n};\n\ntype SelectionRect = {\n left: number;\n top: number;\n width: number;\n height: number;\n};\n\nfunction applyMasking(selectors: string[]): Array<{ element: HTMLElement; previous: string }> {\n const masked: Array<{ element: HTMLElement; previous: string }> = [];\n for (const selector of selectors) {\n document.querySelectorAll<HTMLElement>(selector).forEach((element) => {\n masked.push({ element, previous: element.style.filter });\n element.style.filter = \"blur(12px)\";\n });\n }\n return masked;\n}\n\nfunction resetMasking(masked: Array<{ element: HTMLElement; previous: string }>): void {\n masked.forEach(({ element, previous }) => {\n element.style.filter = previous;\n });\n}\n\nfunction scrubText(root: HTMLElement, patterns: Array<string | RegExp>): Array<{ node: Text; previous: string }> {\n if (!patterns.length) {\n return [];\n }\n\n const walkers: Array<{ node: Text; previous: string }> = [];\n const regexes = patterns.map((pattern) => (typeof pattern === \"string\" ? new RegExp(pattern, \"g\") : pattern));\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);\n while (walker.nextNode()) {\n const text = walker.currentNode as Text;\n let replaced = text.textContent ?? \"\";\n for (const regex of regexes) {\n replaced = replaced.replace(regex, \"[redacted]\");\n }\n if (replaced !== text.textContent) {\n walkers.push({ node: text, previous: text.textContent ?? \"\" });\n text.textContent = replaced;\n }\n }\n return walkers;\n}\n\nfunction restoreText(changed: Array<{ node: Text; previous: string }>): void {\n changed.forEach(({ node, previous }) => {\n node.textContent = previous;\n });\n}\n\nfunction createSelectionOverlay(): Promise<SelectionRect> {\n return new Promise((resolve, reject) => {\n const overlay = document.createElement(\"div\");\n overlay.setAttribute(\"data-bug-reporter-overlay\", \"true\");\n overlay.style.position = \"fixed\";\n overlay.style.inset = \"0\";\n overlay.style.background = \"rgba(0,0,0,0.35)\";\n overlay.style.cursor = \"crosshair\";\n overlay.style.zIndex = \"2147483647\";\n\n const box = document.createElement(\"div\");\n box.style.position = \"fixed\";\n box.style.border = \"2px solid #ffffff\";\n box.style.background = \"rgba(27, 116, 228, 0.2)\";\n box.style.pointerEvents = \"none\";\n box.style.display = \"none\";\n overlay.appendChild(box);\n\n const cleanup = () => {\n overlay.removeEventListener(\"mousedown\", onMouseDown);\n overlay.removeEventListener(\"mousemove\", onMouseMove);\n overlay.removeEventListener(\"mouseup\", onMouseUp);\n window.removeEventListener(\"keydown\", onKeyDown);\n overlay.remove();\n };\n\n let startX = 0;\n let startY = 0;\n let isDragging = false;\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n cleanup();\n reject(new BugReporterError(\"ABORTED\", \"Screenshot capture cancelled.\"));\n }\n };\n\n const onMouseDown = (event: MouseEvent) => {\n isDragging = true;\n startX = event.clientX;\n startY = event.clientY;\n box.style.display = \"block\";\n box.style.left = `${startX}px`;\n box.style.top = `${startY}px`;\n box.style.width = \"0px\";\n box.style.height = \"0px\";\n };\n\n const onMouseMove = (event: MouseEvent) => {\n if (!isDragging) {\n return;\n }\n const left = Math.min(startX, event.clientX);\n const top = Math.min(startY, event.clientY);\n const width = Math.abs(startX - event.clientX);\n const height = Math.abs(startY - event.clientY);\n box.style.left = `${left}px`;\n box.style.top = `${top}px`;\n box.style.width = `${width}px`;\n box.style.height = `${height}px`;\n };\n\n const onMouseUp = (event: MouseEvent) => {\n if (!isDragging) {\n return;\n }\n isDragging = false;\n const left = Math.min(startX, event.clientX);\n const top = Math.min(startY, event.clientY);\n const width = Math.abs(startX - event.clientX);\n const height = Math.abs(startY - event.clientY);\n cleanup();\n if (width < 8 || height < 8) {\n reject(new BugReporterError(\"CAPTURE_ERROR\", \"Selection area is too small.\"));\n return;\n }\n resolve({ left, top, width, height });\n };\n\n overlay.addEventListener(\"mousedown\", onMouseDown);\n overlay.addEventListener(\"mousemove\", onMouseMove);\n overlay.addEventListener(\"mouseup\", onMouseUp);\n window.addEventListener(\"keydown\", onKeyDown);\n document.body.appendChild(overlay);\n });\n}\n\nfunction canvasToBlob(canvas: HTMLCanvasElement): Promise<Blob> {\n return new Promise((resolve, reject) => {\n canvas.toBlob((blob) => {\n if (!blob) {\n reject(new BugReporterError(\"CAPTURE_ERROR\", \"Failed to build screenshot blob.\"));\n return;\n }\n resolve(blob);\n }, \"image/png\");\n });\n}\n\nexport async function captureScreenshotArea(options: CaptureOptions): Promise<Blob> {\n const selection = await createSelectionOverlay();\n const masked = applyMasking(options.maskSelectors);\n const textChanges = scrubText(document.body, options.redactTextPatterns);\n\n try {\n const { default: html2canvas } = await import(\"html2canvas\");\n const baseCanvas = await html2canvas(document.documentElement, {\n useCORS: true,\n scrollX: -window.scrollX,\n scrollY: -window.scrollY,\n backgroundColor: null,\n logging: false,\n windowWidth: document.documentElement.scrollWidth,\n windowHeight: document.documentElement.scrollHeight\n });\n\n const scaleX = baseCanvas.width / window.innerWidth;\n const scaleY = baseCanvas.height / window.innerHeight;\n\n const sx = Math.round(selection.left * scaleX);\n const sy = Math.round(selection.top * scaleY);\n const sw = Math.round(selection.width * scaleX);\n const sh = Math.round(selection.height * scaleY);\n\n const cropped = document.createElement(\"canvas\");\n cropped.width = sw;\n cropped.height = sh;\n\n const context = cropped.getContext(\"2d\");\n if (!context) {\n throw new BugReporterError(\"CAPTURE_ERROR\", \"Canvas 2D context unavailable.\");\n }\n\n context.drawImage(baseCanvas, sx, sy, sw, sh, 0, 0, sw, sh);\n return await canvasToBlob(cropped);\n } catch (error) {\n if (error instanceof BugReporterError) {\n throw error;\n }\n throw new BugReporterError(\"CAPTURE_ERROR\", \"Screenshot capture failed.\", error);\n } finally {\n resetMasking(masked);\n restoreText(textChanges);\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/recording.ts"],"names":["BugReporterError"],"mappings":"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","file":"recording-ML63ZQ6A.cjs","sourcesContent":["import { BugReporterError } from \"../types\";\n\nexport type RecordingResult = {\n blob: Blob;\n mimeType: string;\n durationMs: number;\n};\n\nexport type ActiveRecording = {\n stop: () => void;\n cancel: () => void;\n promise: Promise<RecordingResult>;\n};\n\ntype StartRecordingOptions = {\n maxSeconds: number;\n maxBytes: number;\n onTick?: (seconds: number) => void;\n};\n\nfunction pickMimeType(): string {\n const candidates = [\"video/webm;codecs=vp9\", \"video/webm;codecs=vp8\", \"video/webm\"];\n for (const candidate of candidates) {\n if (typeof MediaRecorder !== \"undefined\" && MediaRecorder.isTypeSupported(candidate)) {\n return candidate;\n }\n }\n return \"video/webm\";\n}\n\nexport async function startScreenRecording(options: StartRecordingOptions): Promise<ActiveRecording> {\n if (!navigator.mediaDevices?.getDisplayMedia) {\n throw new BugReporterError(\"RECORDING_ERROR\", \"Screen recording is not supported by this browser.\");\n }\n\n let stream: MediaStream;\n try {\n stream = await navigator.mediaDevices.getDisplayMedia({\n video: true,\n audio: false\n });\n } catch (error) {\n throw new BugReporterError(\"PERMISSION_DENIED\", \"Permission denied for screen recording.\", error);\n }\n\n const mimeType = pickMimeType();\n let recorder: MediaRecorder;\n try {\n recorder = new MediaRecorder(stream, { mimeType });\n } catch (error) {\n stream.getTracks().forEach((track) => track.stop());\n throw new BugReporterError(\"RECORDING_ERROR\", \"Could not initialize MediaRecorder.\", error);\n }\n\n const chunks: Blob[] = [];\n const startedAt = Date.now();\n let latestSize = 0;\n let tickSeconds = 0;\n let completed = false;\n let isCancelled = false;\n\n let resolvePromise: (value: RecordingResult) => void;\n let rejectPromise: (reason?: unknown) => void;\n\n const promise = new Promise<RecordingResult>((resolve, reject) => {\n resolvePromise = resolve;\n rejectPromise = reject;\n });\n\n const tickInterval = window.setInterval(() => {\n tickSeconds += 1;\n options.onTick?.(tickSeconds);\n }, 1000);\n\n const hardStop = window.setTimeout(() => {\n if (recorder.state !== \"inactive\") {\n recorder.stop();\n }\n }, options.maxSeconds * 1000);\n\n const teardown = () => {\n if (completed) {\n return;\n }\n completed = true;\n window.clearInterval(tickInterval);\n window.clearTimeout(hardStop);\n stream.getTracks().forEach((track) => track.stop());\n };\n\n recorder.addEventListener(\"dataavailable\", (event) => {\n if (!event.data || event.data.size === 0) {\n return;\n }\n chunks.push(event.data);\n latestSize += event.data.size;\n if (latestSize > options.maxBytes) {\n isCancelled = true;\n recorder.stop();\n rejectPromise(\n new BugReporterError(\n \"VALIDATION_ERROR\",\n `Recording exceeds max size (${Math.round(options.maxBytes / 1024 / 1024)}MB).`\n )\n );\n }\n });\n\n recorder.addEventListener(\"error\", (event) => {\n teardown();\n rejectPromise(new BugReporterError(\"RECORDING_ERROR\", \"Recording failed.\", event));\n });\n\n recorder.addEventListener(\"stop\", () => {\n teardown();\n if (isCancelled) {\n return;\n }\n const blob = new Blob(chunks, { type: mimeType });\n resolvePromise({\n blob,\n mimeType,\n durationMs: Date.now() - startedAt\n });\n });\n\n recorder.start(300);\n\n return {\n stop: () => {\n if (recorder.state !== \"inactive\") {\n recorder.stop();\n }\n },\n cancel: () => {\n isCancelled = true;\n if (recorder.state !== \"inactive\") {\n recorder.stop();\n }\n teardown();\n rejectPromise(new BugReporterError(\"ABORTED\", \"Recording cancelled by user.\"));\n },\n promise\n };\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/recording.ts"],"names":[],"mappings":"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","file":"recording-YSR6IORT.js","sourcesContent":["import { BugReporterError } from \"../types\";\n\nexport type RecordingResult = {\n blob: Blob;\n mimeType: string;\n durationMs: number;\n};\n\nexport type ActiveRecording = {\n stop: () => void;\n cancel: () => void;\n promise: Promise<RecordingResult>;\n};\n\ntype StartRecordingOptions = {\n maxSeconds: number;\n maxBytes: number;\n onTick?: (seconds: number) => void;\n};\n\nfunction pickMimeType(): string {\n const candidates = [\"video/webm;codecs=vp9\", \"video/webm;codecs=vp8\", \"video/webm\"];\n for (const candidate of candidates) {\n if (typeof MediaRecorder !== \"undefined\" && MediaRecorder.isTypeSupported(candidate)) {\n return candidate;\n }\n }\n return \"video/webm\";\n}\n\nexport async function startScreenRecording(options: StartRecordingOptions): Promise<ActiveRecording> {\n if (!navigator.mediaDevices?.getDisplayMedia) {\n throw new BugReporterError(\"RECORDING_ERROR\", \"Screen recording is not supported by this browser.\");\n }\n\n let stream: MediaStream;\n try {\n stream = await navigator.mediaDevices.getDisplayMedia({\n video: true,\n audio: false\n });\n } catch (error) {\n throw new BugReporterError(\"PERMISSION_DENIED\", \"Permission denied for screen recording.\", error);\n }\n\n const mimeType = pickMimeType();\n let recorder: MediaRecorder;\n try {\n recorder = new MediaRecorder(stream, { mimeType });\n } catch (error) {\n stream.getTracks().forEach((track) => track.stop());\n throw new BugReporterError(\"RECORDING_ERROR\", \"Could not initialize MediaRecorder.\", error);\n }\n\n const chunks: Blob[] = [];\n const startedAt = Date.now();\n let latestSize = 0;\n let tickSeconds = 0;\n let completed = false;\n let isCancelled = false;\n\n let resolvePromise: (value: RecordingResult) => void;\n let rejectPromise: (reason?: unknown) => void;\n\n const promise = new Promise<RecordingResult>((resolve, reject) => {\n resolvePromise = resolve;\n rejectPromise = reject;\n });\n\n const tickInterval = window.setInterval(() => {\n tickSeconds += 1;\n options.onTick?.(tickSeconds);\n }, 1000);\n\n const hardStop = window.setTimeout(() => {\n if (recorder.state !== \"inactive\") {\n recorder.stop();\n }\n }, options.maxSeconds * 1000);\n\n const teardown = () => {\n if (completed) {\n return;\n }\n completed = true;\n window.clearInterval(tickInterval);\n window.clearTimeout(hardStop);\n stream.getTracks().forEach((track) => track.stop());\n };\n\n recorder.addEventListener(\"dataavailable\", (event) => {\n if (!event.data || event.data.size === 0) {\n return;\n }\n chunks.push(event.data);\n latestSize += event.data.size;\n if (latestSize > options.maxBytes) {\n isCancelled = true;\n recorder.stop();\n rejectPromise(\n new BugReporterError(\n \"VALIDATION_ERROR\",\n `Recording exceeds max size (${Math.round(options.maxBytes / 1024 / 1024)}MB).`\n )\n );\n }\n });\n\n recorder.addEventListener(\"error\", (event) => {\n teardown();\n rejectPromise(new BugReporterError(\"RECORDING_ERROR\", \"Recording failed.\", event));\n });\n\n recorder.addEventListener(\"stop\", () => {\n teardown();\n if (isCancelled) {\n return;\n }\n const blob = new Blob(chunks, { type: mimeType });\n resolvePromise({\n blob,\n mimeType,\n durationMs: Date.now() - startedAt\n });\n });\n\n recorder.start(300);\n\n return {\n stop: () => {\n if (recorder.state !== \"inactive\") {\n recorder.stop();\n }\n },\n cancel: () => {\n isCancelled = true;\n if (recorder.state !== \"inactive\") {\n recorder.stop();\n }\n teardown();\n rejectPromise(new BugReporterError(\"ABORTED\", \"Recording cancelled by user.\"));\n },\n promise\n };\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/screenshot.ts"],"names":[],"mappings":"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","file":"screenshot-F4W72WRK.js","sourcesContent":["import { BugReporterError } from \"../types\";\n\ntype CaptureOptions = {\n maskSelectors: string[];\n redactTextPatterns: Array<string | RegExp>;\n};\n\ntype SelectionRect = {\n left: number;\n top: number;\n width: number;\n height: number;\n};\n\nfunction applyMasking(selectors: string[]): Array<{ element: HTMLElement; previous: string }> {\n const masked: Array<{ element: HTMLElement; previous: string }> = [];\n for (const selector of selectors) {\n document.querySelectorAll<HTMLElement>(selector).forEach((element) => {\n masked.push({ element, previous: element.style.filter });\n element.style.filter = \"blur(12px)\";\n });\n }\n return masked;\n}\n\nfunction resetMasking(masked: Array<{ element: HTMLElement; previous: string }>): void {\n masked.forEach(({ element, previous }) => {\n element.style.filter = previous;\n });\n}\n\nfunction scrubText(root: HTMLElement, patterns: Array<string | RegExp>): Array<{ node: Text; previous: string }> {\n if (!patterns.length) {\n return [];\n }\n\n const walkers: Array<{ node: Text; previous: string }> = [];\n const regexes = patterns.map((pattern) => (typeof pattern === \"string\" ? new RegExp(pattern, \"g\") : pattern));\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);\n while (walker.nextNode()) {\n const text = walker.currentNode as Text;\n let replaced = text.textContent ?? \"\";\n for (const regex of regexes) {\n replaced = replaced.replace(regex, \"[redacted]\");\n }\n if (replaced !== text.textContent) {\n walkers.push({ node: text, previous: text.textContent ?? \"\" });\n text.textContent = replaced;\n }\n }\n return walkers;\n}\n\nfunction restoreText(changed: Array<{ node: Text; previous: string }>): void {\n changed.forEach(({ node, previous }) => {\n node.textContent = previous;\n });\n}\n\nfunction createSelectionOverlay(): Promise<SelectionRect> {\n return new Promise((resolve, reject) => {\n const overlay = document.createElement(\"div\");\n overlay.setAttribute(\"data-bug-reporter-overlay\", \"true\");\n overlay.style.position = \"fixed\";\n overlay.style.inset = \"0\";\n overlay.style.background = \"rgba(0,0,0,0.35)\";\n overlay.style.cursor = \"crosshair\";\n overlay.style.zIndex = \"2147483647\";\n\n const box = document.createElement(\"div\");\n box.style.position = \"fixed\";\n box.style.border = \"2px solid #ffffff\";\n box.style.background = \"rgba(27, 116, 228, 0.2)\";\n box.style.pointerEvents = \"none\";\n box.style.display = \"none\";\n overlay.appendChild(box);\n\n const cleanup = () => {\n overlay.removeEventListener(\"mousedown\", onMouseDown);\n overlay.removeEventListener(\"mousemove\", onMouseMove);\n overlay.removeEventListener(\"mouseup\", onMouseUp);\n window.removeEventListener(\"keydown\", onKeyDown);\n overlay.remove();\n };\n\n let startX = 0;\n let startY = 0;\n let isDragging = false;\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n cleanup();\n reject(new BugReporterError(\"ABORTED\", \"Screenshot capture cancelled.\"));\n }\n };\n\n const onMouseDown = (event: MouseEvent) => {\n isDragging = true;\n startX = event.clientX;\n startY = event.clientY;\n box.style.display = \"block\";\n box.style.left = `${startX}px`;\n box.style.top = `${startY}px`;\n box.style.width = \"0px\";\n box.style.height = \"0px\";\n };\n\n const onMouseMove = (event: MouseEvent) => {\n if (!isDragging) {\n return;\n }\n const left = Math.min(startX, event.clientX);\n const top = Math.min(startY, event.clientY);\n const width = Math.abs(startX - event.clientX);\n const height = Math.abs(startY - event.clientY);\n box.style.left = `${left}px`;\n box.style.top = `${top}px`;\n box.style.width = `${width}px`;\n box.style.height = `${height}px`;\n };\n\n const onMouseUp = (event: MouseEvent) => {\n if (!isDragging) {\n return;\n }\n isDragging = false;\n const left = Math.min(startX, event.clientX);\n const top = Math.min(startY, event.clientY);\n const width = Math.abs(startX - event.clientX);\n const height = Math.abs(startY - event.clientY);\n cleanup();\n if (width < 8 || height < 8) {\n reject(new BugReporterError(\"CAPTURE_ERROR\", \"Selection area is too small.\"));\n return;\n }\n resolve({ left, top, width, height });\n };\n\n overlay.addEventListener(\"mousedown\", onMouseDown);\n overlay.addEventListener(\"mousemove\", onMouseMove);\n overlay.addEventListener(\"mouseup\", onMouseUp);\n window.addEventListener(\"keydown\", onKeyDown);\n document.body.appendChild(overlay);\n });\n}\n\nfunction canvasToBlob(canvas: HTMLCanvasElement): Promise<Blob> {\n return new Promise((resolve, reject) => {\n canvas.toBlob((blob) => {\n if (!blob) {\n reject(new BugReporterError(\"CAPTURE_ERROR\", \"Failed to build screenshot blob.\"));\n return;\n }\n resolve(blob);\n }, \"image/png\");\n });\n}\n\nexport async function captureScreenshotArea(options: CaptureOptions): Promise<Blob> {\n const selection = await createSelectionOverlay();\n const masked = applyMasking(options.maskSelectors);\n const textChanges = scrubText(document.body, options.redactTextPatterns);\n\n try {\n const { default: html2canvas } = await import(\"html2canvas\");\n const baseCanvas = await html2canvas(document.documentElement, {\n useCORS: true,\n scrollX: -window.scrollX,\n scrollY: -window.scrollY,\n backgroundColor: null,\n logging: false,\n windowWidth: document.documentElement.scrollWidth,\n windowHeight: document.documentElement.scrollHeight\n });\n\n const scaleX = baseCanvas.width / window.innerWidth;\n const scaleY = baseCanvas.height / window.innerHeight;\n\n const sx = Math.round(selection.left * scaleX);\n const sy = Math.round(selection.top * scaleY);\n const sw = Math.round(selection.width * scaleX);\n const sh = Math.round(selection.height * scaleY);\n\n const cropped = document.createElement(\"canvas\");\n cropped.width = sw;\n cropped.height = sh;\n\n const context = cropped.getContext(\"2d\");\n if (!context) {\n throw new BugReporterError(\"CAPTURE_ERROR\", \"Canvas 2D context unavailable.\");\n }\n\n context.drawImage(baseCanvas, sx, sy, sw, sh, 0, 0, sw, sh);\n return await canvasToBlob(cropped);\n } catch (error) {\n if (error instanceof BugReporterError) {\n throw error;\n }\n throw new BugReporterError(\"CAPTURE_ERROR\", \"Screenshot capture failed.\", error);\n } finally {\n resetMasking(masked);\n restoreText(textChanges);\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/screenshot.ts"],"names":["BugReporterError"],"mappings":"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","file":"screenshot-FRAZAS6B.cjs","sourcesContent":["import { BugReporterError } from \"../types\";\n\ntype CaptureOptions = {\n maskSelectors: string[];\n redactTextPatterns: Array<string | RegExp>;\n};\n\ntype SelectionRect = {\n left: number;\n top: number;\n width: number;\n height: number;\n};\n\nfunction applyMasking(selectors: string[]): Array<{ element: HTMLElement; previous: string }> {\n const masked: Array<{ element: HTMLElement; previous: string }> = [];\n for (const selector of selectors) {\n document.querySelectorAll<HTMLElement>(selector).forEach((element) => {\n masked.push({ element, previous: element.style.filter });\n element.style.filter = \"blur(12px)\";\n });\n }\n return masked;\n}\n\nfunction resetMasking(masked: Array<{ element: HTMLElement; previous: string }>): void {\n masked.forEach(({ element, previous }) => {\n element.style.filter = previous;\n });\n}\n\nfunction scrubText(root: HTMLElement, patterns: Array<string | RegExp>): Array<{ node: Text; previous: string }> {\n if (!patterns.length) {\n return [];\n }\n\n const walkers: Array<{ node: Text; previous: string }> = [];\n const regexes = patterns.map((pattern) => (typeof pattern === \"string\" ? new RegExp(pattern, \"g\") : pattern));\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);\n while (walker.nextNode()) {\n const text = walker.currentNode as Text;\n let replaced = text.textContent ?? \"\";\n for (const regex of regexes) {\n replaced = replaced.replace(regex, \"[redacted]\");\n }\n if (replaced !== text.textContent) {\n walkers.push({ node: text, previous: text.textContent ?? \"\" });\n text.textContent = replaced;\n }\n }\n return walkers;\n}\n\nfunction restoreText(changed: Array<{ node: Text; previous: string }>): void {\n changed.forEach(({ node, previous }) => {\n node.textContent = previous;\n });\n}\n\nfunction createSelectionOverlay(): Promise<SelectionRect> {\n return new Promise((resolve, reject) => {\n const overlay = document.createElement(\"div\");\n overlay.setAttribute(\"data-bug-reporter-overlay\", \"true\");\n overlay.style.position = \"fixed\";\n overlay.style.inset = \"0\";\n overlay.style.background = \"rgba(0,0,0,0.35)\";\n overlay.style.cursor = \"crosshair\";\n overlay.style.zIndex = \"2147483647\";\n\n const box = document.createElement(\"div\");\n box.style.position = \"fixed\";\n box.style.border = \"2px solid #ffffff\";\n box.style.background = \"rgba(27, 116, 228, 0.2)\";\n box.style.pointerEvents = \"none\";\n box.style.display = \"none\";\n overlay.appendChild(box);\n\n const cleanup = () => {\n overlay.removeEventListener(\"mousedown\", onMouseDown);\n overlay.removeEventListener(\"mousemove\", onMouseMove);\n overlay.removeEventListener(\"mouseup\", onMouseUp);\n window.removeEventListener(\"keydown\", onKeyDown);\n overlay.remove();\n };\n\n let startX = 0;\n let startY = 0;\n let isDragging = false;\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n cleanup();\n reject(new BugReporterError(\"ABORTED\", \"Screenshot capture cancelled.\"));\n }\n };\n\n const onMouseDown = (event: MouseEvent) => {\n isDragging = true;\n startX = event.clientX;\n startY = event.clientY;\n box.style.display = \"block\";\n box.style.left = `${startX}px`;\n box.style.top = `${startY}px`;\n box.style.width = \"0px\";\n box.style.height = \"0px\";\n };\n\n const onMouseMove = (event: MouseEvent) => {\n if (!isDragging) {\n return;\n }\n const left = Math.min(startX, event.clientX);\n const top = Math.min(startY, event.clientY);\n const width = Math.abs(startX - event.clientX);\n const height = Math.abs(startY - event.clientY);\n box.style.left = `${left}px`;\n box.style.top = `${top}px`;\n box.style.width = `${width}px`;\n box.style.height = `${height}px`;\n };\n\n const onMouseUp = (event: MouseEvent) => {\n if (!isDragging) {\n return;\n }\n isDragging = false;\n const left = Math.min(startX, event.clientX);\n const top = Math.min(startY, event.clientY);\n const width = Math.abs(startX - event.clientX);\n const height = Math.abs(startY - event.clientY);\n cleanup();\n if (width < 8 || height < 8) {\n reject(new BugReporterError(\"CAPTURE_ERROR\", \"Selection area is too small.\"));\n return;\n }\n resolve({ left, top, width, height });\n };\n\n overlay.addEventListener(\"mousedown\", onMouseDown);\n overlay.addEventListener(\"mousemove\", onMouseMove);\n overlay.addEventListener(\"mouseup\", onMouseUp);\n window.addEventListener(\"keydown\", onKeyDown);\n document.body.appendChild(overlay);\n });\n}\n\nfunction canvasToBlob(canvas: HTMLCanvasElement): Promise<Blob> {\n return new Promise((resolve, reject) => {\n canvas.toBlob((blob) => {\n if (!blob) {\n reject(new BugReporterError(\"CAPTURE_ERROR\", \"Failed to build screenshot blob.\"));\n return;\n }\n resolve(blob);\n }, \"image/png\");\n });\n}\n\nexport async function captureScreenshotArea(options: CaptureOptions): Promise<Blob> {\n const selection = await createSelectionOverlay();\n const masked = applyMasking(options.maskSelectors);\n const textChanges = scrubText(document.body, options.redactTextPatterns);\n\n try {\n const { default: html2canvas } = await import(\"html2canvas\");\n const baseCanvas = await html2canvas(document.documentElement, {\n useCORS: true,\n scrollX: -window.scrollX,\n scrollY: -window.scrollY,\n backgroundColor: null,\n logging: false,\n windowWidth: document.documentElement.scrollWidth,\n windowHeight: document.documentElement.scrollHeight\n });\n\n const scaleX = baseCanvas.width / window.innerWidth;\n const scaleY = baseCanvas.height / window.innerHeight;\n\n const sx = Math.round(selection.left * scaleX);\n const sy = Math.round(selection.top * scaleY);\n const sw = Math.round(selection.width * scaleX);\n const sh = Math.round(selection.height * scaleY);\n\n const cropped = document.createElement(\"canvas\");\n cropped.width = sw;\n cropped.height = sh;\n\n const context = cropped.getContext(\"2d\");\n if (!context) {\n throw new BugReporterError(\"CAPTURE_ERROR\", \"Canvas 2D context unavailable.\");\n }\n\n context.drawImage(baseCanvas, sx, sy, sw, sh, 0, 0, sw, sh);\n return await canvasToBlob(cropped);\n } catch (error) {\n if (error instanceof BugReporterError) {\n throw error;\n }\n throw new BugReporterError(\"CAPTURE_ERROR\", \"Screenshot capture failed.\", error);\n } finally {\n resetMasking(masked);\n restoreText(textChanges);\n }\n}\n"]}
|