glitchgrab 1.19.2 → 1.21.0

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.js CHANGED
@@ -40,6 +40,7 @@ __export(index_exports, {
40
40
  clearBreadcrumbs: () => clearBreadcrumbs,
41
41
  clearDedupCache: () => clearDedupCache,
42
42
  computeSignature: () => computeSignature,
43
+ enhanceText: () => enhanceText,
43
44
  fetchGlitchgrabReports: () => fetchGlitchgrabReports,
44
45
  getBreadcrumbs: () => getBreadcrumbs,
45
46
  initBreadcrumbs: () => initBreadcrumbs,
@@ -136,7 +137,10 @@ function interceptFetch() {
136
137
  const method = (_a = init == null ? void 0 : init.method) != null ? _a : "GET";
137
138
  const start = Date.now();
138
139
  try {
139
- const response = await origFetch.apply(window, [input, init]);
140
+ const response = await origFetch(
141
+ input,
142
+ init
143
+ );
140
144
  addBreadcrumb("api", `${method} ${url.slice(0, 100)} \u2192 ${response.status}`, {
141
145
  method,
142
146
  status: String(response.status),
@@ -315,6 +319,30 @@ async function sendReport(payload, baseUrl) {
315
319
  return null;
316
320
  }
317
321
  }
322
+ async function enhanceText(text, token, baseUrl) {
323
+ var _a;
324
+ try {
325
+ const trimmed = text.trim();
326
+ if (!trimmed) return text;
327
+ const url = `${baseUrl != null ? baseUrl : DEFAULT_BASE_URL}/api/v1/ai/enhance-text`;
328
+ const response = await fetch(url, {
329
+ method: "POST",
330
+ headers: {
331
+ "Content-Type": "application/json",
332
+ Authorization: `Bearer ${token}`
333
+ },
334
+ body: JSON.stringify({ text: trimmed })
335
+ });
336
+ if (!response.ok) return text;
337
+ const envelope = await response.json();
338
+ if ((envelope == null ? void 0 : envelope.success) && typeof ((_a = envelope.data) == null ? void 0 : _a.text) === "string") {
339
+ return envelope.data.text;
340
+ }
341
+ return text;
342
+ } catch (e) {
343
+ return text;
344
+ }
345
+ }
318
346
 
319
347
  // src/dedup.ts
320
348
  var DEFAULT_WINDOW_MS = 5 * 60 * 1e3;
@@ -586,9 +614,12 @@ function isLowQualityText(text) {
586
614
  }
587
615
  function ReportDialog({
588
616
  report,
617
+ enhanceText: enhanceText2,
589
618
  types,
590
619
  showSeverity = true
591
620
  }) {
621
+ const [isEnhancing, setIsEnhancing] = (0, import_react.useState)(false);
622
+ const [screenshotDragOver, setScreenshotDragOver] = (0, import_react.useState)(false);
592
623
  const [mounted, setMounted] = (0, import_react.useState)(false);
593
624
  (0, import_react.useEffect)(() => {
594
625
  setMounted(true);
@@ -930,38 +961,221 @@ function ReportDialog({
930
961
  type
931
962
  )) }),
932
963
  step === 2 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
933
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
934
- "textarea",
935
- {
936
- value: description,
937
- onChange: (e) => {
938
- setDescription(e.target.value);
939
- if (validationError) setValidationError(null);
940
- },
941
- placeholder: getPlaceholder(reportType),
942
- style: {
943
- width: "100%",
944
- minHeight: "100px",
945
- padding: "10px 12px",
946
- borderRadius: "8px",
947
- border: `1px solid ${t.inputBorder}`,
948
- fontSize: "14px",
949
- fontFamily: "inherit",
950
- resize: "vertical",
951
- outline: "none",
952
- boxSizing: "border-box",
953
- color: t.text,
954
- backgroundColor: t.inputBg
955
- },
956
- onFocus: (e) => {
957
- e.target.style.borderColor = t.accent;
958
- },
959
- onBlur: (e) => {
960
- e.target.style.borderColor = t.inputBorder;
961
- },
962
- autoFocus: true
963
- }
964
- ),
964
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { position: "relative" }, children: [
965
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
966
+ "textarea",
967
+ {
968
+ value: description,
969
+ onChange: (e) => {
970
+ setDescription(e.target.value);
971
+ if (validationError) setValidationError(null);
972
+ },
973
+ placeholder: getPlaceholder(reportType),
974
+ style: {
975
+ width: "100%",
976
+ minHeight: "100px",
977
+ padding: enhanceText2 ? "28px 12px 10px" : "10px 12px",
978
+ borderRadius: "8px",
979
+ border: `1px solid ${t.inputBorder}`,
980
+ fontSize: "14px",
981
+ fontFamily: "inherit",
982
+ resize: "vertical",
983
+ outline: "none",
984
+ boxSizing: "border-box",
985
+ color: t.text,
986
+ backgroundColor: t.inputBg
987
+ },
988
+ onFocus: (e) => {
989
+ e.target.style.borderColor = t.accent;
990
+ },
991
+ onBlur: (e) => {
992
+ e.target.style.borderColor = t.inputBorder;
993
+ },
994
+ autoFocus: true
995
+ }
996
+ ),
997
+ enhanceText2 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
998
+ "button",
999
+ {
1000
+ type: "button",
1001
+ onClick: async () => {
1002
+ if (!description.trim() || isEnhancing) return;
1003
+ setIsEnhancing(true);
1004
+ try {
1005
+ const polished = await enhanceText2(description);
1006
+ if (polished && polished !== description) {
1007
+ setDescription(polished);
1008
+ if (validationError) setValidationError(null);
1009
+ }
1010
+ } finally {
1011
+ setIsEnhancing(false);
1012
+ }
1013
+ },
1014
+ disabled: !description.trim() || isEnhancing,
1015
+ style: {
1016
+ position: "absolute",
1017
+ top: "6px",
1018
+ right: "6px",
1019
+ display: "inline-flex",
1020
+ alignItems: "center",
1021
+ gap: "4px",
1022
+ background: t.inputBg,
1023
+ border: "none",
1024
+ padding: "2px 6px",
1025
+ borderRadius: "4px",
1026
+ fontFamily: "inherit",
1027
+ fontSize: "11px",
1028
+ color: t.textMuted,
1029
+ cursor: !description.trim() || isEnhancing ? "default" : "pointer",
1030
+ opacity: !description.trim() ? 0.5 : 1,
1031
+ zIndex: 1
1032
+ },
1033
+ title: "Polish grammar \u2014 preserves your meaning",
1034
+ children: [
1035
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3zM19 15l.75 2.25L22 18l-2.25.75L19 21l-.75-2.25L16 18l2.25-.75L19 15z", stroke: t.textMuted, strokeWidth: "1.5", strokeLinejoin: "round" }) }),
1036
+ isEnhancing ? "Enhancing..." : "AI enhance"
1037
+ ]
1038
+ }
1039
+ )
1040
+ ] }),
1041
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: "10px" }, children: [
1042
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: "12px", color: t.textMuted, marginBottom: "6px", display: "block", fontWeight: 500 }, children: "Screenshot" }),
1043
+ screenshot ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
1044
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { position: "relative" }, children: [
1045
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1046
+ "img",
1047
+ {
1048
+ src: screenshot,
1049
+ alt: "Page screenshot",
1050
+ onClick: () => setPreviewOpen(true),
1051
+ style: {
1052
+ width: "100%",
1053
+ borderRadius: "6px",
1054
+ border: `1px solid ${t.border}`,
1055
+ maxHeight: "64px",
1056
+ objectFit: "cover",
1057
+ objectPosition: "top",
1058
+ cursor: "zoom-in",
1059
+ display: "block"
1060
+ }
1061
+ }
1062
+ ),
1063
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: {
1064
+ position: "absolute",
1065
+ bottom: "5px",
1066
+ left: "6px",
1067
+ background: "rgba(0,0,0,0.55)",
1068
+ color: "#fff",
1069
+ fontSize: "10px",
1070
+ padding: "1px 5px",
1071
+ borderRadius: "3px",
1072
+ pointerEvents: "none"
1073
+ }, children: "click to preview" })
1074
+ ] }),
1075
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: "6px", marginTop: "6px" }, children: [
1076
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1077
+ "button",
1078
+ {
1079
+ type: "button",
1080
+ onClick: () => setScreenshot(null),
1081
+ style: {
1082
+ flex: 1,
1083
+ padding: "6px 0",
1084
+ borderRadius: "6px",
1085
+ border: `1px solid ${t.inputBorder}`,
1086
+ background: "transparent",
1087
+ color: "#ef4444",
1088
+ fontSize: "12px",
1089
+ fontWeight: 500,
1090
+ cursor: "pointer",
1091
+ fontFamily: "inherit",
1092
+ display: "flex",
1093
+ alignItems: "center",
1094
+ justifyContent: "center",
1095
+ gap: "4px"
1096
+ },
1097
+ children: [
1098
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "11", height: "11", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M1 1L9 9M9 1L1 9", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) }),
1099
+ "Remove"
1100
+ ]
1101
+ }
1102
+ ),
1103
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1104
+ "button",
1105
+ {
1106
+ type: "button",
1107
+ onClick: () => {
1108
+ var _a;
1109
+ return (_a = fileInputRef.current) == null ? void 0 : _a.click();
1110
+ },
1111
+ style: {
1112
+ flex: 1,
1113
+ padding: "6px 0",
1114
+ borderRadius: "6px",
1115
+ border: `1px solid ${t.inputBorder}`,
1116
+ background: "transparent",
1117
+ color: t.textMuted,
1118
+ fontSize: "12px",
1119
+ fontWeight: 500,
1120
+ cursor: "pointer",
1121
+ fontFamily: "inherit",
1122
+ display: "flex",
1123
+ alignItems: "center",
1124
+ justifyContent: "center",
1125
+ gap: "4px"
1126
+ },
1127
+ children: [
1128
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M17 8l-5-5-5 5M12 3v12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
1129
+ "Replace"
1130
+ ]
1131
+ }
1132
+ )
1133
+ ] })
1134
+ ] }) : (
1135
+ /* Drop zone */
1136
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1137
+ "div",
1138
+ {
1139
+ onClick: () => {
1140
+ var _a;
1141
+ return (_a = fileInputRef.current) == null ? void 0 : _a.click();
1142
+ },
1143
+ onDrop: (e) => {
1144
+ e.preventDefault();
1145
+ setScreenshotDragOver(false);
1146
+ const file = Array.from(e.dataTransfer.files).find((f) => f.type.startsWith("image/"));
1147
+ if (!file) return;
1148
+ const reader = new FileReader();
1149
+ reader.onload = () => setScreenshot(reader.result);
1150
+ reader.readAsDataURL(file);
1151
+ },
1152
+ onDragOver: (e) => {
1153
+ e.preventDefault();
1154
+ setScreenshotDragOver(true);
1155
+ },
1156
+ onDragLeave: () => setScreenshotDragOver(false),
1157
+ style: {
1158
+ border: `1.5px dashed ${screenshotDragOver ? t.accent : t.inputBorder}`,
1159
+ borderRadius: "8px",
1160
+ padding: "18px 12px",
1161
+ textAlign: "center",
1162
+ cursor: "pointer",
1163
+ background: screenshotDragOver ? isDark ? "rgba(34,211,238,0.06)" : "rgba(8,145,178,0.04)" : "transparent",
1164
+ transition: "border-color 0.15s ease, background 0.15s ease"
1165
+ },
1166
+ children: [
1167
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", style: { margin: "0 auto 6px", display: "block", opacity: 0.45 }, children: [
1168
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", stroke: t.textMuted, strokeWidth: "1.5" }),
1169
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "8.5", cy: "8.5", r: "1.5", stroke: t.textMuted, strokeWidth: "1.5" }),
1170
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M21 15l-5-5L5 21", stroke: t.textMuted, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
1171
+ ] }),
1172
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { margin: 0, fontSize: "12px", fontWeight: 600, color: t.text }, children: screenshotDragOver ? "Drop to attach" : "Add a screenshot" }),
1173
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { margin: "3px 0 0", fontSize: "11px", color: t.textMuted }, children: "Drag & drop \xB7 Paste \u2318V / Ctrl+V \xB7 Click to browse" })
1174
+ ]
1175
+ }
1176
+ )
1177
+ )
1178
+ ] }),
965
1179
  showSeverity && reportType === "BUG" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: "10px" }, children: [
966
1180
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: "12px", color: t.textMuted, marginBottom: "6px", display: "block" }, children: "Severity" }),
967
1181
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", gap: "6px" }, children: ["low", "medium", "high"].map((s) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -1063,91 +1277,23 @@ function ReportDialog({
1063
1277
  overflow: "hidden",
