@insitue/sdk 0.1.4 → 0.1.6
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/capture-only.js +2 -2
- package/dist/{chunk-65BGOX2M.js → chunk-TQEOC7QZ.js} +77 -9
- package/dist/{chunk-TTH4NBFA.js → chunk-UWKF2IKW.js} +13 -4
- package/dist/{chunk-7GRJ5SZQ.js → chunk-V2VYHBQC.js} +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +7 -3
- package/dist/overlay.js +2 -2
- package/package.json +1 -1
package/dist/capture-only.js
CHANGED
|
@@ -1644,22 +1644,33 @@ async function toCanvas(node, options = {}) {
|
|
|
1644
1644
|
var IMAGE_PLACEHOLDER = "data:image/svg+xml;base64," + (typeof btoa !== "undefined" ? btoa(
|
|
1645
1645
|
'<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><rect width="32" height="32" fill="#e8e8e8"/><path d="M0 0 L32 32 M32 0 L0 32" stroke="#b0b0b0" stroke-width="1.5"/></svg>'
|
|
1646
1646
|
) : "");
|
|
1647
|
-
async function preResolveImages() {
|
|
1647
|
+
async function preResolveImages(cropRect) {
|
|
1648
1648
|
const restorations = [];
|
|
1649
1649
|
const failedImages = /* @__PURE__ */ new Set();
|
|
1650
|
+
const PAD = 64;
|
|
1650
1651
|
const images = Array.from(
|
|
1651
1652
|
document.querySelectorAll("img")
|
|
1652
|
-
).filter(
|
|
1653
|
-
(img
|
|
1654
|
-
|
|
1655
|
-
|
|
1653
|
+
).filter((img) => {
|
|
1654
|
+
if (img.closest?.("#insitu-root, [data-insitu-layer]")) return false;
|
|
1655
|
+
if (!cropRect) return true;
|
|
1656
|
+
const r3 = img.getBoundingClientRect();
|
|
1657
|
+
if (r3.width <= 0 || r3.height <= 0) return false;
|
|
1658
|
+
return r3.right >= cropRect.x - PAD && r3.left <= cropRect.x + cropRect.width + PAD && r3.bottom >= cropRect.y - PAD && r3.top <= cropRect.y + cropRect.height + PAD;
|
|
1659
|
+
});
|
|
1660
|
+
const PER_IMAGE_TIMEOUT_MS = 3e3;
|
|
1661
|
+
await Promise.allSettled(
|
|
1656
1662
|
images.map(async (img) => {
|
|
1657
1663
|
const srcToFetch = img.currentSrc || img.src;
|
|
1658
1664
|
if (!srcToFetch || srcToFetch.startsWith("data:") || srcToFetch.startsWith("blob:")) {
|
|
1659
1665
|
return;
|
|
1660
1666
|
}
|
|
1667
|
+
const ac = new AbortController();
|
|
1668
|
+
const timer = setTimeout(() => ac.abort(), PER_IMAGE_TIMEOUT_MS);
|
|
1661
1669
|
try {
|
|
1662
|
-
const res = await fetch(srcToFetch, {
|
|
1670
|
+
const res = await fetch(srcToFetch, {
|
|
1671
|
+
cache: "force-cache",
|
|
1672
|
+
signal: ac.signal
|
|
1673
|
+
});
|
|
1663
1674
|
if (!res.ok) {
|
|
1664
1675
|
failedImages.add(img);
|
|
1665
1676
|
return;
|
|
@@ -1687,6 +1698,8 @@ async function preResolveImages() {
|
|
|
1687
1698
|
}
|
|
1688
1699
|
} catch {
|
|
1689
1700
|
failedImages.add(img);
|
|
1701
|
+
} finally {
|
|
1702
|
+
clearTimeout(timer);
|
|
1690
1703
|
}
|
|
1691
1704
|
})
|
|
1692
1705
|
);
|
|
@@ -1718,7 +1731,7 @@ async function renderViewportCrop(cropRect, pixelRatio) {
|
|
|
1718
1731
|
const bodyBg = getComputedStyle(document.body).backgroundColor;
|
|
1719
1732
|
const htmlBg = getComputedStyle(document.documentElement).backgroundColor;
|
|
1720
1733
|
const backgroundColor = bodyBg && bodyBg !== "rgba(0, 0, 0, 0)" && bodyBg !== "transparent" ? bodyBg : htmlBg && htmlBg !== "rgba(0, 0, 0, 0)" && htmlBg !== "transparent" ? htmlBg : "#ffffff";
|
|
1721
|
-
const { restore: restoreImages, failedImages } = await preResolveImages();
|
|
1734
|
+
const { restore: restoreImages, failedImages } = await preResolveImages(cropRect);
|
|
1722
1735
|
try {
|
|
1723
1736
|
const fullCanvas = await toCanvas(document.documentElement, {
|
|
1724
1737
|
pixelRatio,
|
|
@@ -1750,11 +1763,59 @@ async function renderViewportCrop(cropRect, pixelRatio) {
|
|
|
1750
1763
|
if (looksBlankUniform(ctx, out.width, out.height)) {
|
|
1751
1764
|
return { dataUrl: null, failedImages };
|
|
1752
1765
|
}
|
|
1766
|
+
detectUnrenderedImages(ctx, cropRect, out, pixelRatio, failedImages);
|
|
1753
1767
|
return { dataUrl: out.toDataURL("image/png"), failedImages };
|
|
1754
1768
|
} finally {
|
|
1755
1769
|
restoreImages();
|
|
1756
1770
|
}
|
|
1757
1771
|
}
|
|
1772
|
+
function detectUnrenderedImages(cropCtx, cropRect, cropCanvas, pixelRatio, failedImages) {
|
|
1773
|
+
const imgs = Array.from(
|
|
1774
|
+
document.querySelectorAll("img")
|
|
1775
|
+
).filter(
|
|
1776
|
+
(img) => !img.closest?.("#insitu-root, [data-insitu-layer]")
|
|
1777
|
+
);
|
|
1778
|
+
for (const img of imgs) {
|
|
1779
|
+
if (failedImages.has(img)) continue;
|
|
1780
|
+
const r3 = img.getBoundingClientRect();
|
|
1781
|
+
if (r3.width < 32 || r3.height < 32) continue;
|
|
1782
|
+
const overlapX = Math.min(r3.right, cropRect.x + cropRect.width) - Math.max(r3.left, cropRect.x);
|
|
1783
|
+
const overlapY = Math.min(r3.bottom, cropRect.y + cropRect.height) - Math.max(r3.top, cropRect.y);
|
|
1784
|
+
if (overlapX <= 0 || overlapY <= 0) continue;
|
|
1785
|
+
const baseX = Math.max(r3.left, cropRect.x);
|
|
1786
|
+
const baseY = Math.max(r3.top, cropRect.y);
|
|
1787
|
+
const samples = /* @__PURE__ */ new Set();
|
|
1788
|
+
try {
|
|
1789
|
+
for (let i3 = 0; i3 < 3; i3++) {
|
|
1790
|
+
for (let j3 = 0; j3 < 3; j3++) {
|
|
1791
|
+
const px2 = baseX + overlapX * (i3 + 0.5) / 3;
|
|
1792
|
+
const py = baseY + overlapY * (j3 + 0.5) / 3;
|
|
1793
|
+
const cx = Math.max(
|
|
1794
|
+
0,
|
|
1795
|
+
Math.min(
|
|
1796
|
+
cropCanvas.width - 1,
|
|
1797
|
+
Math.round((px2 - cropRect.x) * pixelRatio)
|
|
1798
|
+
)
|
|
1799
|
+
);
|
|
1800
|
+
const cy = Math.max(
|
|
1801
|
+
0,
|
|
1802
|
+
Math.min(
|
|
1803
|
+
cropCanvas.height - 1,
|
|
1804
|
+
Math.round((py - cropRect.y) * pixelRatio)
|
|
1805
|
+
)
|
|
1806
|
+
);
|
|
1807
|
+
const d3 = cropCtx.getImageData(cx, cy, 1, 1).data;
|
|
1808
|
+
samples.add(`${d3[0]},${d3[1]},${d3[2]},${d3[3]}`);
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
} catch {
|
|
1812
|
+
continue;
|
|
1813
|
+
}
|
|
1814
|
+
if (samples.size === 1) {
|
|
1815
|
+
failedImages.add(img);
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1758
1819
|
function looksBlankUniform(ctx, w3, h3) {
|
|
1759
1820
|
if (w3 < 4 || h3 < 4) return false;
|
|
1760
1821
|
const samples = [];
|
|
@@ -1994,7 +2055,7 @@ async function buildBundle(sel) {
|
|
|
1994
2055
|
const settings = getCaptureSettings();
|
|
1995
2056
|
let screenshot;
|
|
1996
2057
|
let screenshotUnavailable;
|
|
1997
|
-
if (el instanceof HTMLElement) {
|
|
2058
|
+
if (el instanceof HTMLElement || el instanceof SVGElement) {
|
|
1998
2059
|
const context = findContextAncestor(el);
|
|
1999
2060
|
const cr = context.getBoundingClientRect();
|
|
2000
2061
|
const cropRect = new DOMRect(
|
|
@@ -2084,7 +2145,14 @@ async function buildBundle(sel) {
|
|
|
2084
2145
|
computedStyles: el ? curateComputedStyles(el) : {},
|
|
2085
2146
|
tailwindClasses: el ? extractTailwindClasses(el) : [],
|
|
2086
2147
|
...screenshot ? { screenshot } : {},
|
|
2087
|
-
|
|
2148
|
+
// "Never silent" — if neither screenshot nor screenshotUnavailable
|
|
2149
|
+
// got set above (an unexpected fallthrough), surface that fact
|
|
2150
|
+
// so the widget never renders a blank where a result should be.
|
|
2151
|
+
// The structured diagnostic below tells future-me exactly which
|
|
2152
|
+
// branch ran, surfaced as `__insitu_capture__.bundle` in dev.
|
|
2153
|
+
...screenshotUnavailable ? { screenshotUnavailable } : !screenshot ? {
|
|
2154
|
+
screenshotUnavailable: el ? `screenshot path didn't set a result (el=${el.tagName.toLowerCase()}; rasterisable=${el instanceof HTMLElement || el instanceof SVGElement})` : "no element selected"
|
|
2155
|
+
} : {},
|
|
2088
2156
|
viewport: {
|
|
2089
2157
|
w: window.innerWidth,
|
|
2090
2158
|
h: window.innerHeight,
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
retryDisplayMedia,
|
|
11
11
|
stopDisplayMedia,
|
|
12
12
|
y
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-TQEOC7QZ.js";
|
|
14
14
|
|
|
15
15
|
// src/capture-only.ts
|
|
16
16
|
var DEFAULT_INGEST = "https://www.insitue.com/api/v1/capture";
|
|
@@ -260,9 +260,11 @@ function CaptureOnlyApp(props) {
|
|
|
260
260
|
}) : bundle?.screenshotUnavailable ? k(
|
|
261
261
|
"div",
|
|
262
262
|
{
|
|
263
|
-
style: `font-size:12px;color:${C.faint};background:${C.surface2};border:1px solid ${C.line};border-radius:10px;padding:10px;margin-bottom:12px`
|
|
263
|
+
style: `font-size:12px;color:${C.faint};background:${C.surface2};border:1px solid ${C.line};border-radius:10px;padding:10px;margin-bottom:12px;word-break:break-word`
|
|
264
264
|
},
|
|
265
|
-
|
|
265
|
+
// Surface the actual reason inline — helps diagnose
|
|
266
|
+
// when a capture lands empty without expecting it.
|
|
267
|
+
`Screenshot unavailable \u2014 ${bundle.screenshotUnavailable}`
|
|
266
268
|
) : null,
|
|
267
269
|
// Nudge: the screenshot is structurally OK but some content
|
|
268
270
|
// couldn't be embedded (non-CORS img / video / canvas). Offer
|
|
@@ -347,7 +349,14 @@ function CaptureOnlyApp(props) {
|
|
|
347
349
|
{
|
|
348
350
|
style: `display:flex;justify-content:space-between;padding:9px 16px;border-top:1px solid ${C.line};color:${C.faint};font-size:11px`
|
|
349
351
|
},
|
|
350
|
-
[
|
|
352
|
+
[
|
|
353
|
+
k("span", {}, "\u{1F512} Secrets scrubbed automatically"),
|
|
354
|
+
k(
|
|
355
|
+
"span",
|
|
356
|
+
{ title: `@insitue/sdk@${"0.1.6"}` },
|
|
357
|
+
`InSitue \xB7 v${"0.1.6"}`
|
|
358
|
+
)
|
|
359
|
+
]
|
|
351
360
|
)
|
|
352
361
|
]);
|
|
353
362
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -33,4 +33,10 @@ interface InSitueCaptureProps {
|
|
|
33
33
|
*/
|
|
34
34
|
declare function InSitueCapture({ projectKey, endpoint, onCapture, }: InSitueCaptureProps): null;
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
/** Build-time-inlined version of `@insitue/sdk` (from package.json).
|
|
37
|
+
* Exposed so the host app can self-verify which SDK build is loaded
|
|
38
|
+
* — useful in dev when iterating across publishes. Also surfaced in
|
|
39
|
+
* the capture widget footer so a screenshot proves the build. */
|
|
40
|
+
declare const SDK_VERSION: string;
|
|
41
|
+
|
|
42
|
+
export { InSitue, InSitueCapture, type InSitueCaptureProps, type InSitueProps, SDK_VERSION };
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
mountCaptureOnly
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-UWKF2IKW.js";
|
|
4
4
|
import {
|
|
5
5
|
mountInSitue
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-V2VYHBQC.js";
|
|
7
|
+
import "./chunk-TQEOC7QZ.js";
|
|
8
8
|
|
|
9
9
|
// src/InSitue.tsx
|
|
10
10
|
import { useEffect } from "react";
|
|
@@ -44,9 +44,13 @@ function InSitueCapture({
|
|
|
44
44
|
}, [projectKey, endpoint, onCapture]);
|
|
45
45
|
return null;
|
|
46
46
|
}
|
|
47
|
+
|
|
48
|
+
// src/index.ts
|
|
49
|
+
var SDK_VERSION = "0.1.6";
|
|
47
50
|
export {
|
|
48
51
|
InSitue,
|
|
49
52
|
InSitueCapture,
|
|
53
|
+
SDK_VERSION,
|
|
50
54
|
mountCaptureOnly,
|
|
51
55
|
mountInSitue
|
|
52
56
|
};
|
package/dist/overlay.js
CHANGED
package/package.json
CHANGED