@merittdev/horus-lens 0.1.1 → 0.2.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/browser.cjs +1261 -194
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +2 -2
- package/dist/browser.d.ts +2 -2
- package/dist/browser.js +2 -2
- package/dist/{chunk-UB7YYHI4.js → chunk-JXSK4JG4.js} +245 -27
- package/dist/chunk-JXSK4JG4.js.map +1 -0
- package/dist/{chunk-CRV65EEY.js → chunk-UT7E5LCG.js} +1016 -167
- package/dist/chunk-UT7E5LCG.js.map +1 -0
- package/dist/index.cjs +244 -26
- package/dist/index.cjs.map +1 -1
- package/dist/{index.d-DeLYS02n.d.ts → index.d-BtnbCqUx.d.ts} +26 -1
- package/dist/index.d-Cyvb07sp.d.cts +301 -0
- package/dist/index.d-Cyvb07sp.d.ts +301 -0
- package/dist/{index.d-sNoEEgRg.d.cts → index.d-QzZn4EMM.d.cts} +26 -1
- package/dist/index.d.cts +342 -37
- package/dist/index.d.ts +342 -37
- package/dist/index.js +1 -1
- package/dist/lens.min.js +163 -43
- package/dist/lens.min.js.map +1 -1
- package/dist/react.cjs +1261 -194
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js +2 -2
- package/package.json +3 -3
- package/dist/chunk-CRV65EEY.js.map +0 -1
- package/dist/chunk-UB7YYHI4.js.map +0 -1
- package/dist/index.d-Bzgtl7-B.d.cts +0 -161
- package/dist/index.d-Bzgtl7-B.d.ts +0 -161
package/dist/index.cjs
CHANGED
|
@@ -14633,15 +14633,86 @@ var TargetElementSchema = external_exports.object({
|
|
|
14633
14633
|
boundingRect: external_exports.object({ x: external_exports.number(), y: external_exports.number(), width: external_exports.number(), height: external_exports.number() }).optional(),
|
|
14634
14634
|
reactComponents: external_exports.array(external_exports.string()).optional()
|
|
14635
14635
|
});
|
|
14636
|
-
var
|
|
14637
|
-
|
|
14638
|
-
|
|
14639
|
-
|
|
14640
|
-
|
|
14641
|
-
|
|
14642
|
-
|
|
14643
|
-
|
|
14644
|
-
|
|
14636
|
+
var annotationCommon = {
|
|
14637
|
+
id: external_exports.string().optional(),
|
|
14638
|
+
/** Any CSS color string. */
|
|
14639
|
+
color: external_exports.string().optional(),
|
|
14640
|
+
strokeWidth: external_exports.number().optional()
|
|
14641
|
+
};
|
|
14642
|
+
var AnnotationPointSchema = external_exports.object({ x: external_exports.number(), y: external_exports.number() });
|
|
14643
|
+
var AnnotationSchema = external_exports.discriminatedUnion("kind", [
|
|
14644
|
+
external_exports.object({
|
|
14645
|
+
...annotationCommon,
|
|
14646
|
+
kind: external_exports.literal("rect"),
|
|
14647
|
+
x: external_exports.number(),
|
|
14648
|
+
y: external_exports.number(),
|
|
14649
|
+
width: external_exports.number(),
|
|
14650
|
+
height: external_exports.number(),
|
|
14651
|
+
/**
|
|
14652
|
+
* OPTIONAL, kept for back-compat with 0.1.x clients that emit
|
|
14653
|
+
* viewport-anchored rects. New clients emit document-pixel rects with no
|
|
14654
|
+
* viewport.
|
|
14655
|
+
*/
|
|
14656
|
+
viewport: external_exports.object({ width: external_exports.number(), height: external_exports.number() }).optional()
|
|
14657
|
+
}),
|
|
14658
|
+
external_exports.object({
|
|
14659
|
+
...annotationCommon,
|
|
14660
|
+
kind: external_exports.literal("ellipse"),
|
|
14661
|
+
x: external_exports.number(),
|
|
14662
|
+
y: external_exports.number(),
|
|
14663
|
+
width: external_exports.number(),
|
|
14664
|
+
height: external_exports.number()
|
|
14665
|
+
}),
|
|
14666
|
+
external_exports.object({
|
|
14667
|
+
...annotationCommon,
|
|
14668
|
+
kind: external_exports.literal("blur"),
|
|
14669
|
+
x: external_exports.number(),
|
|
14670
|
+
y: external_exports.number(),
|
|
14671
|
+
width: external_exports.number(),
|
|
14672
|
+
height: external_exports.number()
|
|
14673
|
+
}),
|
|
14674
|
+
external_exports.object({
|
|
14675
|
+
...annotationCommon,
|
|
14676
|
+
kind: external_exports.literal("arrow"),
|
|
14677
|
+
x1: external_exports.number(),
|
|
14678
|
+
y1: external_exports.number(),
|
|
14679
|
+
x2: external_exports.number(),
|
|
14680
|
+
y2: external_exports.number()
|
|
14681
|
+
}),
|
|
14682
|
+
external_exports.object({
|
|
14683
|
+
...annotationCommon,
|
|
14684
|
+
kind: external_exports.literal("line"),
|
|
14685
|
+
x1: external_exports.number(),
|
|
14686
|
+
y1: external_exports.number(),
|
|
14687
|
+
x2: external_exports.number(),
|
|
14688
|
+
y2: external_exports.number()
|
|
14689
|
+
}),
|
|
14690
|
+
external_exports.object({
|
|
14691
|
+
...annotationCommon,
|
|
14692
|
+
kind: external_exports.literal("pencil"),
|
|
14693
|
+
points: external_exports.array(AnnotationPointSchema).min(2)
|
|
14694
|
+
}),
|
|
14695
|
+
external_exports.object({
|
|
14696
|
+
...annotationCommon,
|
|
14697
|
+
kind: external_exports.literal("highlighter"),
|
|
14698
|
+
points: external_exports.array(AnnotationPointSchema).min(2)
|
|
14699
|
+
}),
|
|
14700
|
+
external_exports.object({
|
|
14701
|
+
...annotationCommon,
|
|
14702
|
+
kind: external_exports.literal("text"),
|
|
14703
|
+
x: external_exports.number(),
|
|
14704
|
+
y: external_exports.number(),
|
|
14705
|
+
text: external_exports.string(),
|
|
14706
|
+
fontSize: external_exports.number().optional()
|
|
14707
|
+
}),
|
|
14708
|
+
external_exports.object({
|
|
14709
|
+
...annotationCommon,
|
|
14710
|
+
kind: external_exports.literal("step"),
|
|
14711
|
+
x: external_exports.number(),
|
|
14712
|
+
y: external_exports.number(),
|
|
14713
|
+
n: external_exports.number()
|
|
14714
|
+
})
|
|
14715
|
+
]);
|
|
14645
14716
|
var AssetKindSchema = external_exports.enum(["replay", "console", "network", "dom", "screenshot", "attachment"]);
|
|
14646
14717
|
var AssetRefSchema = external_exports.object({
|
|
14647
14718
|
kind: AssetKindSchema,
|
|
@@ -29492,7 +29563,20 @@ var ReplayRecorder = class {
|
|
|
29492
29563
|
console.warn("[lens] rrweb recording unavailable; replay disabled", err);
|
|
29493
29564
|
}
|
|
29494
29565
|
};
|
|
29495
|
-
|
|
29566
|
+
var SVG_RASTERIZE_TIMEOUT_MS = 3e3;
|
|
29567
|
+
function computeCropRect(crop, scale, rasterWidth, rasterHeight) {
|
|
29568
|
+
let sx = Math.round(crop.x * scale);
|
|
29569
|
+
let sy = Math.round(crop.y * scale);
|
|
29570
|
+
let sw = Math.round(crop.width * scale);
|
|
29571
|
+
let sh = Math.round(crop.height * scale);
|
|
29572
|
+
sx = Math.max(0, Math.min(sx, rasterWidth));
|
|
29573
|
+
sy = Math.max(0, Math.min(sy, rasterHeight));
|
|
29574
|
+
sw = Math.min(sw, rasterWidth - sx);
|
|
29575
|
+
sh = Math.min(sh, rasterHeight - sy);
|
|
29576
|
+
if (sw <= 0 || sh <= 0) return null;
|
|
29577
|
+
return { sx, sy, sw, sh };
|
|
29578
|
+
}
|
|
29579
|
+
async function captureScreenshot(excludeHost, crop, composite) {
|
|
29496
29580
|
if (typeof document === "undefined" || typeof window === "undefined") return null;
|
|
29497
29581
|
try {
|
|
29498
29582
|
const viewportPixels = window.innerWidth * window.innerHeight || 1;
|
|
@@ -29502,6 +29586,15 @@ async function captureScreenshot(excludeHost, crop) {
|
|
|
29502
29586
|
scale,
|
|
29503
29587
|
type: "image/jpeg",
|
|
29504
29588
|
quality: 0.82,
|
|
29589
|
+
// JPEG has no alpha — transparent page regions (and any capture box
|
|
29590
|
+
// extending past short content) would otherwise encode as BLACK.
|
|
29591
|
+
backgroundColor: "#ffffff",
|
|
29592
|
+
// When compositing annotations, force the capture box to the editor's
|
|
29593
|
+
// document measurement (scrollHeight-based). modern-screenshot otherwise
|
|
29594
|
+
// sizes from documentElement's bounding box, which on pages SHORTER than
|
|
29595
|
+
// the viewport is the content height only — marks drawn in the lower
|
|
29596
|
+
// viewport band would fall off the raster and the crop would clamp short.
|
|
29597
|
+
...composite ? { width: composite.docWidth, height: composite.docHeight } : {},
|
|
29505
29598
|
// Exclude the overlay from the capture CLONE — never hide the live node.
|
|
29506
29599
|
filter: (node2) => node2 !== excludeHost,
|
|
29507
29600
|
// Per-resource fetch budget: a single slow cross-origin image must not
|
|
@@ -29526,6 +29619,16 @@ async function captureScreenshot(excludeHost, crop) {
|
|
|
29526
29619
|
);
|
|
29527
29620
|
return null;
|
|
29528
29621
|
}
|
|
29622
|
+
if (composite) {
|
|
29623
|
+
const baked = await compositeScreenshot(blob2, composite, scale, crop);
|
|
29624
|
+
if (baked) return baked;
|
|
29625
|
+
if (composite.blurRegions.length > 0) {
|
|
29626
|
+
console.warn(
|
|
29627
|
+
"[lens] screenshot compositing failed with active redactions; dropping screenshot to avoid leaking un-blurred content"
|
|
29628
|
+
);
|
|
29629
|
+
return null;
|
|
29630
|
+
}
|
|
29631
|
+
}
|
|
29529
29632
|
if (crop) {
|
|
29530
29633
|
const cropped = await cropBlob(blob2, crop, scale);
|
|
29531
29634
|
return cropped ?? blob2;
|
|
@@ -29536,35 +29639,146 @@ async function captureScreenshot(excludeHost, crop) {
|
|
|
29536
29639
|
return null;
|
|
29537
29640
|
}
|
|
29538
29641
|
}
|
|
29642
|
+
async function compositeScreenshot(blob2, composite, scale, crop) {
|
|
29643
|
+
try {
|
|
29644
|
+
if (typeof createImageBitmap !== "function" || typeof document === "undefined") return null;
|
|
29645
|
+
const bitmap = await createImageBitmap(blob2);
|
|
29646
|
+
const canvas = document.createElement("canvas");
|
|
29647
|
+
canvas.width = bitmap.width;
|
|
29648
|
+
canvas.height = bitmap.height;
|
|
29649
|
+
const ctx = canvas.getContext("2d");
|
|
29650
|
+
if (!ctx) {
|
|
29651
|
+
bitmap.close?.();
|
|
29652
|
+
return null;
|
|
29653
|
+
}
|
|
29654
|
+
ctx.fillStyle = "#ffffff";
|
|
29655
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
29656
|
+
ctx.drawImage(bitmap, 0, 0);
|
|
29657
|
+
bitmap.close?.();
|
|
29658
|
+
applyBlurRegions(ctx, canvas, composite.blurRegions, scale);
|
|
29659
|
+
await drawSvgOverlay(ctx, composite, scale);
|
|
29660
|
+
if (crop) {
|
|
29661
|
+
const rect = computeCropRect(crop, scale, canvas.width, canvas.height);
|
|
29662
|
+
if (rect) {
|
|
29663
|
+
const out = document.createElement("canvas");
|
|
29664
|
+
out.width = rect.sw;
|
|
29665
|
+
out.height = rect.sh;
|
|
29666
|
+
const octx = out.getContext("2d");
|
|
29667
|
+
if (octx) {
|
|
29668
|
+
octx.drawImage(canvas, rect.sx, rect.sy, rect.sw, rect.sh, 0, 0, rect.sw, rect.sh);
|
|
29669
|
+
return await canvasToJpegBlob(out);
|
|
29670
|
+
}
|
|
29671
|
+
}
|
|
29672
|
+
}
|
|
29673
|
+
return await canvasToJpegBlob(canvas);
|
|
29674
|
+
} catch (err) {
|
|
29675
|
+
console.warn("[lens] screenshot compositing failed:", err);
|
|
29676
|
+
return null;
|
|
29677
|
+
}
|
|
29678
|
+
}
|
|
29679
|
+
function applyBlurRegions(ctx, canvas, regions, scale) {
|
|
29680
|
+
if (regions.length === 0) return;
|
|
29681
|
+
const filterSupported = typeof ctx.filter === "string";
|
|
29682
|
+
const blurPx = Math.max(8, 12 * scale);
|
|
29683
|
+
const pad = Math.ceil(blurPx);
|
|
29684
|
+
for (const region of regions) {
|
|
29685
|
+
const x = Math.max(0, Math.min(Math.round(region.x * scale), canvas.width));
|
|
29686
|
+
const y = Math.max(0, Math.min(Math.round(region.y * scale), canvas.height));
|
|
29687
|
+
const w = Math.min(Math.round(region.width * scale), canvas.width - x);
|
|
29688
|
+
const h = Math.min(Math.round(region.height * scale), canvas.height - y);
|
|
29689
|
+
if (w <= 0 || h <= 0) continue;
|
|
29690
|
+
if (!filterSupported) {
|
|
29691
|
+
ctx.fillStyle = "rgba(127,127,127,1)";
|
|
29692
|
+
ctx.fillRect(x, y, w, h);
|
|
29693
|
+
continue;
|
|
29694
|
+
}
|
|
29695
|
+
const px = Math.max(0, x - pad);
|
|
29696
|
+
const py = Math.max(0, y - pad);
|
|
29697
|
+
const pw = Math.min(canvas.width, x + w + pad) - px;
|
|
29698
|
+
const ph = Math.min(canvas.height, y + h + pad) - py;
|
|
29699
|
+
if (pw <= 0 || ph <= 0) continue;
|
|
29700
|
+
const temp = document.createElement("canvas");
|
|
29701
|
+
temp.width = pw;
|
|
29702
|
+
temp.height = ph;
|
|
29703
|
+
const tctx = temp.getContext("2d");
|
|
29704
|
+
if (!tctx) {
|
|
29705
|
+
ctx.fillStyle = "rgba(127,127,127,1)";
|
|
29706
|
+
ctx.fillRect(x, y, w, h);
|
|
29707
|
+
continue;
|
|
29708
|
+
}
|
|
29709
|
+
tctx.filter = `blur(${blurPx}px)`;
|
|
29710
|
+
tctx.drawImage(canvas, px, py, pw, ph, 0, 0, pw, ph);
|
|
29711
|
+
tctx.filter = "none";
|
|
29712
|
+
ctx.save();
|
|
29713
|
+
ctx.beginPath();
|
|
29714
|
+
ctx.rect(x, y, w, h);
|
|
29715
|
+
ctx.clip();
|
|
29716
|
+
ctx.drawImage(temp, px, py);
|
|
29717
|
+
ctx.restore();
|
|
29718
|
+
}
|
|
29719
|
+
}
|
|
29720
|
+
async function drawSvgOverlay(ctx, composite, scale) {
|
|
29721
|
+
const { svgMarkup, docWidth, docHeight } = composite;
|
|
29722
|
+
if (!svgMarkup) return;
|
|
29723
|
+
const img = await loadSvgImage(svgMarkup);
|
|
29724
|
+
if (!img) return;
|
|
29725
|
+
try {
|
|
29726
|
+
ctx.drawImage(img, 0, 0, docWidth * scale, docHeight * scale);
|
|
29727
|
+
} catch (err) {
|
|
29728
|
+
console.warn("[lens] annotation overlay draw failed:", err);
|
|
29729
|
+
}
|
|
29730
|
+
}
|
|
29731
|
+
function loadSvgImage(svg) {
|
|
29732
|
+
return new Promise((resolve) => {
|
|
29733
|
+
if (typeof Image !== "function") {
|
|
29734
|
+
resolve(null);
|
|
29735
|
+
return;
|
|
29736
|
+
}
|
|
29737
|
+
let settled = false;
|
|
29738
|
+
const finish = (result2) => {
|
|
29739
|
+
if (settled) return;
|
|
29740
|
+
settled = true;
|
|
29741
|
+
clearTimeout(timer);
|
|
29742
|
+
resolve(result2);
|
|
29743
|
+
};
|
|
29744
|
+
const timer = setTimeout(() => {
|
|
29745
|
+
console.warn("[lens] annotation overlay rasterization timed out");
|
|
29746
|
+
finish(null);
|
|
29747
|
+
}, SVG_RASTERIZE_TIMEOUT_MS);
|
|
29748
|
+
const img = new Image();
|
|
29749
|
+
img.onload = () => finish(img);
|
|
29750
|
+
img.onerror = () => {
|
|
29751
|
+
console.warn("[lens] annotation overlay failed to rasterize");
|
|
29752
|
+
finish(null);
|
|
29753
|
+
};
|
|
29754
|
+
img.src = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svg);
|
|
29755
|
+
});
|
|
29756
|
+
}
|
|
29757
|
+
function canvasToJpegBlob(canvas) {
|
|
29758
|
+
return new Promise((resolve) => {
|
|
29759
|
+
canvas.toBlob((out) => resolve(out), "image/jpeg", 0.82);
|
|
29760
|
+
});
|
|
29761
|
+
}
|
|
29539
29762
|
async function cropBlob(blob2, crop, scale) {
|
|
29540
29763
|
try {
|
|
29541
29764
|
if (typeof createImageBitmap !== "function" || typeof document === "undefined") return null;
|
|
29542
29765
|
const bitmap = await createImageBitmap(blob2);
|
|
29543
|
-
|
|
29544
|
-
|
|
29545
|
-
let sw = Math.round(crop.width * scale);
|
|
29546
|
-
let sh = Math.round(crop.height * scale);
|
|
29547
|
-
sx = Math.max(0, Math.min(sx, bitmap.width));
|
|
29548
|
-
sy = Math.max(0, Math.min(sy, bitmap.height));
|
|
29549
|
-
sw = Math.min(sw, bitmap.width - sx);
|
|
29550
|
-
sh = Math.min(sh, bitmap.height - sy);
|
|
29551
|
-
if (sw <= 0 || sh <= 0) {
|
|
29766
|
+
const rect = computeCropRect(crop, scale, bitmap.width, bitmap.height);
|
|
29767
|
+
if (!rect) {
|
|
29552
29768
|
bitmap.close?.();
|
|
29553
29769
|
return null;
|
|
29554
29770
|
}
|
|
29555
29771
|
const canvas = document.createElement("canvas");
|
|
29556
|
-
canvas.width = sw;
|
|
29557
|
-
canvas.height = sh;
|
|
29772
|
+
canvas.width = rect.sw;
|
|
29773
|
+
canvas.height = rect.sh;
|
|
29558
29774
|
const ctx = canvas.getContext("2d");
|
|
29559
29775
|
if (!ctx) {
|
|
29560
29776
|
bitmap.close?.();
|
|
29561
29777
|
return null;
|
|
29562
29778
|
}
|
|
29563
|
-
ctx.drawImage(bitmap, sx, sy, sw, sh, 0, 0, sw, sh);
|
|
29779
|
+
ctx.drawImage(bitmap, rect.sx, rect.sy, rect.sw, rect.sh, 0, 0, rect.sw, rect.sh);
|
|
29564
29780
|
bitmap.close?.();
|
|
29565
|
-
return await
|
|
29566
|
-
canvas.toBlob((out) => resolve(out), "image/jpeg", 0.82);
|
|
29567
|
-
});
|
|
29781
|
+
return await canvasToJpegBlob(canvas);
|
|
29568
29782
|
} catch (err) {
|
|
29569
29783
|
console.warn("[lens] screenshot crop failed:", err);
|
|
29570
29784
|
return null;
|
|
@@ -29834,7 +30048,11 @@ var LensClient = class {
|
|
|
29834
30048
|
const wantErrors = include.errors !== false;
|
|
29835
30049
|
const wantScreenshot = include.screenshot !== false;
|
|
29836
30050
|
const wantDom = include.dom !== false;
|
|
29837
|
-
const screenshotPromise = this.screenshotEnabled && wantScreenshot ? captureScreenshot(
|
|
30051
|
+
const screenshotPromise = this.screenshotEnabled && wantScreenshot ? captureScreenshot(
|
|
30052
|
+
input2.excludeFromScreenshot,
|
|
30053
|
+
input2.screenshotCrop,
|
|
30054
|
+
input2.annotationComposite
|
|
30055
|
+
) : Promise.resolve(null);
|
|
29838
30056
|
const replayEvents = wantReplay ? this.replay?.snapshot() ?? [] : [];
|
|
29839
30057
|
const errorEntries = this.errorBuffer.drain();
|
|
29840
30058
|
const consoleTail = this.consoleBuffer.tail(CONSOLE_TAIL_SIZE);
|