1064
1278
  lineHeight: "1.4"
1065
1279
  }, children: description.length > 200 ? description.slice(0, 200) + "..." : description }),
1066
- screenshot && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginBottom: "10px", position: "relative" }, children: [
1067
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1068
- "img",
1069
- {
1070
- src: screenshot,
1071
- alt: "Page screenshot",
1072
- onClick: () => setPreviewOpen(true),
1073
- style: {
1074
- width: "100%",
1075
- borderRadius: "6px",
1076
- border: `1px solid ${t.border}`,
1077
- maxHeight: "80px",
1078
- objectFit: "cover",
1079
- objectPosition: "top",
1080
- cursor: "pointer"
1081
- }
1082
- }
1083
- ),
1084
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1085
- "button",
1086
- {
1087
- type: "button",
1088
- onClick: () => setScreenshot(null),
1089
- style: {
1090
- position: "absolute",
1091
- top: "4px",
1092
- right: "4px",
1093
- background: "rgba(0,0,0,0.6)",
1094
- border: "none",
1095
- borderRadius: "50%",
1096
- width: "20px",
1097
- height: "20px",
1098
- cursor: "pointer",
1099
- display: "flex",
1100
- alignItems: "center",
1101
- justifyContent: "center"
1102
- },
1103
- "aria-label": "Remove screenshot",
1104
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M1 1L9 9M9 1L1 9", stroke: "#fff", strokeWidth: "1.5", strokeLinecap: "round" }) })
1105
- }
1106
- )
1107
- ] }),
1108
- !screenshot && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: "6px", marginBottom: "10px" }, children: [
1109
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1110
- "button",
1111
- {
1112
- type: "button",
1113
- onClick: () => {
1114
- var _a;
1115
- return (_a = fileInputRef.current) == null ? void 0 : _a.click();
1116
- },
1117
- style: {
1118
- flex: 1,
1119
- padding: "8px",
1120
- borderRadius: "6px",
1121
- border: `1px dashed ${t.inputBorder}`,
1122
- textAlign: "center",
1123
- fontSize: "11px",
1124
- color: t.textMuted,
1125
- background: "none",
1126
- cursor: "pointer"
1127
- },
1128
- children: "Upload or paste (\u2318V)"
1129
- }
1130
- ),
1131
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1132
- "button",
1133
- {
1134
- type: "button",
1135
- onClick: retakeScreenshot,
1136
- style: {
1137
- flex: 1,
1138
- padding: "8px",
1139
- borderRadius: "6px",
1140
- border: `1px dashed ${t.inputBorder}`,
1141
- textAlign: "center",
1142
- fontSize: "11px",
1143
- color: t.textMuted,
1144
- background: "none",
1145
- cursor: "pointer"
1146
- },
1147
- children: "Retake screenshot"
1280
+ screenshot && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { marginBottom: "10px", position: "relative" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1281
+ "img",
1282
+ {
1283
+ src: screenshot,
1284
+ alt: "Page screenshot",
1285
+ onClick: () => setPreviewOpen(true),
1286
+ style: {
1287
+ width: "100%",
1288
+ borderRadius: "6px",
1289
+ border: `1px solid ${t.border}`,
1290
+ maxHeight: "80px",
1291
+ objectFit: "cover",
1292
+ objectPosition: "top",
1293
+ cursor: "pointer"
1148
1294
  }
1149
- )
1150
- ] }),
1295
+ }
1296
+ ) }),
1151
1297
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1152
1298
  "button",
