@merittdev/horus-lens 0.5.0 → 0.5.2

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.
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  LENS_OVERLAY_HOST_ID,
3
3
  LensClient
4
- } from "./chunk-2G5FEWPU.js";
4
+ } from "./chunk-25CZMYQK.js";
5
5
 
6
6
  // ../browser/dist/index.js
7
7
  var DEFAULT_PARAM_NAME = "lens";
@@ -2724,4 +2724,4 @@ export {
2724
2724
  boot,
2725
2725
  autoBoot
2726
2726
  };
2727
- //# sourceMappingURL=chunk-M3QMIY4Y.js.map
2727
+ //# sourceMappingURL=chunk-4E427AKG.js.map
package/dist/index.cjs CHANGED
@@ -29111,7 +29111,7 @@ async function domToBlob(node2, options) {
29111
29111
 
29112
29112
  // ../core/dist/index.js
29113
29113
  var SDK_NAME = "@merittdev/horus-lens";
29114
- var SDK_VERSION = true ? "0.5.0" : "0.0.0-dev";
29114
+ var SDK_VERSION = true ? "0.5.2" : "0.0.0-dev";
29115
29115
  var DEFAULT_ENDPOINT = "https://api.horus.sh";
29116
29116
  var DEFAULT_REPLAY_WINDOW_MS = 15e3;
29117
29117
  var DEFAULT_MAX_CONSOLE_ENTRIES = 200;
@@ -29123,6 +29123,7 @@ var MAX_SERIALIZED_ARG_CHARS = 2e3;
29123
29123
  var MAX_DOM_BYTES = 2 * 1024 * 1024;
29124
29124
  var MAX_TARGET_TEXT_CHARS = 200;
29125
29125
  var SCREENSHOT_TIMEOUT_MS = 2e4;
29126
+ var SCREENSHOT_RESOURCE_TIMEOUT_MS = 3500;
29126
29127
  var SCREENSHOT_MAX_SCALE = 2;
29127
29128
  var SCREENSHOT_MAX_PIXELS = 25e5;
29128
29129
  var AUTO_CAPTURE_COOLDOWN_MS = 10 * 60 * 1e3;
@@ -29677,6 +29678,14 @@ var ReplayRecorder = class {
29677
29678
  }
29678
29679
  };
29679
29680
  var SVG_RASTERIZE_TIMEOUT_MS = 3e3;
