qapture2 0.7.2 → 0.7.4
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/README.md +34 -4
- package/dist/{chunk-CIFJMD2B.cjs → chunk-7WHQBMVP.cjs} +150 -56
- package/dist/{chunk-NVFFN7SC.js → chunk-ZAWR5VJR.js} +150 -56
- package/dist/index.cjs +5 -5
- package/dist/index.js +1 -1
- package/dist/next.cjs +4 -4
- package/dist/next.js +1 -1
- package/dist/standalone.cjs +2 -2
- package/dist/standalone.js +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -326,10 +326,40 @@ failure with nothing on screen to reveal it.
|
|
|
326
326
|
|
|
327
327
|
Captures now render the union of the viewport and the selection, so an element
|
|
328
328
|
that leaves the screen in any direction is rendered whole, up to 4000px per
|
|
329
|
-
side (past a
|
|
330
|
-
The exact engine can't photograph off-screen pixels, so there the
|
|
331
|
-
trimmed to the visible part instead — cropped, never displaced.
|
|
332
|
-
element-capture-test` measures all
|
|
329
|
+
side (past a ~64 MB device-pixel render budget the scale drops, not the
|
|
330
|
+
framing). The exact engine can't photograph off-screen pixels, so there the
|
|
331
|
+
selection is trimmed to the visible part instead — cropped, never displaced.
|
|
332
|
+
`npm run element-capture-test` measures all four cases.
|
|
333
|
+
|
|
334
|
+
**v0.7.3 corrected the half of that which was wrong.** Chasing an element's
|
|
335
|
+
whole box is only right when the whole box is *drawn*. Inside a scroll
|
|
336
|
+
container it isn't: a dashboard scrolls an inner `overflow:auto` box, so a
|
|
337
|
+
3000px column inside a 700px box is 700px of pixels and 2300px of nothing.
|
|
338
|
+
0.7.2 rendered the nothing — measured at 23.3% element, 76.7% empty page, with
|
|
339
|
+
the real content squeezed from 1040px wide to 312px by the long-edge cap.
|
|
340
|
+
|
|
341
|
+
Captures are now clipped to what the browser actually paints: the element's box
|
|
342
|
+
intersected with every ancestor that clips it, on either axis, up to `<html>`.
|
|
343
|
+
The viewport is deliberately not a clipper, so a long form on an ordinary
|
|
344
|
+
scrolling page still captures in full. Same fixture after: 100% element, full
|
|
345
|
+
1040×1400. The hover outline is clipped identically, so what you highlight is
|
|
346
|
+
what you get.
|
|
347
|
+
|
|
348
|
+
### "The screenshot looks simulated"
|
|
349
|
+
|
|
350
|
+
Because by default it is. The DOM engine re-draws your page; fonts shift,
|
|
351
|
+
shadows and gradients flatten, `<canvas>` and video come out blank. From
|
|
352
|
+
v0.7.3 a redrawn capture says so under the preview and offers a one-tap **Use
|
|
353
|
+
real screenshots**, which grants tab-share and re-shoots the same selection
|
|
354
|
+
with the exact engine below.
|
|
355
|
+
|
|
356
|
+
That upgrade is Chromium-only, because it depends on `preferCurrentTab`. On
|
|
357
|
+
Safari and Firefox the redraw is the only engine there is — so from v0.7.4 the
|
|
358
|
+
card says so outright and points you at Chrome, rather than leaving you to
|
|
359
|
+
conclude the tool is broken. **If your app draws anything with inline SVG, a
|
|
360
|
+
`<canvas>`, or video, do your screenshot QA in Chrome.** A redraw will render
|
|
361
|
+
an SVG chart as bare outlines and a canvas as a blank box, every time, in any
|
|
362
|
+
tool built this way.
|
|
333
363
|
|
|
334
364
|
### `exact` — opt-in, pixel-for-pixel
|
|
335
365
|
|
|
@@ -1782,6 +1782,9 @@ var STR = {
|
|
|
1782
1782
|
expected_label: "Expected",
|
|
1783
1783
|
exact_label: "Pixel-exact shots",
|
|
1784
1784
|
exact_hint: "Screenshots become a real photo of the tab instead of a redraw. Asks once to share this tab; nothing leaves your device.",
|
|
1785
|
+
redraw_notice: "This is a redraw of the page, not a real photo.",
|
|
1786
|
+
redraw_action: "Use real screenshots",
|
|
1787
|
+
redraw_no_engine: "This browser cannot photograph a tab, so charts and canvases may come out wrong. Open the app in Chrome, Edge or Brave for true screenshots.",
|
|
1785
1788
|
exact_on: "Pixel-exact screenshots on",
|
|
1786
1789
|
exact_off: "Back to redrawn screenshots",
|
|
1787
1790
|
exact_declined: "Staying on redrawn screenshots",
|
|
@@ -1976,6 +1979,9 @@ var STR = {
|
|
|
1976
1979
|
expected_label: "\u0627\u0644\u0645\u062A\u0648\u0642\u0639",
|
|
1977
1980
|
exact_label: "\u0644\u0642\u0637\u0627\u062A \u0645\u0637\u0627\u0628\u0642\u0629 \u062A\u0645\u0627\u0645\u064B\u0627",
|
|
1978
1981
|
exact_hint: "\u062A\u0635\u0628\u062D \u0627\u0644\u0644\u0642\u0637\u0629 \u0635\u0648\u0631\u0629 \u062D\u0642\u064A\u0642\u064A\u0629 \u0644\u0644\u062A\u0628\u0648\u064A\u0628 \u0628\u062F\u0644 \u0625\u0639\u0627\u062F\u0629 \u0631\u0633\u0645\u0647. \u064A\u064F\u0637\u0644\u0628 \u0627\u0644\u0625\u0630\u0646 \u0645\u0631\u0629 \u0648\u0627\u062D\u062F\u0629\u060C \u0648\u0644\u0627 \u0634\u064A\u0621 \u064A\u063A\u0627\u062F\u0631 \u062C\u0647\u0627\u0632\u0643.",
|
|
1982
|
+
redraw_notice: "\u0647\u0630\u0647 \u0625\u0639\u0627\u062F\u0629 \u0631\u0633\u0645 \u0644\u0644\u0635\u0641\u062D\u0629\u060C \u0648\u0644\u064A\u0633\u062A \u0635\u0648\u0631\u0629 \u062D\u0642\u064A\u0642\u064A\u0629.",
|
|
1983
|
+
redraw_action: "\u0627\u0633\u062A\u062E\u062F\u0645 \u0644\u0642\u0637\u0627\u062A \u062D\u0642\u064A\u0642\u064A\u0629",
|
|
1984
|
+
redraw_no_engine: "\u0644\u0627 \u064A\u0633\u062A\u0637\u064A\u0639 \u0647\u0630\u0627 \u0627\u0644\u0645\u062A\u0635\u0641\u062D \u062A\u0635\u0648\u064A\u0631 \u0627\u0644\u062A\u0628\u0648\u064A\u0628\u060C \u0644\u0630\u0627 \u0642\u062F \u062A\u0638\u0647\u0631 \u0627\u0644\u0645\u062E\u0637\u0637\u0627\u062A \u0648\u0627\u0644\u0644\u0648\u062D\u0627\u062A \u0628\u0634\u0643\u0644 \u062E\u0627\u0637\u0626. \u0627\u0641\u062A\u062D \u0627\u0644\u062A\u0637\u0628\u064A\u0642 \u0641\u064A Chrome \u0623\u0648 Edge \u0623\u0648 Brave \u0644\u0644\u062D\u0635\u0648\u0644 \u0639\u0644\u0649 \u0644\u0642\u0637\u0627\u062A \u062D\u0642\u064A\u0642\u064A\u0629.",
|
|
1979
1985
|
exact_on: "\u062A\u0645 \u062A\u0641\u0639\u064A\u0644 \u0627\u0644\u0644\u0642\u0637\u0627\u062A \u0627\u0644\u0645\u0637\u0627\u0628\u0642\u0629",
|
|
1980
1986
|
exact_off: "\u0627\u0644\u0639\u0648\u062F\u0629 \u0625\u0644\u0649 \u0627\u0644\u0644\u0642\u0637\u0627\u062A \u0627\u0644\u0645\u064F\u0639\u0627\u062F \u0631\u0633\u0645\u0647\u0627",
|
|
1981
1987
|
exact_declined: "\u0633\u0646\u0628\u0642\u0649 \u0639\u0644\u0649 \u0627\u0644\u0644\u0642\u0637\u0627\u062A \u0627\u0644\u0645\u064F\u0639\u0627\u062F \u0631\u0633\u0645\u0647\u0627",
|
|
@@ -2538,7 +2544,7 @@ var MAX_SHOT_EDGE = 1800;
|
|
|
2538
2544
|
var WEBP_QUALITY = 0.92;
|
|
2539
2545
|
var STUCK_ATTR = "data-qa-stuck";
|
|
2540
2546
|
var MAX_CAPTURE_EDGE = 4e3;
|
|
2541
|
-
var
|
|
2547
|
+
var MAX_RENDER_DEVICE_PIXELS = 16e6;
|
|
2542
2548
|
function withTimeout(promise, ms) {
|
|
2543
2549
|
let timer;
|
|
2544
2550
|
return Promise.race([
|
|
@@ -2710,6 +2716,39 @@ function viewportSize() {
|
|
|
2710
2716
|
vh: document.documentElement.clientHeight || window.innerHeight
|
|
2711
2717
|
};
|
|
2712
2718
|
}
|
|
2719
|
+
function clipToPaintedArea(el, rect) {
|
|
2720
|
+
let left = rect.left;
|
|
2721
|
+
let top = rect.top;
|
|
2722
|
+
let right = rect.left + rect.width;
|
|
2723
|
+
let bottom = rect.top + rect.height;
|
|
2724
|
+
let node = el.parentElement;
|
|
2725
|
+
while (node) {
|
|
2726
|
+
let style;
|
|
2727
|
+
try {
|
|
2728
|
+
style = getComputedStyle(node);
|
|
2729
|
+
} catch {
|
|
2730
|
+
break;
|
|
2731
|
+
}
|
|
2732
|
+
const clipsX = style.overflowX !== "visible";
|
|
2733
|
+
const clipsY = style.overflowY !== "visible";
|
|
2734
|
+
if (clipsX || clipsY) {
|
|
2735
|
+
const b = node.getBoundingClientRect();
|
|
2736
|
+
const padLeft = b.left + node.clientLeft;
|
|
2737
|
+
const padTop = b.top + node.clientTop;
|
|
2738
|
+
if (clipsX) {
|
|
2739
|
+
left = Math.max(left, padLeft);
|
|
2740
|
+
right = Math.min(right, padLeft + node.clientWidth);
|
|
2741
|
+
}
|
|
2742
|
+
if (clipsY) {
|
|
2743
|
+
top = Math.max(top, padTop);
|
|
2744
|
+
bottom = Math.min(bottom, padTop + node.clientHeight);
|
|
2745
|
+
}
|
|
2746
|
+
}
|
|
2747
|
+
node = node.parentElement;
|
|
2748
|
+
}
|
|
2749
|
+
if (right - left < 2 || bottom - top < 2) return rect;
|
|
2750
|
+
return { left, top, width: right - left, height: bottom - top };
|
|
2751
|
+
}
|
|
2713
2752
|
function intersectViewport(rect) {
|
|
2714
2753
|
const { vw, vh } = viewportSize();
|
|
2715
2754
|
const left = Math.max(0, rect.left);
|
|
@@ -2746,9 +2785,10 @@ async function captureViaDom(rect, sx, sy, aggressiveColors = false) {
|
|
|
2746
2785
|
const { vw, vh } = viewportSize();
|
|
2747
2786
|
const plan = planRender(rect, sx, sy, vw, vh);
|
|
2748
2787
|
let scale = Math.min(window.devicePixelRatio || 1, 2);
|
|
2749
|
-
const budget = vw * vh * MAX_RENDER_VIEWPORTS;
|
|
2750
2788
|
const area = plan.render.width * plan.render.height;
|
|
2751
|
-
if (area
|
|
2789
|
+
if (area * scale * scale > MAX_RENDER_DEVICE_PIXELS) {
|
|
2790
|
+
scale = Math.sqrt(MAX_RENDER_DEVICE_PIXELS / area);
|
|
2791
|
+
}
|
|
2752
2792
|
const marked = markStuckElements();
|
|
2753
2793
|
try {
|
|
2754
2794
|
const full = await withTimeout(
|
|
@@ -8880,6 +8920,7 @@ function CaptureMode() {
|
|
|
8880
8920
|
const [candidate, setCandidate] = React.useState(null);
|
|
8881
8921
|
const [regionMode, setRegionMode] = React.useState(false);
|
|
8882
8922
|
const [shot, setShot] = React.useState(null);
|
|
8923
|
+
const [shotEngine, setShotEngine] = React.useState(null);
|
|
8883
8924
|
const [shotUrl, setShotUrl] = React.useState(null);
|
|
8884
8925
|
const [capturing, setCapturing] = React.useState(false);
|
|
8885
8926
|
const [captureError, setCaptureError] = React.useState(false);
|
|
@@ -8922,6 +8963,7 @@ function CaptureMode() {
|
|
|
8922
8963
|
return;
|
|
8923
8964
|
}
|
|
8924
8965
|
setCaptureError(outcome.status === "failed");
|
|
8966
|
+
setShotEngine(outcome.status === "ok" ? outcome.engine : null);
|
|
8925
8967
|
setShot(blob);
|
|
8926
8968
|
setShotUrl((old) => {
|
|
8927
8969
|
if (old) URL.revokeObjectURL(old);
|
|
@@ -8986,7 +9028,9 @@ function CaptureMode() {
|
|
|
8986
9028
|
}
|
|
8987
9029
|
const r = el.getBoundingClientRect();
|
|
8988
9030
|
setHover({
|
|
8989
|
-
|
|
9031
|
+
// Highlight only what will actually be captured, so the outline is a
|
|
9032
|
+
// promise the screenshot can keep.
|
|
9033
|
+
rect: clipToPaintedArea(el, { top: r.top, left: r.left, width: r.width, height: r.height }),
|
|
8990
9034
|
selector: getStableSelector(el)
|
|
8991
9035
|
});
|
|
8992
9036
|
}
|
|
@@ -9033,7 +9077,10 @@ function CaptureMode() {
|
|
|
9033
9077
|
const r = el.getBoundingClientRect();
|
|
9034
9078
|
const sel = {
|
|
9035
9079
|
kind: "element",
|
|
9036
|
-
|
|
9080
|
+
// What the browser PAINTS of this element, not its full bounding box —
|
|
9081
|
+
// a row inside a scrolled table is only ever drawn where the table shows
|
|
9082
|
+
// it. See clipToPaintedArea().
|
|
9083
|
+
rect: clipToPaintedArea(el, { top: r.top, left: r.left, width: r.width, height: r.height }),
|
|
9037
9084
|
selector: getStableSelector(el),
|
|
9038
9085
|
text: (el.innerText ?? el.textContent ?? "").trim().slice(0, 120),
|
|
9039
9086
|
tagName: el.tagName.toLowerCase()
|
|
@@ -9644,7 +9691,7 @@ function CaptureMode() {
|
|
|
9644
9691
|
)
|
|
9645
9692
|
] }),
|
|
9646
9693
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "qa-space-y-2 qa-p-3", children: [
|
|
9647
|
-
/* @__PURE__ */ jsxRuntime.
|
|
9694
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9648
9695
|
"div",
|
|
9649
9696
|
{
|
|
9650
9697
|
className: "qa-flex qa-min-h-16 qa-items-center qa-justify-center qa-rounded-lg qa-border",
|
|
@@ -9652,66 +9699,113 @@ function CaptureMode() {
|
|
|
9652
9699
|
borderColor: "var(--qa-border-subtle)",
|
|
9653
9700
|
background: "var(--qa-surface-0)"
|
|
9654
9701
|
},
|
|
9655
|
-
children:
|
|
9656
|
-
/* @__PURE__ */ jsxRuntime.
|
|
9657
|
-
|
|
9658
|
-
|
|
9659
|
-
|
|
9660
|
-
|
|
9661
|
-
|
|
9662
|
-
|
|
9663
|
-
|
|
9664
|
-
|
|
9665
|
-
|
|
9666
|
-
|
|
9667
|
-
|
|
9668
|
-
|
|
9669
|
-
|
|
9670
|
-
|
|
9671
|
-
|
|
9672
|
-
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9702
|
+
children: [
|
|
9703
|
+
capturing ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "qa-flex qa-items-center qa-gap-2 qa-py-4 qa-text-xs qa-text-accent", children: [
|
|
9704
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "Loader2", size: 16, className: "qa-animate-spin" }),
|
|
9705
|
+
t("capturing")
|
|
9706
|
+
] }) : shotUrl ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9707
|
+
"button",
|
|
9708
|
+
{
|
|
9709
|
+
type: "button",
|
|
9710
|
+
onClick: () => setDrawing(true),
|
|
9711
|
+
title: t("draw_label"),
|
|
9712
|
+
"aria-label": t("draw_label"),
|
|
9713
|
+
className: "qa-relative qa-group qa-tap",
|
|
9714
|
+
style: { background: "transparent", border: "none", padding: 0, cursor: "pointer" },
|
|
9715
|
+
children: [
|
|
9716
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9717
|
+
"img",
|
|
9718
|
+
{
|
|
9719
|
+
src: shotUrl,
|
|
9720
|
+
alt: "capture",
|
|
9721
|
+
className: "qa-max-h-32 qa-rounded-md"
|
|
9722
|
+
}
|
|
9723
|
+
),
|
|
9724
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9725
|
+
"span",
|
|
9726
|
+
{
|
|
9727
|
+
className: "qa-absolute qa-inline-flex qa-items-center qa-gap-1 qa-rounded-full qa-px-1.5 qa-py-0.5 qa-text-10",
|
|
9728
|
+
style: {
|
|
9729
|
+
bottom: 4,
|
|
9730
|
+
insetInlineEnd: 4,
|
|
9731
|
+
background: "var(--qa-surface-1)",
|
|
9732
|
+
color: "var(--qa-ink-hi)",
|
|
9733
|
+
border: "1px solid var(--qa-border-subtle)"
|
|
9734
|
+
},
|
|
9735
|
+
children: [
|
|
9736
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "Pencil", size: 10 }),
|
|
9737
|
+
t("draw_label")
|
|
9738
|
+
]
|
|
9739
|
+
}
|
|
9740
|
+
)
|
|
9741
|
+
]
|
|
9742
|
+
}
|
|
9743
|
+
) : captureError ? (
|
|
9744
|
+
// The render broke rather than being skipped — offer a retry
|
|
9745
|
+
// against the same selection instead of a dead-end message.
|
|
9746
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "qa-flex qa-flex-col qa-items-center qa-gap-2 qa-py-3", children: [
|
|
9747
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "qa-text-xs qa-text-red-600", children: t("capture_failed") }),
|
|
9676
9748
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9677
|
-
"
|
|
9749
|
+
"button",
|
|
9678
9750
|
{
|
|
9679
|
-
|
|
9680
|
-
|
|
9681
|
-
|
|
9682
|
-
|
|
9683
|
-
background: "var(--qa-surface-1)",
|
|
9684
|
-
color: "var(--qa-ink-hi)",
|
|
9685
|
-
border: "1px solid var(--qa-border-subtle)"
|
|
9686
|
-
},
|
|
9751
|
+
type: "button",
|
|
9752
|
+
onClick: () => selection && void runCapture(selection.rect),
|
|
9753
|
+
className: "qa-tap qa-inline-flex qa-items-center qa-gap-1.5 qa-rounded-md qa-border qa-border-subtle qa-px-2 qa-py-1 qa-text-xs qa-text-mid qa-focus-ring",
|
|
9754
|
+
style: { background: "transparent", cursor: "pointer" },
|
|
9687
9755
|
children: [
|
|
9688
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "
|
|
9689
|
-
t("
|
|
9756
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "RotateCcw", size: 13 }),
|
|
9757
|
+
t("retry")
|
|
9690
9758
|
]
|
|
9691
9759
|
}
|
|
9692
9760
|
)
|
|
9693
|
-
]
|
|
9694
|
-
}
|
|
9695
|
-
|
|
9696
|
-
|
|
9697
|
-
|
|
9698
|
-
|
|
9699
|
-
|
|
9761
|
+
] })
|
|
9762
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "qa-py-4 qa-text-xs qa-text-slate-400", children: t("no_shot") }),
|
|
9763
|
+
shotUrl && shotEngine === "dom" && (exactShots.status !== "live" && exactShots.supported ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9764
|
+
"span",
|
|
9765
|
+
{
|
|
9766
|
+
"data-qa-redraw-offer": "true",
|
|
9767
|
+
className: "qa-mt-1.5 qa-flex qa-items-center qa-justify-center qa-flex-wrap qa-gap-1.5 qa-text-10 qa-text-mid",
|
|
9768
|
+
children: [
|
|
9769
|
+
t("redraw_notice"),
|
|
9770
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9771
|
+
"button",
|
|
9772
|
+
{
|
|
9773
|
+
type: "button",
|
|
9774
|
+
onClick: () => void (async () => {
|
|
9775
|
+
const granted = await enableExactShots();
|
|
9776
|
+
if (granted && selection) void runCapture(selection.rect);
|
|
9777
|
+
})(),
|
|
9778
|
+
title: t("exact_hint"),
|
|
9779
|
+
className: "qa-tap qa-inline-flex qa-items-center qa-gap-1 qa-rounded-full qa-border qa-border-subtle qa-px-1.5 qa-py-0.5 qa-text-10 qa-text-hi qa-focus-ring",
|
|
9780
|
+
style: { background: "transparent", cursor: "pointer" },
|
|
9781
|
+
children: [
|
|
9782
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "Camera", size: 10 }),
|
|
9783
|
+
t("redraw_action")
|
|
9784
|
+
]
|
|
9785
|
+
}
|
|
9786
|
+
)
|
|
9787
|
+
]
|
|
9788
|
+
}
|
|
9789
|
+
) : !exactShots.supported ? (
|
|
9790
|
+
// Safari and Firefox have no way to photograph the tab, so
|
|
9791
|
+
// there is nothing to offer — but saying NOTHING was the real
|
|
9792
|
+
// failure. A tester watching an SVG chart come back as bare
|
|
9793
|
+
// outlines concludes the tool is broken and files it as a bug,
|
|
9794
|
+
// over and over. Name the limit and name the way out.
|
|
9700
9795
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9701
|
-
"
|
|
9796
|
+
"span",
|
|
9702
9797
|
{
|
|
9703
|
-
|
|
9704
|
-
|
|
9705
|
-
className: "qa-tap qa-inline-flex qa-items-center qa-gap-1.5 qa-rounded-md qa-border qa-border-subtle qa-px-2 qa-py-1 qa-text-xs qa-text-mid qa-focus-ring",
|
|
9706
|
-
style: { background: "transparent", cursor: "pointer" },
|
|
9798
|
+
"data-qa-redraw-note": "true",
|
|
9799
|
+
className: "qa-mt-1.5 qa-block qa-text-center qa-text-10 qa-text-mid",
|
|
9707
9800
|
children: [
|
|
9708
|
-
|
|
9709
|
-
|
|
9801
|
+
t("redraw_notice"),
|
|
9802
|
+
" ",
|
|
9803
|
+
t("redraw_no_engine")
|
|
9710
9804
|
]
|
|
9711
9805
|
}
|
|
9712
9806
|
)
|
|
9713
|
-
|
|
9714
|
-
|
|
9807
|
+
) : null)
|
|
9808
|
+
]
|
|
9715
9809
|
}
|
|
9716
9810
|
),
|
|
9717
9811
|
/* @__PURE__ */ jsxRuntime.jsx(LocationReveal, { target: selection }),
|
|
@@ -10005,5 +10099,5 @@ function Qapture({ config }) {
|
|
|
10005
10099
|
exports.Qapture = Qapture;
|
|
10006
10100
|
exports.deleteQaDatabase = deleteQaDatabase;
|
|
10007
10101
|
exports.initQaStudio = initQaStudio;
|
|
10008
|
-
//# sourceMappingURL=chunk-
|
|
10009
|
-
//# sourceMappingURL=chunk-
|
|
10102
|
+
//# sourceMappingURL=chunk-7WHQBMVP.cjs.map
|
|
10103
|
+
//# sourceMappingURL=chunk-7WHQBMVP.cjs.map
|
|
@@ -1775,6 +1775,9 @@ var STR = {
|
|
|
1775
1775
|
expected_label: "Expected",
|
|
1776
1776
|
exact_label: "Pixel-exact shots",
|
|
1777
1777
|
exact_hint: "Screenshots become a real photo of the tab instead of a redraw. Asks once to share this tab; nothing leaves your device.",
|
|
1778
|
+
redraw_notice: "This is a redraw of the page, not a real photo.",
|
|
1779
|
+
redraw_action: "Use real screenshots",
|
|
1780
|
+
redraw_no_engine: "This browser cannot photograph a tab, so charts and canvases may come out wrong. Open the app in Chrome, Edge or Brave for true screenshots.",
|
|
1778
1781
|
exact_on: "Pixel-exact screenshots on",
|
|
1779
1782
|
exact_off: "Back to redrawn screenshots",
|
|
1780
1783
|
exact_declined: "Staying on redrawn screenshots",
|
|
@@ -1969,6 +1972,9 @@ var STR = {
|
|
|
1969
1972
|
expected_label: "\u0627\u0644\u0645\u062A\u0648\u0642\u0639",
|
|
1970
1973
|
exact_label: "\u0644\u0642\u0637\u0627\u062A \u0645\u0637\u0627\u0628\u0642\u0629 \u062A\u0645\u0627\u0645\u064B\u0627",
|
|
1971
1974
|
exact_hint: "\u062A\u0635\u0628\u062D \u0627\u0644\u0644\u0642\u0637\u0629 \u0635\u0648\u0631\u0629 \u062D\u0642\u064A\u0642\u064A\u0629 \u0644\u0644\u062A\u0628\u0648\u064A\u0628 \u0628\u062F\u0644 \u0625\u0639\u0627\u062F\u0629 \u0631\u0633\u0645\u0647. \u064A\u064F\u0637\u0644\u0628 \u0627\u0644\u0625\u0630\u0646 \u0645\u0631\u0629 \u0648\u0627\u062D\u062F\u0629\u060C \u0648\u0644\u0627 \u0634\u064A\u0621 \u064A\u063A\u0627\u062F\u0631 \u062C\u0647\u0627\u0632\u0643.",
|
|
1975
|
+
redraw_notice: "\u0647\u0630\u0647 \u0625\u0639\u0627\u062F\u0629 \u0631\u0633\u0645 \u0644\u0644\u0635\u0641\u062D\u0629\u060C \u0648\u0644\u064A\u0633\u062A \u0635\u0648\u0631\u0629 \u062D\u0642\u064A\u0642\u064A\u0629.",
|
|
1976
|
+
redraw_action: "\u0627\u0633\u062A\u062E\u062F\u0645 \u0644\u0642\u0637\u0627\u062A \u062D\u0642\u064A\u0642\u064A\u0629",
|
|
1977
|
+
redraw_no_engine: "\u0644\u0627 \u064A\u0633\u062A\u0637\u064A\u0639 \u0647\u0630\u0627 \u0627\u0644\u0645\u062A\u0635\u0641\u062D \u062A\u0635\u0648\u064A\u0631 \u0627\u0644\u062A\u0628\u0648\u064A\u0628\u060C \u0644\u0630\u0627 \u0642\u062F \u062A\u0638\u0647\u0631 \u0627\u0644\u0645\u062E\u0637\u0637\u0627\u062A \u0648\u0627\u0644\u0644\u0648\u062D\u0627\u062A \u0628\u0634\u0643\u0644 \u062E\u0627\u0637\u0626. \u0627\u0641\u062A\u062D \u0627\u0644\u062A\u0637\u0628\u064A\u0642 \u0641\u064A Chrome \u0623\u0648 Edge \u0623\u0648 Brave \u0644\u0644\u062D\u0635\u0648\u0644 \u0639\u0644\u0649 \u0644\u0642\u0637\u0627\u062A \u062D\u0642\u064A\u0642\u064A\u0629.",
|
|
1972
1978
|
exact_on: "\u062A\u0645 \u062A\u0641\u0639\u064A\u0644 \u0627\u0644\u0644\u0642\u0637\u0627\u062A \u0627\u0644\u0645\u0637\u0627\u0628\u0642\u0629",
|
|
1973
1979
|
exact_off: "\u0627\u0644\u0639\u0648\u062F\u0629 \u0625\u0644\u0649 \u0627\u0644\u0644\u0642\u0637\u0627\u062A \u0627\u0644\u0645\u064F\u0639\u0627\u062F \u0631\u0633\u0645\u0647\u0627",
|
|
1974
1980
|
exact_declined: "\u0633\u0646\u0628\u0642\u0649 \u0639\u0644\u0649 \u0627\u0644\u0644\u0642\u0637\u0627\u062A \u0627\u0644\u0645\u064F\u0639\u0627\u062F \u0631\u0633\u0645\u0647\u0627",
|
|
@@ -2531,7 +2537,7 @@ var MAX_SHOT_EDGE = 1800;
|
|
|
2531
2537
|
var WEBP_QUALITY = 0.92;
|
|
2532
2538
|
var STUCK_ATTR = "data-qa-stuck";
|
|
2533
2539
|
var MAX_CAPTURE_EDGE = 4e3;
|
|
2534
|
-
var
|
|
2540
|
+
var MAX_RENDER_DEVICE_PIXELS = 16e6;
|
|
2535
2541
|
function withTimeout(promise, ms) {
|
|
2536
2542
|
let timer;
|
|
2537
2543
|
return Promise.race([
|
|
@@ -2703,6 +2709,39 @@ function viewportSize() {
|
|
|
2703
2709
|
vh: document.documentElement.clientHeight || window.innerHeight
|
|
2704
2710
|
};
|
|
2705
2711
|
}
|
|
2712
|
+
function clipToPaintedArea(el, rect) {
|
|
2713
|
+
let left = rect.left;
|
|
2714
|
+
let top = rect.top;
|
|
2715
|
+
let right = rect.left + rect.width;
|
|
2716
|
+
let bottom = rect.top + rect.height;
|
|
2717
|
+
let node = el.parentElement;
|
|
2718
|
+
while (node) {
|
|
2719
|
+
let style;
|
|
2720
|
+
try {
|
|
2721
|
+
style = getComputedStyle(node);
|
|
2722
|
+
} catch {
|
|
2723
|
+
break;
|
|
2724
|
+
}
|
|
2725
|
+
const clipsX = style.overflowX !== "visible";
|
|
2726
|
+
const clipsY = style.overflowY !== "visible";
|
|
2727
|
+
if (clipsX || clipsY) {
|
|
2728
|
+
const b = node.getBoundingClientRect();
|
|
2729
|
+
const padLeft = b.left + node.clientLeft;
|
|
2730
|
+
const padTop = b.top + node.clientTop;
|
|
2731
|
+
if (clipsX) {
|
|
2732
|
+
left = Math.max(left, padLeft);
|
|
2733
|
+
right = Math.min(right, padLeft + node.clientWidth);
|
|
2734
|
+
}
|
|
2735
|
+
if (clipsY) {
|
|
2736
|
+
top = Math.max(top, padTop);
|
|
2737
|
+
bottom = Math.min(bottom, padTop + node.clientHeight);
|
|
2738
|
+
}
|
|
2739
|
+
}
|
|
2740
|
+
node = node.parentElement;
|
|
2741
|
+
}
|
|
2742
|
+
if (right - left < 2 || bottom - top < 2) return rect;
|
|
2743
|
+
return { left, top, width: right - left, height: bottom - top };
|
|
2744
|
+
}
|
|
2706
2745
|
function intersectViewport(rect) {
|
|
2707
2746
|
const { vw, vh } = viewportSize();
|
|
2708
2747
|
const left = Math.max(0, rect.left);
|
|
@@ -2739,9 +2778,10 @@ async function captureViaDom(rect, sx, sy, aggressiveColors = false) {
|
|
|
2739
2778
|
const { vw, vh } = viewportSize();
|
|
2740
2779
|
const plan = planRender(rect, sx, sy, vw, vh);
|
|
2741
2780
|
let scale = Math.min(window.devicePixelRatio || 1, 2);
|
|
2742
|
-
const budget = vw * vh * MAX_RENDER_VIEWPORTS;
|
|
2743
2781
|
const area = plan.render.width * plan.render.height;
|
|
2744
|
-
if (area
|
|
2782
|
+
if (area * scale * scale > MAX_RENDER_DEVICE_PIXELS) {
|
|
2783
|
+
scale = Math.sqrt(MAX_RENDER_DEVICE_PIXELS / area);
|
|
2784
|
+
}
|
|
2745
2785
|
const marked = markStuckElements();
|
|
2746
2786
|
try {
|
|
2747
2787
|
const full = await withTimeout(
|
|
@@ -8873,6 +8913,7 @@ function CaptureMode() {
|
|
|
8873
8913
|
const [candidate, setCandidate] = useState(null);
|
|
8874
8914
|
const [regionMode, setRegionMode] = useState(false);
|
|
8875
8915
|
const [shot, setShot] = useState(null);
|
|
8916
|
+
const [shotEngine, setShotEngine] = useState(null);
|
|
8876
8917
|
const [shotUrl, setShotUrl] = useState(null);
|
|
8877
8918
|
const [capturing, setCapturing] = useState(false);
|
|
8878
8919
|
const [captureError, setCaptureError] = useState(false);
|
|
@@ -8915,6 +8956,7 @@ function CaptureMode() {
|
|
|
8915
8956
|
return;
|
|
8916
8957
|
}
|
|
8917
8958
|
setCaptureError(outcome.status === "failed");
|
|
8959
|
+
setShotEngine(outcome.status === "ok" ? outcome.engine : null);
|
|
8918
8960
|
setShot(blob);
|
|
8919
8961
|
setShotUrl((old) => {
|
|
8920
8962
|
if (old) URL.revokeObjectURL(old);
|
|
@@ -8979,7 +9021,9 @@ function CaptureMode() {
|
|
|
8979
9021
|
}
|
|
8980
9022
|
const r = el.getBoundingClientRect();
|
|
8981
9023
|
setHover({
|
|
8982
|
-
|
|
9024
|
+
// Highlight only what will actually be captured, so the outline is a
|
|
9025
|
+
// promise the screenshot can keep.
|
|
9026
|
+
rect: clipToPaintedArea(el, { top: r.top, left: r.left, width: r.width, height: r.height }),
|
|
8983
9027
|
selector: getStableSelector(el)
|
|
8984
9028
|
});
|
|
8985
9029
|
}
|
|
@@ -9026,7 +9070,10 @@ function CaptureMode() {
|
|
|
9026
9070
|
const r = el.getBoundingClientRect();
|
|
9027
9071
|
const sel = {
|
|
9028
9072
|
kind: "element",
|
|
9029
|
-
|
|
9073
|
+
// What the browser PAINTS of this element, not its full bounding box —
|
|
9074
|
+
// a row inside a scrolled table is only ever drawn where the table shows
|
|
9075
|
+
// it. See clipToPaintedArea().
|
|
9076
|
+
rect: clipToPaintedArea(el, { top: r.top, left: r.left, width: r.width, height: r.height }),
|
|
9030
9077
|
selector: getStableSelector(el),
|
|
9031
9078
|
text: (el.innerText ?? el.textContent ?? "").trim().slice(0, 120),
|
|
9032
9079
|
tagName: el.tagName.toLowerCase()
|
|
@@ -9637,7 +9684,7 @@ function CaptureMode() {
|
|
|
9637
9684
|
)
|
|
9638
9685
|
] }),
|
|
9639
9686
|
/* @__PURE__ */ jsxs("div", { className: "qa-space-y-2 qa-p-3", children: [
|
|
9640
|
-
/* @__PURE__ */
|
|
9687
|
+
/* @__PURE__ */ jsxs(
|
|
9641
9688
|
"div",
|
|
9642
9689
|
{
|
|
9643
9690
|
className: "qa-flex qa-min-h-16 qa-items-center qa-justify-center qa-rounded-lg qa-border",
|
|
@@ -9645,66 +9692,113 @@ function CaptureMode() {
|
|
|
9645
9692
|
borderColor: "var(--qa-border-subtle)",
|
|
9646
9693
|
background: "var(--qa-surface-0)"
|
|
9647
9694
|
},
|
|
9648
|
-
children:
|
|
9649
|
-
/* @__PURE__ */
|
|
9650
|
-
|
|
9651
|
-
|
|
9652
|
-
|
|
9653
|
-
|
|
9654
|
-
|
|
9655
|
-
|
|
9656
|
-
|
|
9657
|
-
|
|
9658
|
-
|
|
9659
|
-
|
|
9660
|
-
|
|
9661
|
-
|
|
9662
|
-
|
|
9663
|
-
|
|
9664
|
-
|
|
9665
|
-
|
|
9666
|
-
|
|
9667
|
-
|
|
9668
|
-
|
|
9695
|
+
children: [
|
|
9696
|
+
capturing ? /* @__PURE__ */ jsxs("span", { className: "qa-flex qa-items-center qa-gap-2 qa-py-4 qa-text-xs qa-text-accent", children: [
|
|
9697
|
+
/* @__PURE__ */ jsx(Icon, { name: "Loader2", size: 16, className: "qa-animate-spin" }),
|
|
9698
|
+
t("capturing")
|
|
9699
|
+
] }) : shotUrl ? /* @__PURE__ */ jsxs(
|
|
9700
|
+
"button",
|
|
9701
|
+
{
|
|
9702
|
+
type: "button",
|
|
9703
|
+
onClick: () => setDrawing(true),
|
|
9704
|
+
title: t("draw_label"),
|
|
9705
|
+
"aria-label": t("draw_label"),
|
|
9706
|
+
className: "qa-relative qa-group qa-tap",
|
|
9707
|
+
style: { background: "transparent", border: "none", padding: 0, cursor: "pointer" },
|
|
9708
|
+
children: [
|
|
9709
|
+
/* @__PURE__ */ jsx(
|
|
9710
|
+
"img",
|
|
9711
|
+
{
|
|
9712
|
+
src: shotUrl,
|
|
9713
|
+
alt: "capture",
|
|
9714
|
+
className: "qa-max-h-32 qa-rounded-md"
|
|
9715
|
+
}
|
|
9716
|
+
),
|
|
9717
|
+
/* @__PURE__ */ jsxs(
|
|
9718
|
+
"span",
|
|
9719
|
+
{
|
|
9720
|
+
className: "qa-absolute qa-inline-flex qa-items-center qa-gap-1 qa-rounded-full qa-px-1.5 qa-py-0.5 qa-text-10",
|
|
9721
|
+
style: {
|
|
9722
|
+
bottom: 4,
|
|
9723
|
+
insetInlineEnd: 4,
|
|
9724
|
+
background: "var(--qa-surface-1)",
|
|
9725
|
+
color: "var(--qa-ink-hi)",
|
|
9726
|
+
border: "1px solid var(--qa-border-subtle)"
|
|
9727
|
+
},
|
|
9728
|
+
children: [
|
|
9729
|
+
/* @__PURE__ */ jsx(Icon, { name: "Pencil", size: 10 }),
|
|
9730
|
+
t("draw_label")
|
|
9731
|
+
]
|
|
9732
|
+
}
|
|
9733
|
+
)
|
|
9734
|
+
]
|
|
9735
|
+
}
|
|
9736
|
+
) : captureError ? (
|
|
9737
|
+
// The render broke rather than being skipped — offer a retry
|
|
9738
|
+
// against the same selection instead of a dead-end message.
|
|
9739
|
+
/* @__PURE__ */ jsxs("span", { className: "qa-flex qa-flex-col qa-items-center qa-gap-2 qa-py-3", children: [
|
|
9740
|
+
/* @__PURE__ */ jsx("span", { className: "qa-text-xs qa-text-red-600", children: t("capture_failed") }),
|
|
9669
9741
|
/* @__PURE__ */ jsxs(
|
|
9670
|
-
"
|
|
9742
|
+
"button",
|
|
9671
9743
|
{
|
|
9672
|
-
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
background: "var(--qa-surface-1)",
|
|
9677
|
-
color: "var(--qa-ink-hi)",
|
|
9678
|
-
border: "1px solid var(--qa-border-subtle)"
|
|
9679
|
-
},
|
|
9744
|
+
type: "button",
|
|
9745
|
+
onClick: () => selection && void runCapture(selection.rect),
|
|
9746
|
+
className: "qa-tap qa-inline-flex qa-items-center qa-gap-1.5 qa-rounded-md qa-border qa-border-subtle qa-px-2 qa-py-1 qa-text-xs qa-text-mid qa-focus-ring",
|
|
9747
|
+
style: { background: "transparent", cursor: "pointer" },
|
|
9680
9748
|
children: [
|
|
9681
|
-
/* @__PURE__ */ jsx(Icon, { name: "
|
|
9682
|
-
t("
|
|
9749
|
+
/* @__PURE__ */ jsx(Icon, { name: "RotateCcw", size: 13 }),
|
|
9750
|
+
t("retry")
|
|
9683
9751
|
]
|
|
9684
9752
|
}
|
|
9685
9753
|
)
|
|
9686
|
-
]
|
|
9687
|
-
}
|
|
9688
|
-
|
|
9689
|
-
|
|
9690
|
-
|
|
9691
|
-
|
|
9692
|
-
|
|
9754
|
+
] })
|
|
9755
|
+
) : /* @__PURE__ */ jsx("span", { className: "qa-py-4 qa-text-xs qa-text-slate-400", children: t("no_shot") }),
|
|
9756
|
+
shotUrl && shotEngine === "dom" && (exactShots.status !== "live" && exactShots.supported ? /* @__PURE__ */ jsxs(
|
|
9757
|
+
"span",
|
|
9758
|
+
{
|
|
9759
|
+
"data-qa-redraw-offer": "true",
|
|
9760
|
+
className: "qa-mt-1.5 qa-flex qa-items-center qa-justify-center qa-flex-wrap qa-gap-1.5 qa-text-10 qa-text-mid",
|
|
9761
|
+
children: [
|
|
9762
|
+
t("redraw_notice"),
|
|
9763
|
+
/* @__PURE__ */ jsxs(
|
|
9764
|
+
"button",
|
|
9765
|
+
{
|
|
9766
|
+
type: "button",
|
|
9767
|
+
onClick: () => void (async () => {
|
|
9768
|
+
const granted = await enableExactShots();
|
|
9769
|
+
if (granted && selection) void runCapture(selection.rect);
|
|
9770
|
+
})(),
|
|
9771
|
+
title: t("exact_hint"),
|
|
9772
|
+
className: "qa-tap qa-inline-flex qa-items-center qa-gap-1 qa-rounded-full qa-border qa-border-subtle qa-px-1.5 qa-py-0.5 qa-text-10 qa-text-hi qa-focus-ring",
|
|
9773
|
+
style: { background: "transparent", cursor: "pointer" },
|
|
9774
|
+
children: [
|
|
9775
|
+
/* @__PURE__ */ jsx(Icon, { name: "Camera", size: 10 }),
|
|
9776
|
+
t("redraw_action")
|
|
9777
|
+
]
|
|
9778
|
+
}
|
|
9779
|
+
)
|
|
9780
|
+
]
|
|
9781
|
+
}
|
|
9782
|
+
) : !exactShots.supported ? (
|
|
9783
|
+
// Safari and Firefox have no way to photograph the tab, so
|
|
9784
|
+
// there is nothing to offer — but saying NOTHING was the real
|
|
9785
|
+
// failure. A tester watching an SVG chart come back as bare
|
|
9786
|
+
// outlines concludes the tool is broken and files it as a bug,
|
|
9787
|
+
// over and over. Name the limit and name the way out.
|
|
9693
9788
|
/* @__PURE__ */ jsxs(
|
|
9694
|
-
"
|
|
9789
|
+
"span",
|
|
9695
9790
|
{
|
|
9696
|
-
|
|
9697
|
-
|
|
9698
|
-
className: "qa-tap qa-inline-flex qa-items-center qa-gap-1.5 qa-rounded-md qa-border qa-border-subtle qa-px-2 qa-py-1 qa-text-xs qa-text-mid qa-focus-ring",
|
|
9699
|
-
style: { background: "transparent", cursor: "pointer" },
|
|
9791
|
+
"data-qa-redraw-note": "true",
|
|
9792
|
+
className: "qa-mt-1.5 qa-block qa-text-center qa-text-10 qa-text-mid",
|
|
9700
9793
|
children: [
|
|
9701
|
-
|
|
9702
|
-
|
|
9794
|
+
t("redraw_notice"),
|
|
9795
|
+
" ",
|
|
9796
|
+
t("redraw_no_engine")
|
|
9703
9797
|
]
|
|
9704
9798
|
}
|
|
9705
9799
|
)
|
|
9706
|
-
|
|
9707
|
-
|
|
9800
|
+
) : null)
|
|
9801
|
+
]
|
|
9708
9802
|
}
|
|
9709
9803
|
),
|
|
9710
9804
|
/* @__PURE__ */ jsx(LocationReveal, { target: selection }),
|
|
@@ -9996,5 +10090,5 @@ function Qapture({ config }) {
|
|
|
9996
10090
|
}
|
|
9997
10091
|
|
|
9998
10092
|
export { Qapture, deleteQaDatabase, initQaStudio };
|
|
9999
|
-
//# sourceMappingURL=chunk-
|
|
10000
|
-
//# sourceMappingURL=chunk-
|
|
10093
|
+
//# sourceMappingURL=chunk-ZAWR5VJR.js.map
|
|
10094
|
+
//# sourceMappingURL=chunk-ZAWR5VJR.js.map
|
package/dist/index.cjs
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunk7WHQBMVP_cjs = require('./chunk-7WHQBMVP.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
Object.defineProperty(exports, "QaStudio", {
|
|
8
8
|
enumerable: true,
|
|
9
|
-
get: function () { return
|
|
9
|
+
get: function () { return chunk7WHQBMVP_cjs.Qapture; }
|
|
10
10
|
});
|
|
11
11
|
Object.defineProperty(exports, "Qapture", {
|
|
12
12
|
enumerable: true,
|
|
13
|
-
get: function () { return
|
|
13
|
+
get: function () { return chunk7WHQBMVP_cjs.Qapture; }
|
|
14
14
|
});
|
|
15
15
|
Object.defineProperty(exports, "deleteQaDatabase", {
|
|
16
16
|
enumerable: true,
|
|
17
|
-
get: function () { return
|
|
17
|
+
get: function () { return chunk7WHQBMVP_cjs.deleteQaDatabase; }
|
|
18
18
|
});
|
|
19
19
|
Object.defineProperty(exports, "initQaStudio", {
|
|
20
20
|
enumerable: true,
|
|
21
|
-
get: function () { return
|
|
21
|
+
get: function () { return chunk7WHQBMVP_cjs.initQaStudio; }
|
|
22
22
|
});
|
|
23
23
|
//# sourceMappingURL=index.cjs.map
|
|
24
24
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.js
CHANGED
package/dist/next.cjs
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var chunk7WHQBMVP_cjs = require('./chunk-7WHQBMVP.cjs');
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
Object.defineProperty(exports, "QaStudio", {
|
|
9
9
|
enumerable: true,
|
|
10
|
-
get: function () { return
|
|
10
|
+
get: function () { return chunk7WHQBMVP_cjs.Qapture; }
|
|
11
11
|
});
|
|
12
12
|
Object.defineProperty(exports, "Qapture", {
|
|
13
13
|
enumerable: true,
|
|
14
|
-
get: function () { return
|
|
14
|
+
get: function () { return chunk7WHQBMVP_cjs.Qapture; }
|
|
15
15
|
});
|
|
16
16
|
Object.defineProperty(exports, "initQaStudio", {
|
|
17
17
|
enumerable: true,
|
|
18
|
-
get: function () { return
|
|
18
|
+
get: function () { return chunk7WHQBMVP_cjs.initQaStudio; }
|
|
19
19
|
});
|
|
20
20
|
//# sourceMappingURL=next.cjs.map
|
|
21
21
|
//# sourceMappingURL=next.cjs.map
|
package/dist/next.js
CHANGED
package/dist/standalone.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunk7WHQBMVP_cjs = require('./chunk-7WHQBMVP.cjs');
|
|
4
4
|
|
|
5
5
|
// src/standalone.ts
|
|
6
6
|
if (typeof window !== "undefined" && typeof customElements !== "undefined" && !customElements.get("qapture-widget")) {
|
|
@@ -38,7 +38,7 @@ if (typeof window !== "undefined" && typeof customElements !== "undefined" && !c
|
|
|
38
38
|
|
|
39
39
|
Object.defineProperty(exports, "initQaStudio", {
|
|
40
40
|
enumerable: true,
|
|
41
|
-
get: function () { return
|
|
41
|
+
get: function () { return chunk7WHQBMVP_cjs.initQaStudio; }
|
|
42
42
|
});
|
|
43
43
|
//# sourceMappingURL=standalone.cjs.map
|
|
44
44
|
//# sourceMappingURL=standalone.cjs.map
|
package/dist/standalone.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qapture2",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.4",
|
|
4
4
|
"description": "Drop-in, AI-aware in-browser QA capture widget. A tester annotates the live app (element/region + auto-screenshot + note), tracks a graded testing journey, and exports a ZIP your own coding agent reads. Ships zero AI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -90,6 +90,7 @@
|
|
|
90
90
|
"browser-test": "node scripts/browser-test.mjs",
|
|
91
91
|
"capture-accuracy-test": "node scripts/capture-accuracy-test.mjs",
|
|
92
92
|
"element-capture-test": "node scripts/element-capture-test.mjs",
|
|
93
|
+
"svg-vars-test": "node scripts/svg-vars-test.mjs",
|
|
93
94
|
"loop-features-test": "node scripts/loop-features-test.mjs",
|
|
94
95
|
"walk-test": "node scripts/walk-test.mjs",
|
|
95
96
|
"modern-css-test": "node scripts/modern-css-test.mjs",
|