@merittdev/horus-lens 0.1.1 → 0.2.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/dist/browser.cjs +1262 -195
- 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-CRV65EEY.js → chunk-SDMTZ5Y6.js} +1016 -167
- package/dist/chunk-SDMTZ5Y6.js.map +1 -0
- package/dist/{chunk-UB7YYHI4.js → chunk-U6GBOUCE.js} +246 -28
- package/dist/chunk-U6GBOUCE.js.map +1 -0
- package/dist/index.cjs +245 -27
- 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 +343 -38
- package/dist/index.d.ts +343 -38
- 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 +1262 -195
- 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 +4 -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
|
@@ -14586,15 +14586,86 @@ var TargetElementSchema = external_exports.object({
|
|
|
14586
14586
|
boundingRect: external_exports.object({ x: external_exports.number(), y: external_exports.number(), width: external_exports.number(), height: external_exports.number() }).optional(),
|
|
14587
14587
|
reactComponents: external_exports.array(external_exports.string()).optional()
|
|
14588
14588
|
});
|
|
14589
|
-
var
|
|
14590
|
-
|
|
14591
|
-
|
|
14592
|
-
|
|
14593
|
-
|
|
14594
|
-
|
|
14595
|
-
|
|
14596
|
-
|
|
14597
|
-
|
|
14589
|
+
var annotationCommon = {
|
|
14590
|
+
id: external_exports.string().optional(),
|
|
14591
|
+
/** Any CSS color string. */
|
|
14592
|
+
color: external_exports.string().optional(),
|
|
14593
|
+
strokeWidth: external_exports.number().optional()
|
|
14594
|
+
};
|
|
14595
|
+
var AnnotationPointSchema = external_exports.object({ x: external_exports.number(), y: external_exports.number() });
|
|
14596
|
+
var AnnotationSchema = external_exports.discriminatedUnion("kind", [
|
|
14597
|
+
external_exports.object({
|
|
14598
|
+
...annotationCommon,
|
|
14599
|
+
kind: external_exports.literal("rect"),
|
|
14600
|
+
x: external_exports.number(),
|
|
14601
|
+
y: external_exports.number(),
|
|
14602
|
+
width: external_exports.number(),
|
|
14603
|
+
height: external_exports.number(),
|
|
14604
|
+
/**
|
|
14605
|
+
* OPTIONAL, kept for back-compat with 0.1.x clients that emit
|
|
14606
|
+
* viewport-anchored rects. New clients emit document-pixel rects with no
|
|
14607
|
+
* viewport.
|
|
14608
|
+
*/
|
|
14609
|
+
viewport: external_exports.object({ width: external_exports.number(), height: external_exports.number() }).optional()
|
|
14610
|
+
}),
|
|
14611
|
+
external_exports.object({
|
|
14612
|
+
...annotationCommon,
|
|
14613
|
+
kind: external_exports.literal("ellipse"),
|
|
14614
|
+
x: external_exports.number(),
|
|
14615
|
+
y: external_exports.number(),
|
|
14616
|
+
width: external_exports.number(),
|
|
14617
|
+
height: external_exports.number()
|
|
14618
|
+
}),
|
|
14619
|
+
external_exports.object({
|
|
14620
|
+
...annotationCommon,
|
|
14621
|
+
kind: external_exports.literal("blur"),
|
|
14622
|
+
x: external_exports.number(),
|
|
14623
|
+
y: external_exports.number(),
|
|
14624
|
+
width: external_exports.number(),
|
|
14625
|
+
height: external_exports.number()
|
|
14626
|
+
}),
|
|
14627
|
+
external_exports.object({
|
|
14628
|
+
...annotationCommon,
|
|
14629
|
+
kind: external_exports.literal("arrow"),
|
|
14630
|
+
x1: external_exports.number(),
|
|
14631
|
+
y1: external_exports.number(),
|
|
14632
|
+
x2: external_exports.number(),
|
|
14633
|
+
y2: external_exports.number()
|
|
14634
|
+
}),
|
|
14635
|
+
external_exports.object({
|
|
14636
|
+
...annotationCommon,
|
|
14637
|
+
kind: external_exports.literal("line"),
|
|
14638
|
+
x1: external_exports.number(),
|
|
14639
|
+
y1: external_exports.number(),
|
|
14640
|
+
x2: external_exports.number(),
|
|
14641
|
+
y2: external_exports.number()
|
|
14642
|
+
}),
|
|
14643
|
+
external_exports.object({
|
|
14644
|
+
...annotationCommon,
|
|
14645
|
+
kind: external_exports.literal("pencil"),
|
|
14646
|
+
points: external_exports.array(AnnotationPointSchema).min(2)
|
|
14647
|
+
}),
|
|
14648
|
+
external_exports.object({
|
|
14649
|
+
...annotationCommon,
|
|
14650
|
+
kind: external_exports.literal("highlighter"),
|
|
14651
|
+
points: external_exports.array(AnnotationPointSchema).min(2)
|
|
14652
|
+
}),
|
|
14653
|
+
external_exports.object({
|
|
14654
|
+
...annotationCommon,
|
|
14655
|
+
kind: external_exports.literal("text"),
|
|
14656
|
+
x: external_exports.number(),
|
|
14657
|
+
y: external_exports.number(),
|
|
14658
|
+
text: external_exports.string(),
|
|
14659
|
+
fontSize: external_exports.number().optional()
|
|
14660
|
+
}),
|
|
14661
|
+
external_exports.object({
|
|
14662
|
+
...annotationCommon,
|
|
14663
|
+
kind: external_exports.literal("step"),
|
|
14664
|
+
x: external_exports.number(),
|
|
14665
|
+
y: external_exports.number(),
|
|
14666
|
+
n: external_exports.number()
|
|
14667
|
+
})
|
|
14668
|
+
]);
|
|
14598
14669
|
var AssetKindSchema = external_exports.enum(["replay", "console", "network", "dom", "screenshot", "attachment"]);
|
|
14599
14670
|
var AssetRefSchema = external_exports.object({
|
|
14600
14671
|
kind: AssetKindSchema,
|
|
@@ -28984,7 +29055,7 @@ async function domToBlob(node2, options) {
|
|
|
28984
29055
|
|
|
28985
29056
|
// ../core/dist/index.js
|
|
28986
29057
|
var SDK_NAME = "@merittdev/horus-lens";
|
|
28987
|
-
var SDK_VERSION = "0.
|
|
29058
|
+
var SDK_VERSION = true ? "0.2.1" : "0.0.0-dev";
|
|
28988
29059
|
var DEFAULT_ENDPOINT = "https://api.horus.sh";
|
|
28989
29060
|
var DEFAULT_REPLAY_WINDOW_MS = 15e3;
|
|
28990
29061
|
var DEFAULT_MAX_CONSOLE_ENTRIES = 200;
|
|
@@ -29445,7 +29516,20 @@ var ReplayRecorder = class {
|
|
|
29445
29516
|
console.warn("[lens] rrweb recording unavailable; replay disabled", err);
|
|
29446
29517
|
}
|
|
29447
29518
|
};
|
|
29448
|
-
|
|
29519
|
+
var SVG_RASTERIZE_TIMEOUT_MS = 3e3;
|
|
29520
|
+
function computeCropRect(crop, scale, rasterWidth, rasterHeight) {
|
|
29521
|
+
let sx = Math.round(crop.x * scale);
|
|
29522
|
+
let sy = Math.round(crop.y * scale);
|
|
29523
|
+
let sw = Math.round(crop.width * scale);
|
|
29524
|
+
let sh = Math.round(crop.height * scale);
|
|
29525
|
+
sx = Math.max(0, Math.min(sx, rasterWidth));
|
|
29526
|
+
sy = Math.max(0, Math.min(sy, rasterHeight));
|
|
29527
|
+
sw = Math.min(sw, rasterWidth - sx);
|
|
29528
|
+
sh = Math.min(sh, rasterHeight - sy);
|
|
29529
|
+
if (sw <= 0 || sh <= 0) return null;
|
|
29530
|
+
return { sx, sy, sw, sh };
|
|
29531
|
+
}
|
|
29532
|
+
async function captureScreenshot(excludeHost, crop, composite) {
|
|
29449
29533
|
if (typeof document === "undefined" || typeof window === "undefined") return null;
|
|
29450
29534
|
try {
|
|
29451
29535
|
const viewportPixels = window.innerWidth * window.innerHeight || 1;
|
|
@@ -29455,6 +29539,15 @@ async function captureScreenshot(excludeHost, crop) {
|
|
|
29455
29539
|
scale,
|
|
29456
29540
|
type: "image/jpeg",
|
|
29457
29541
|
quality: 0.82,
|
|
29542
|
+
// JPEG has no alpha — transparent page regions (and any capture box
|
|
29543
|
+
// extending past short content) would otherwise encode as BLACK.
|
|
29544
|
+
backgroundColor: "#ffffff",
|
|
29545
|
+
// When compositing annotations, force the capture box to the editor's
|
|
29546
|
+
// document measurement (scrollHeight-based). modern-screenshot otherwise
|
|
29547
|
+
// sizes from documentElement's bounding box, which on pages SHORTER than
|
|
29548
|
+
// the viewport is the content height only — marks drawn in the lower
|
|
29549
|
+
// viewport band would fall off the raster and the crop would clamp short.
|
|
29550
|
+
...composite ? { width: composite.docWidth, height: composite.docHeight } : {},
|
|
29458
29551
|
// Exclude the overlay from the capture CLONE — never hide the live node.
|
|
29459
29552
|
filter: (node2) => node2 !== excludeHost,
|
|
29460
29553
|
// Per-resource fetch budget: a single slow cross-origin image must not
|
|
@@ -29479,6 +29572,16 @@ async function captureScreenshot(excludeHost, crop) {
|
|
|
29479
29572
|
);
|
|
29480
29573
|
return null;
|
|
29481
29574
|
}
|
|
29575
|
+
if (composite) {
|
|
29576
|
+
const baked = await compositeScreenshot(blob2, composite, scale, crop);
|
|
29577
|
+
if (baked) return baked;
|
|
29578
|
+
if (composite.blurRegions.length > 0) {
|
|
29579
|
+
console.warn(
|
|
29580
|
+
"[lens] screenshot compositing failed with active redactions; dropping screenshot to avoid leaking un-blurred content"
|
|
29581
|
+
);
|
|
29582
|
+
return null;
|
|
29583
|
+
}
|
|
29584
|
+
}
|
|
29482
29585
|
if (crop) {
|
|
29483
29586
|
const cropped = await cropBlob(blob2, crop, scale);
|
|
29484
29587
|
return cropped ?? blob2;
|
|
@@ -29489,35 +29592,146 @@ async function captureScreenshot(excludeHost, crop) {
|
|
|
29489
29592
|
return null;
|
|
29490
29593
|
}
|
|
29491
29594
|
}
|
|
29595
|
+
async function compositeScreenshot(blob2, composite, scale, crop) {
|
|
29596
|
+
try {
|
|
29597
|
+
if (typeof createImageBitmap !== "function" || typeof document === "undefined") return null;
|
|
29598
|
+
const bitmap = await createImageBitmap(blob2);
|
|
29599
|
+
const canvas = document.createElement("canvas");
|
|
29600
|
+
canvas.width = bitmap.width;
|
|
29601
|
+
canvas.height = bitmap.height;
|
|
29602
|
+
const ctx = canvas.getContext("2d");
|
|
29603
|
+
if (!ctx) {
|
|
29604
|
+
bitmap.close?.();
|
|
29605
|
+
return null;
|
|
29606
|
+
}
|
|
29607
|
+
ctx.fillStyle = "#ffffff";
|
|
29608
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
29609
|
+
ctx.drawImage(bitmap, 0, 0);
|
|
29610
|
+
bitmap.close?.();
|
|
29611
|
+
applyBlurRegions(ctx, canvas, composite.blurRegions, scale);
|
|
29612
|
+
await drawSvgOverlay(ctx, composite, scale);
|
|
29613
|
+
if (crop) {
|
|
29614
|
+
const rect = computeCropRect(crop, scale, canvas.width, canvas.height);
|
|
29615
|
+
if (rect) {
|
|
29616
|
+
const out = document.createElement("canvas");
|
|
29617
|
+
out.width = rect.sw;
|
|
29618
|
+
out.height = rect.sh;
|
|
29619
|
+
const octx = out.getContext("2d");
|
|
29620
|
+
if (octx) {
|
|
29621
|
+
octx.drawImage(canvas, rect.sx, rect.sy, rect.sw, rect.sh, 0, 0, rect.sw, rect.sh);
|
|
29622
|
+
return await canvasToJpegBlob(out);
|
|
29623
|
+
}
|
|
29624
|
+
}
|
|
29625
|
+
}
|
|
29626
|
+
return await canvasToJpegBlob(canvas);
|
|
29627
|
+
} catch (err) {
|
|
29628
|
+
console.warn("[lens] screenshot compositing failed:", err);
|
|
29629
|
+
return null;
|
|
29630
|
+
}
|
|
29631
|
+
}
|
|
29632
|
+
function applyBlurRegions(ctx, canvas, regions, scale) {
|
|
29633
|
+
if (regions.length === 0) return;
|
|
29634
|
+
const filterSupported = typeof ctx.filter === "string";
|
|
29635
|
+
const blurPx = Math.max(8, 12 * scale);
|
|
29636
|
+
const pad = Math.ceil(blurPx);
|
|
29637
|
+
for (const region of regions) {
|
|
29638
|
+
const x = Math.max(0, Math.min(Math.round(region.x * scale), canvas.width));
|
|
29639
|
+
const y = Math.max(0, Math.min(Math.round(region.y * scale), canvas.height));
|
|
29640
|
+
const w = Math.min(Math.round(region.width * scale), canvas.width - x);
|
|
29641
|
+
const h = Math.min(Math.round(region.height * scale), canvas.height - y);
|
|
29642
|
+
if (w <= 0 || h <= 0) continue;
|
|
29643
|
+
if (!filterSupported) {
|
|
29644
|
+
ctx.fillStyle = "rgba(127,127,127,1)";
|
|
29645
|
+
ctx.fillRect(x, y, w, h);
|
|
29646
|
+
continue;
|
|
29647
|
+
}
|
|
29648
|
+
const px = Math.max(0, x - pad);
|
|
29649
|
+
const py = Math.max(0, y - pad);
|
|
29650
|
+
const pw = Math.min(canvas.width, x + w + pad) - px;
|
|
29651
|
+
const ph = Math.min(canvas.height, y + h + pad) - py;
|
|
29652
|
+
if (pw <= 0 || ph <= 0) continue;
|
|
29653
|
+
const temp = document.createElement("canvas");
|
|
29654
|
+
temp.width = pw;
|
|
29655
|
+
temp.height = ph;
|
|
29656
|
+
const tctx = temp.getContext("2d");
|
|
29657
|
+
if (!tctx) {
|
|
29658
|
+
ctx.fillStyle = "rgba(127,127,127,1)";
|
|
29659
|
+
ctx.fillRect(x, y, w, h);
|
|
29660
|
+
continue;
|
|
29661
|
+
}
|
|
29662
|
+
tctx.filter = `blur(${blurPx}px)`;
|
|
29663
|
+
tctx.drawImage(canvas, px, py, pw, ph, 0, 0, pw, ph);
|
|
29664
|
+
tctx.filter = "none";
|
|
29665
|
+
ctx.save();
|
|
29666
|
+
ctx.beginPath();
|
|
29667
|
+
ctx.rect(x, y, w, h);
|
|
29668
|
+
ctx.clip();
|
|
29669
|
+
ctx.drawImage(temp, px, py);
|
|
29670
|
+
ctx.restore();
|
|
29671
|
+
}
|
|
29672
|
+
}
|
|
29673
|
+
async function drawSvgOverlay(ctx, composite, scale) {
|
|
29674
|
+
const { svgMarkup, docWidth, docHeight } = composite;
|
|
29675
|
+
if (!svgMarkup) return;
|
|
29676
|
+
const img = await loadSvgImage(svgMarkup);
|
|
29677
|
+
if (!img) return;
|
|
29678
|
+
try {
|
|
29679
|
+
ctx.drawImage(img, 0, 0, docWidth * scale, docHeight * scale);
|
|
29680
|
+
} catch (err) {
|
|
29681
|
+
console.warn("[lens] annotation overlay draw failed:", err);
|
|
29682
|
+
}
|
|
29683
|
+
}
|
|
29684
|
+
function loadSvgImage(svg) {
|
|
29685
|
+
return new Promise((resolve) => {
|
|
29686
|
+
if (typeof Image !== "function") {
|
|
29687
|
+
resolve(null);
|
|
29688
|
+
return;
|
|
29689
|
+
}
|
|
29690
|
+
let settled = false;
|
|
29691
|
+
const finish = (result2) => {
|
|
29692
|
+
if (settled) return;
|
|
29693
|
+
settled = true;
|
|
29694
|
+
clearTimeout(timer);
|
|
29695
|
+
resolve(result2);
|
|
29696
|
+
};
|
|
29697
|
+
const timer = setTimeout(() => {
|
|
29698
|
+
console.warn("[lens] annotation overlay rasterization timed out");
|
|
29699
|
+
finish(null);
|
|
29700
|
+
}, SVG_RASTERIZE_TIMEOUT_MS);
|
|
29701
|
+
const img = new Image();
|
|
29702
|
+
img.onload = () => finish(img);
|
|
29703
|
+
img.onerror = () => {
|
|
29704
|
+
console.warn("[lens] annotation overlay failed to rasterize");
|
|
29705
|
+
finish(null);
|
|
29706
|
+
};
|
|
29707
|
+
img.src = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svg);
|
|
29708
|
+
});
|
|
29709
|
+
}
|
|
29710
|
+
function canvasToJpegBlob(canvas) {
|
|
29711
|
+
return new Promise((resolve) => {
|
|
29712
|
+
canvas.toBlob((out) => resolve(out), "image/jpeg", 0.82);
|
|
29713
|
+
});
|
|
29714
|
+
}
|
|
29492
29715
|
async function cropBlob(blob2, crop, scale) {
|
|
29493
29716
|
try {
|
|
29494
29717
|
if (typeof createImageBitmap !== "function" || typeof document === "undefined") return null;
|
|
29495
29718
|
const bitmap = await createImageBitmap(blob2);
|
|
29496
|
-
|
|
29497
|
-
|
|
29498
|
-
let sw = Math.round(crop.width * scale);
|
|
29499
|
-
let sh = Math.round(crop.height * scale);
|
|
29500
|
-
sx = Math.max(0, Math.min(sx, bitmap.width));
|
|
29501
|
-
sy = Math.max(0, Math.min(sy, bitmap.height));
|
|
29502
|
-
sw = Math.min(sw, bitmap.width - sx);
|
|
29503
|
-
sh = Math.min(sh, bitmap.height - sy);
|
|
29504
|
-
if (sw <= 0 || sh <= 0) {
|
|
29719
|
+
const rect = computeCropRect(crop, scale, bitmap.width, bitmap.height);
|
|
29720
|
+
if (!rect) {
|
|
29505
29721
|
bitmap.close?.();
|
|
29506
29722
|
return null;
|
|
29507
29723
|
}
|
|
29508
29724
|
const canvas = document.createElement("canvas");
|
|
29509
|
-
canvas.width = sw;
|
|
29510
|
-
canvas.height = sh;
|
|
29725
|
+
canvas.width = rect.sw;
|
|
29726
|
+
canvas.height = rect.sh;
|
|
29511
29727
|
const ctx = canvas.getContext("2d");
|
|
29512
29728
|
if (!ctx) {
|
|
29513
29729
|
bitmap.close?.();
|
|
29514
29730
|
return null;
|
|
29515
29731
|
}
|
|
29516
|
-
ctx.drawImage(bitmap, sx, sy, sw, sh, 0, 0, sw, sh);
|
|
29732
|
+
ctx.drawImage(bitmap, rect.sx, rect.sy, rect.sw, rect.sh, 0, 0, rect.sw, rect.sh);
|
|
29517
29733
|
bitmap.close?.();
|
|
29518
|
-
return await
|
|
29519
|
-
canvas.toBlob((out) => resolve(out), "image/jpeg", 0.82);
|
|
29520
|
-
});
|
|
29734
|
+
return await canvasToJpegBlob(canvas);
|
|
29521
29735
|
} catch (err) {
|
|
29522
29736
|
console.warn("[lens] screenshot crop failed:", err);
|
|
29523
29737
|
return null;
|
|
@@ -29787,7 +30001,11 @@ var LensClient = class {
|
|
|
29787
30001
|
const wantErrors = include.errors !== false;
|
|
29788
30002
|
const wantScreenshot = include.screenshot !== false;
|
|
29789
30003
|
const wantDom = include.dom !== false;
|
|
29790
|
-
const screenshotPromise = this.screenshotEnabled && wantScreenshot ? captureScreenshot(
|
|
30004
|
+
const screenshotPromise = this.screenshotEnabled && wantScreenshot ? captureScreenshot(
|
|
30005
|
+
input2.excludeFromScreenshot,
|
|
30006
|
+
input2.screenshotCrop,
|
|
30007
|
+
input2.annotationComposite
|
|
30008
|
+
) : Promise.resolve(null);
|
|
29791
30009
|
const replayEvents = wantReplay ? this.replay?.snapshot() ?? [] : [];
|
|
29792
30010
|
const errorEntries = this.errorBuffer.drain();
|
|
29793
30011
|
const consoleTail = this.consoleBuffer.tail(CONSOLE_TAIL_SIZE);
|
|
@@ -29926,4 +30144,4 @@ rrweb/dist/rrweb.js:
|
|
|
29926
30144
|
PERFORMANCE OF THIS SOFTWARE.
|
|
29927
30145
|
***************************************************************************** *)
|
|
29928
30146
|
*/
|
|
29929
|
-
//# sourceMappingURL=chunk-
|
|
30147
|
+
//# sourceMappingURL=chunk-U6GBOUCE.js.map
|