1153
1299
  {
@@ -1379,14 +1525,25 @@ function GlitchgrabProviderInner({
1379
1525
  try {
1380
1526
  if (typeof window === "undefined") return;
1381
1527
  if (process.env.NODE_ENV === "development") return;
1528
+ const EXTENSION_ORIGIN_RE = /\b(?:chrome|safari|moz)-extension:\/\//;
1382
1529
  const handleError = (event) => {
1383
- var _a, _b, _c, _d, _e, _f;
1530
+ var _a, _b, _c, _d, _e, _f, _g;
1384
1531
  try {
1532
+ const isOpaqueCrossOrigin = event.message === "Script error." || event.message === "Script error" || !event.error && !event.filename;
1533
+ if (isOpaqueCrossOrigin) {
1534
+ return;
1535
+ }
1536
+ if (event.message === "ResizeObserver loop completed with undelivered notifications." || event.message === "ResizeObserver loop limit exceeded") {
1537
+ return;
1538
+ }
1539
+ if (event.filename && EXTENSION_ORIGIN_RE.test(event.filename) || ((_a = event.error) == null ? void 0 : _a.stack) && EXTENSION_ORIGIN_RE.test(event.error.stack)) {
1540
+ return;
1541
+ }
1385
1542
  const context = captureContext(visitedPagesRef.current);
1386
1543
  const sig = computeSignature({
1387
1544
  errorMessage: event.message,
1388
1545
  pageUrl: context.url,
1389
- errorStack: (_a = event.error) == null ? void 0 : _a.stack
1546
+ errorStack: (_b = event.error) == null ? void 0 : _b.stack
1390
1547
  });
1391
1548
  if (shouldSkipDuplicate(sig)) return;
1392
1549
  const payload = {
@@ -1394,17 +1551,17 @@ function GlitchgrabProviderInner({
1394
1551
  source: "SDK_AUTO",
1395
1552
  type: "BUG",
1396
1553
  errorMessage: event.message,
1397
- errorStack: (_b = event.error) == null ? void 0 : _b.stack,
1554
+ errorStack: (_c = event.error) == null ? void 0 : _c.stack,
1398
1555
  pageUrl: context.url,
1399
1556
  userAgent: context.userAgent,
1400
1557
  breadcrumbs: context.breadcrumbs,
1401
- deviceInfo: (_c = context.deviceInfo) != null ? _c : void 0,
1558
+ deviceInfo: (_d = context.deviceInfo) != null ? _d : void 0,
1402
1559
  metadata: {
1403
1560
  timestamp: context.timestamp,
1404
1561
  visitedPages: JSON.stringify(context.visitedPages),
1405
- filename: (_d = event.filename) != null ? _d : "",
1406
- lineno: String((_e = event.lineno) != null ? _e : ""),
1407
- colno: String((_f = event.colno) != null ? _f : ""),
1562
+ filename: (_e = event.filename) != null ? _e : "",
1563
+ lineno: String((_f = event.lineno) != null ? _f : ""),
1564
+ colno: String((_g = event.colno) != null ? _g : ""),
1408
1565
  ...(session == null ? void 0 : session.userId) ? { sessionUserId: session.userId } : {},
1409
1566
  ...(session == null ? void 0 : session.name) ? { sessionUserName: String(session.name) } : {},
1410
1567
  ...(session == null ? void 0 : session.email) ? { sessionUserEmail: String(session.email) } : {},
@@ -1424,7 +1581,11 @@ function GlitchgrabProviderInner({
1424
1581
  const context = captureContext(visitedPagesRef.current);
1425
1582
  const reason = event.reason;
1426
1583
  const errMsg = reason instanceof Error ? reason.message : String(reason);
1584
+ if (errMsg === "Script error." || errMsg === "Script error") {
1585
+ return;
1586
+ }
1427
1587
  const errStack = reason instanceof Error ? reason.stack : void 0;
1588
+ if (errStack && EXTENSION_ORIGIN_RE.test(errStack)) return;
1428
1589
  const sig = computeSignature({
1429
1590
  errorMessage: errMsg,
1430
1591
  pageUrl: context.url,
@@ -1510,6 +1671,16 @@ function GlitchgrabProviderInner({
1510
1671
  },
1511
1672
  []
1512
1673
  );
1674
+ const enhance = (0, import_react2.useCallback)(
1675
+ async (text) => {
1676
+ try {
1677
+ return await enhanceText(text, token, baseUrl);
1678
+ } catch (e) {
1679
+ return text;
1680
+ }
1681
+ },
1682
+ [token, baseUrl]
1683
+ );
1513
1684
  const openReportDialog = (0, import_react2.useCallback)((options) => {
1514
1685
  if (typeof window !== "undefined") {
1515
1686
  window.dispatchEvent(new CustomEvent("glitchgrab:open-report", { detail: options }));
@@ -1538,7 +1709,8 @@ function GlitchgrabProviderInner({
1538
1709
  reportBug,
1539
1710
  report,
1540
1711
  addBreadcrumb: addBreadcrumb2,
1541
- openReportDialog
1712
+ openReportDialog,
1713
+ enhanceText: enhance
1542
1714
  },
1543
1715
  children: [
1544
1716
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
@@ -1553,7 +1725,7 @@ function GlitchgrabProviderInner({
1553
1725
  children
1554
1726
  }
1555
1727
  ),
1556
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ReportDialog, { report, types, showSeverity })
1728
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ReportDialog, { report, enhanceText: enhance, types, showSeverity })
1557
1729
  ]
1558
1730
  }
1559
1731
  );
@@ -1779,6 +1951,7 @@ function useGlitchgrabActions({
1779
1951
  clearBreadcrumbs,
1780
1952
  clearDedupCache,
1781
1953
  computeSignature,
1954
+ enhanceText,
1782
1955
  fetchGlitchgrabReports,
1783
1956
  getBreadcrumbs,
1784
1957
  initBreadcrumbs,