29681
+ function isOffscreenMedia(node2) {
29682
+ if (!(node2 instanceof HTMLImageElement) && !(node2 instanceof HTMLIFrameElement) && !(typeof HTMLVideoElement !== "undefined" && node2 instanceof HTMLVideoElement)) {
29683
+ return false;
29684
+ }
29685
+ const r = node2.getBoundingClientRect();
29686
+ if (r.width === 0 && r.height === 0) return false;
29687
+ return r.bottom < 0 || r.top > window.innerHeight || r.right < 0 || r.left > window.innerWidth;
29688
+ }
29680
29689
  function computeCropRect(crop, scale, rasterWidth, rasterHeight) {
29681
29690
  let sx = Math.round(crop.x * scale);
29682
29691
  let sy = Math.round(crop.y * scale);
@@ -29692,8 +29701,11 @@ function computeCropRect(crop, scale, rasterWidth, rasterHeight) {
29692
29701
  async function captureScreenshot(excludeHost, crop, composite) {
29693
29702
  if (typeof document === "undefined" || typeof window === "undefined") return null;
29694
29703
  try {
29695
- const viewportPixels = window.innerWidth * window.innerHeight || 1;
29696
- const pixelCap = Math.sqrt(SCREENSHOT_MAX_PIXELS / viewportPixels);
29704
+ const viewportOnly = !composite && !crop;
29705
+ const captureW = composite ? composite.docWidth : window.innerWidth;
29706
+ const captureH = composite ? composite.docHeight : window.innerHeight;
29707
+ const capturePixels = captureW * captureH || 1;
29708
+ const pixelCap = Math.sqrt(SCREENSHOT_MAX_PIXELS / capturePixels);
29697
29709
  const scale = Math.max(1, Math.min(window.devicePixelRatio || 1, SCREENSHOT_MAX_SCALE, pixelCap));
29698
29710
  const capture = domToBlob(document.documentElement, {
29699
29711
  scale,
@@ -29702,18 +29714,35 @@ async function captureScreenshot(excludeHost, crop, composite) {
29702
29714
  // JPEG has no alpha — transparent page regions (and any capture box
29703
29715
  // extending past short content) would otherwise encode as BLACK.
29704
29716
  backgroundColor: "#ffffff",
29705
- // When compositing annotations, force the capture box to the editor's
29706
- // document measurement (scrollHeight-based). modern-screenshot otherwise
29707
- // sizes from documentElement's bounding box, which on pages SHORTER than
29708
- // the viewport is the content height only — marks drawn in the lower
29709
- // viewport band would fall off the raster and the crop would clamp short.
29717
+ // Composite (annotations): force the capture box to the editor's document
29718
+ // measurement so marks in the lower viewport band aren't clipped.
29710
29719
  ...composite ? { width: composite.docWidth, height: composite.docHeight } : {},
29711
- // Exclude the overlay from the capture CLONE — never hide the live node.
29712
- filter: (node2) => node2 !== excludeHost,
29713
- // Per-resource fetch budget: a single slow cross-origin image must not
29714
- // consume the whole capture window.
29720
+ // Plain report: clip the render to the viewport and shift the scrolled
29721
+ // content into it, so only the visible region is rasterized/fetched.
29722
+ ...viewportOnly ? {
29723
+ width: window.innerWidth,
29724
+ height: window.innerHeight,
29725
+ style: {
29726
+ transform: `translate(${-window.scrollX}px, ${-window.scrollY}px)`,
29727
+ transformOrigin: "top left"
29728
+ }
29729
+ } : {},
29730
+ // Exclude the overlay from the capture CLONE (never hide the live node),
29731
+ // and — for a plain viewport report — drop images/iframes entirely outside
29732
+ // the viewport so we don't fetch dozens of off-screen cross-origin assets.
29733
+ filter: (node2) => {
29734
+ if (node2 === excludeHost) return false;
29735
+ if (viewportOnly && isOffscreenMedia(node2)) return false;
29736
+ return true;
29737
+ },
29738
+ // Skip web-font download/embed. On font-heavy pages (multiple custom
29739
+ // families) this is a dominant, flaky cost; fallback fonts are fine for a
29740
+ // bug-report screenshot and capture becomes far more reliable.
29741
+ font: false,
29715
29742
  fetch: { requestInit: { cache: "force-cache" }, bypassingCache: false },
29716
- timeout: SCREENSHOT_TIMEOUT_MS - 1e3
29743
+ // PER-RESOURCE cap (NOT the overall budget): a hanging asset fails fast to
29744
+ // a placeholder instead of stalling the whole capture.
29745
+ timeout: SCREENSHOT_RESOURCE_TIMEOUT_MS
29717
29746
  });
29718
29747
  const started = Date.now();
29719
29748
  const timeout = new Promise((resolve) => {
@@ -29742,14 +29771,8 @@ async function captureScreenshot(excludeHost, crop, composite) {
29742
29771
  return null;
29743
29772
  }
29744
29773
  }
29745
- const effectiveCrop = crop ?? (composite ? void 0 : {
29746
- x: window.scrollX,
29747
- y: window.scrollY,
29748
- width: window.innerWidth,
29749
- height: window.innerHeight
29750
- });
29751
- if (effectiveCrop) {
29752
- const cropped = await cropBlob(blob2, effectiveCrop, scale);
29774
+ if (crop) {
29775
+ const cropped = await cropBlob(blob2, crop, scale);
29753
29776
  return cropped ?? blob2;
29754
29777
  }
29755
29778
  return blob2;