@replohq/sandbox-runtime 1.10.2 → 1.10.3
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/_vendor/replo-utils/lib/fonts.d.ts +12 -1
- package/_vendor/replo-utils/lib/fonts.mjs +41 -3
- package/_vendor/replo-utils/lib/miniappPreview.d.ts +13 -0
- package/_vendor/replo-utils/lib/miniappPreview.mjs +48 -0
- package/_vendor/replo-utils/lib/misc.d.ts +4 -0
- package/_vendor/replo-utils/lib/misc.mjs +1 -1
- package/_vendor/schemas/componentPreview.d.ts +0 -55
- package/_vendor/schemas/componentPreview.mjs +1 -45
- package/_vendor/schemas/designLibrary.d.ts +23 -0
- package/_vendor/schemas/designLibrary.mjs +8 -1
- package/_vendor/schemas/generated/componentPreview.d.ts +0 -34
- package/_vendor/schemas/generated/selectMode.d.ts +8 -0
- package/_vendor/schemas/iframeRpcChannel.mjs +1 -1
- package/_vendor/schemas/selectMode.d.ts +25 -1
- package/_vendor/schemas/selectMode.mjs +2 -2
- package/_vendor/schemas/selectModeIframeRpc.d.ts +45 -5
- package/_vendor/schemas/selectModeIframeRpc.mjs +2 -2
- package/annotations/bridgeGate.d.ts +0 -5
- package/annotations/bridgeGate.js +2 -1
- package/buildMetadata.js +3 -3
- package/capturePage.d.ts +6 -0
- package/capturePage.js +118 -6
- package/{chunk-NBVMONRN.mjs → chunk-KFJZ2OLV.mjs} +10 -2
- package/{chunk-JUKCUPQ6.mjs → chunk-PH3S6LJI.mjs} +21 -1
- package/package.json +4 -4
- package/select-mode/descriptor/elementDescriptor.js +10 -2
- package/select-mode/descriptor/styleExtraction.d.ts +4 -0
- package/select-mode/descriptor/styleExtraction.js +134 -19
- package/select-mode/hooks/useOptimisticOverrides.js +7 -0
- package/select-mode/hooks/useSelectionInteractions.js +7 -5
- package/select-mode/iframeRpcChannel.d.ts +16 -1
- package/select-mode/selectModeStore.js +5 -1
|
@@ -4,8 +4,8 @@ export declare const SELECT_MODE_IFRAME_RPC_CHANNEL_ID: "replo:select-mode-ifram
|
|
|
4
4
|
export declare const SELECT_MODE_IFRAME_RPC_CHANNEL_VERSION: 1;
|
|
5
5
|
export declare const inlineEditFeedbackSchema: z.ZodObject<{
|
|
6
6
|
status: z.ZodEnum<{
|
|
7
|
-
unavailable: "unavailable";
|
|
8
7
|
pending: "pending";
|
|
8
|
+
unavailable: "unavailable";
|
|
9
9
|
failed: "failed";
|
|
10
10
|
}>;
|
|
11
11
|
rect: z.ZodObject<{
|
|
@@ -91,6 +91,10 @@ export declare const selectModeEventInputSchemas: {
|
|
|
91
91
|
previewUrl: z.ZodNullable<z.ZodString>;
|
|
92
92
|
}, z.core.$strip>>;
|
|
93
93
|
}, z.core.$strip>>;
|
|
94
|
+
video: z.ZodOptional<z.ZodObject<{
|
|
95
|
+
src: z.ZodString;
|
|
96
|
+
currentSrc: z.ZodString;
|
|
97
|
+
}, z.core.$strip>>;
|
|
94
98
|
definedStyles: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
95
99
|
property: z.ZodString;
|
|
96
100
|
variant: z.ZodNullable<z.ZodObject<{
|
|
@@ -104,6 +108,7 @@ export declare const selectModeEventInputSchemas: {
|
|
|
104
108
|
raw: z.ZodString;
|
|
105
109
|
resolved: z.ZodString;
|
|
106
110
|
}, z.core.$strip>>>;
|
|
111
|
+
authoredStyles: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
107
112
|
inheritedStyles: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
108
113
|
clickPosition: z.ZodObject<{
|
|
109
114
|
x: z.ZodNumber;
|
|
@@ -233,6 +238,10 @@ export declare const websiteBuilderToPreviewIframeMethodConfig: {
|
|
|
233
238
|
previewUrl: z.ZodNullable<z.ZodString>;
|
|
234
239
|
}, z.core.$strip>>;
|
|
235
240
|
}, z.core.$strip>>;
|
|
241
|
+
video: z.ZodOptional<z.ZodObject<{
|
|
242
|
+
src: z.ZodString;
|
|
243
|
+
currentSrc: z.ZodString;
|
|
244
|
+
}, z.core.$strip>>;
|
|
236
245
|
definedStyles: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
237
246
|
property: z.ZodString;
|
|
238
247
|
variant: z.ZodNullable<z.ZodObject<{
|
|
@@ -246,6 +255,7 @@ export declare const websiteBuilderToPreviewIframeMethodConfig: {
|
|
|
246
255
|
raw: z.ZodString;
|
|
247
256
|
resolved: z.ZodString;
|
|
248
257
|
}, z.core.$strip>>>;
|
|
258
|
+
authoredStyles: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
249
259
|
inheritedStyles: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
250
260
|
clickPosition: z.ZodObject<{
|
|
251
261
|
x: z.ZodNumber;
|
|
@@ -310,6 +320,10 @@ export declare const websiteBuilderToPreviewIframeMethodConfig: {
|
|
|
310
320
|
previewUrl: z.ZodNullable<z.ZodString>;
|
|
311
321
|
}, z.core.$strip>>;
|
|
312
322
|
}, z.core.$strip>>;
|
|
323
|
+
video: z.ZodOptional<z.ZodObject<{
|
|
324
|
+
src: z.ZodString;
|
|
325
|
+
currentSrc: z.ZodString;
|
|
326
|
+
}, z.core.$strip>>;
|
|
313
327
|
definedStyles: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
314
328
|
property: z.ZodString;
|
|
315
329
|
variant: z.ZodNullable<z.ZodObject<{
|
|
@@ -323,6 +337,7 @@ export declare const websiteBuilderToPreviewIframeMethodConfig: {
|
|
|
323
337
|
raw: z.ZodString;
|
|
324
338
|
resolved: z.ZodString;
|
|
325
339
|
}, z.core.$strip>>>;
|
|
340
|
+
authoredStyles: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
326
341
|
inheritedStyles: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
327
342
|
clickPosition: z.ZodObject<{
|
|
328
343
|
x: z.ZodNumber;
|
|
@@ -369,8 +384,8 @@ export declare const websiteBuilderToPreviewIframeMethodConfig: {
|
|
|
369
384
|
selectionType: z.ZodEnum<{
|
|
370
385
|
drag: "drag";
|
|
371
386
|
area: "area";
|
|
372
|
-
element: "element";
|
|
373
387
|
none: "none";
|
|
388
|
+
element: "element";
|
|
374
389
|
}>;
|
|
375
390
|
selectors: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
376
391
|
}, z.core.$strip>;
|
|
@@ -506,6 +521,10 @@ export declare const previewIframeToWebsiteBuilderMethodConfig: {
|
|
|
506
521
|
previewUrl: z.ZodNullable<z.ZodString>;
|
|
507
522
|
}, z.core.$strip>>;
|
|
508
523
|
}, z.core.$strip>>;
|
|
524
|
+
video: z.ZodOptional<z.ZodObject<{
|
|
525
|
+
src: z.ZodString;
|
|
526
|
+
currentSrc: z.ZodString;
|
|
527
|
+
}, z.core.$strip>>;
|
|
509
528
|
definedStyles: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
510
529
|
property: z.ZodString;
|
|
511
530
|
variant: z.ZodNullable<z.ZodObject<{
|
|
@@ -519,6 +538,7 @@ export declare const previewIframeToWebsiteBuilderMethodConfig: {
|
|
|
519
538
|
raw: z.ZodString;
|
|
520
539
|
resolved: z.ZodString;
|
|
521
540
|
}, z.core.$strip>>>;
|
|
541
|
+
authoredStyles: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
522
542
|
inheritedStyles: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
523
543
|
clickPosition: z.ZodObject<{
|
|
524
544
|
x: z.ZodNumber;
|
|
@@ -601,6 +621,10 @@ export declare const previewIframeToWebsiteBuilderMethodConfig: {
|
|
|
601
621
|
previewUrl: z.ZodNullable<z.ZodString>;
|
|
602
622
|
}, z.core.$strip>>;
|
|
603
623
|
}, z.core.$strip>>;
|
|
624
|
+
video: z.ZodOptional<z.ZodObject<{
|
|
625
|
+
src: z.ZodString;
|
|
626
|
+
currentSrc: z.ZodString;
|
|
627
|
+
}, z.core.$strip>>;
|
|
604
628
|
definedStyles: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
605
629
|
property: z.ZodString;
|
|
606
630
|
variant: z.ZodNullable<z.ZodObject<{
|
|
@@ -614,6 +638,7 @@ export declare const previewIframeToWebsiteBuilderMethodConfig: {
|
|
|
614
638
|
raw: z.ZodString;
|
|
615
639
|
resolved: z.ZodString;
|
|
616
640
|
}, z.core.$strip>>>;
|
|
641
|
+
authoredStyles: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
617
642
|
inheritedStyles: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
618
643
|
clickPosition: z.ZodObject<{
|
|
619
644
|
x: z.ZodNumber;
|
|
@@ -785,6 +810,10 @@ export declare const previewIframeToWebsiteBuilderMethodConfig: {
|
|
|
785
810
|
previewUrl: z.ZodNullable<z.ZodString>;
|
|
786
811
|
}, z.core.$strip>>;
|
|
787
812
|
}, z.core.$strip>>;
|
|
813
|
+
video: z.ZodOptional<z.ZodObject<{
|
|
814
|
+
src: z.ZodString;
|
|
815
|
+
currentSrc: z.ZodString;
|
|
816
|
+
}, z.core.$strip>>;
|
|
788
817
|
definedStyles: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
789
818
|
property: z.ZodString;
|
|
790
819
|
variant: z.ZodNullable<z.ZodObject<{
|
|
@@ -798,6 +827,7 @@ export declare const previewIframeToWebsiteBuilderMethodConfig: {
|
|
|
798
827
|
raw: z.ZodString;
|
|
799
828
|
resolved: z.ZodString;
|
|
800
829
|
}, z.core.$strip>>>;
|
|
830
|
+
authoredStyles: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
801
831
|
inheritedStyles: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
802
832
|
clickPosition: z.ZodObject<{
|
|
803
833
|
x: z.ZodNumber;
|
|
@@ -852,8 +882,8 @@ export declare const previewIframeToWebsiteBuilderMethodConfig: {
|
|
|
852
882
|
inputSchema: z.ZodObject<{
|
|
853
883
|
feedback: z.ZodNullable<z.ZodObject<{
|
|
854
884
|
status: z.ZodEnum<{
|
|
855
|
-
unavailable: "unavailable";
|
|
856
885
|
pending: "pending";
|
|
886
|
+
unavailable: "unavailable";
|
|
857
887
|
failed: "failed";
|
|
858
888
|
}>;
|
|
859
889
|
rect: z.ZodObject<{
|
|
@@ -912,8 +942,8 @@ export declare const selectModeParentMessageSchema: z.ZodDiscriminatedUnion<[z.Z
|
|
|
912
942
|
selectionType: z.ZodEnum<{
|
|
913
943
|
drag: "drag";
|
|
914
944
|
area: "area";
|
|
915
|
-
element: "element";
|
|
916
945
|
none: "none";
|
|
946
|
+
element: "element";
|
|
917
947
|
}>;
|
|
918
948
|
selectors: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
919
949
|
}, z.core.$strip>;
|
|
@@ -1046,6 +1076,10 @@ export declare const selectModeIframeMessageSchema: z.ZodDiscriminatedUnion<[z.Z
|
|
|
1046
1076
|
previewUrl: z.ZodNullable<z.ZodString>;
|
|
1047
1077
|
}, z.core.$strip>>;
|
|
1048
1078
|
}, z.core.$strip>>;
|
|
1079
|
+
video: z.ZodOptional<z.ZodObject<{
|
|
1080
|
+
src: z.ZodString;
|
|
1081
|
+
currentSrc: z.ZodString;
|
|
1082
|
+
}, z.core.$strip>>;
|
|
1049
1083
|
definedStyles: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
1050
1084
|
property: z.ZodString;
|
|
1051
1085
|
variant: z.ZodNullable<z.ZodObject<{
|
|
@@ -1059,6 +1093,7 @@ export declare const selectModeIframeMessageSchema: z.ZodDiscriminatedUnion<[z.Z
|
|
|
1059
1093
|
raw: z.ZodString;
|
|
1060
1094
|
resolved: z.ZodString;
|
|
1061
1095
|
}, z.core.$strip>>>;
|
|
1096
|
+
authoredStyles: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1062
1097
|
inheritedStyles: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1063
1098
|
clickPosition: z.ZodObject<{
|
|
1064
1099
|
x: z.ZodNumber;
|
|
@@ -1225,6 +1260,10 @@ export declare const selectModeIframeMessageSchema: z.ZodDiscriminatedUnion<[z.Z
|
|
|
1225
1260
|
previewUrl: z.ZodNullable<z.ZodString>;
|
|
1226
1261
|
}, z.core.$strip>>;
|
|
1227
1262
|
}, z.core.$strip>>;
|
|
1263
|
+
video: z.ZodOptional<z.ZodObject<{
|
|
1264
|
+
src: z.ZodString;
|
|
1265
|
+
currentSrc: z.ZodString;
|
|
1266
|
+
}, z.core.$strip>>;
|
|
1228
1267
|
definedStyles: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
1229
1268
|
property: z.ZodString;
|
|
1230
1269
|
variant: z.ZodNullable<z.ZodObject<{
|
|
@@ -1238,6 +1277,7 @@ export declare const selectModeIframeMessageSchema: z.ZodDiscriminatedUnion<[z.Z
|
|
|
1238
1277
|
raw: z.ZodString;
|
|
1239
1278
|
resolved: z.ZodString;
|
|
1240
1279
|
}, z.core.$strip>>>;
|
|
1280
|
+
authoredStyles: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1241
1281
|
inheritedStyles: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1242
1282
|
clickPosition: z.ZodObject<{
|
|
1243
1283
|
x: z.ZodNumber;
|
|
@@ -1290,8 +1330,8 @@ export declare const selectModeIframeMessageSchema: z.ZodDiscriminatedUnion<[z.Z
|
|
|
1290
1330
|
data: z.ZodObject<{
|
|
1291
1331
|
feedback: z.ZodNullable<z.ZodObject<{
|
|
1292
1332
|
status: z.ZodEnum<{
|
|
1293
|
-
unavailable: "unavailable";
|
|
1294
1333
|
pending: "pending";
|
|
1334
|
+
unavailable: "unavailable";
|
|
1295
1335
|
failed: "failed";
|
|
1296
1336
|
}>;
|
|
1297
1337
|
rect: z.ZodObject<{
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { selectModeBoundingRectSchema, selectModeTiptapActiveMarksSchema, selectModeSelectionRectSchema, selectableDataSchema, selectModeHoverRectSchema, selectModeFormatCommandSchema, selectModeOptimisticUpdatePayloadSchema, selectModeSelectionTypeSchema, displayModeSchema, selectModeClickPositionSchema, selectedElementSchema } from '../../chunk-
|
|
2
|
-
import '../../chunk-
|
|
1
|
+
import { selectModeBoundingRectSchema, selectModeTiptapActiveMarksSchema, selectModeSelectionRectSchema, selectableDataSchema, selectModeHoverRectSchema, selectModeFormatCommandSchema, selectModeOptimisticUpdatePayloadSchema, selectModeSelectionTypeSchema, displayModeSchema, selectModeClickPositionSchema, selectedElementSchema } from '../../chunk-KFJZ2OLV.mjs';
|
|
2
|
+
import '../../chunk-PH3S6LJI.mjs';
|
|
3
3
|
import '../../chunk-FLYEIRFK.mjs';
|
|
4
4
|
import '../../chunk-TESFJQID.mjs';
|
|
5
5
|
import '../../chunk-G3S6ZNPF.mjs';
|
|
@@ -1,7 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Origin gate for inbound editor-bridge messages, checked BEFORE any payload
|
|
3
|
-
* parsing. The select-mode bridge predates this and validates payload shape
|
|
4
|
-
* only; its hardening ticket is expected to adopt this helper.
|
|
5
|
-
*/
|
|
6
1
|
export declare function isAllowedEditorOrigin(origin: string): boolean;
|
|
7
2
|
export declare function isAllowedEditorMessage(event: MessageEvent): boolean;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { isMiniappPreviewOrigin } from "../_vendor/replo-utils/lib/miniappPreview.mjs";
|
|
1
2
|
const ALLOWED_EDITOR_ORIGIN_PATTERNS = [
|
|
2
3
|
/^https?:\/\/localhost(?::\d+)?$/u,
|
|
3
4
|
/^https:\/\/(?:[a-z0-9-]+\.)*replo\.app$/u,
|
|
4
5
|
/^https:\/\/replo-[a-z0-9-]+\.ngrok\.app$/u
|
|
5
6
|
];
|
|
6
7
|
function isAllowedEditorOrigin(origin) {
|
|
7
|
-
return ALLOWED_EDITOR_ORIGIN_PATTERNS.some((pattern) => pattern.test(origin));
|
|
8
|
+
return isMiniappPreviewOrigin(origin) || ALLOWED_EDITOR_ORIGIN_PATTERNS.some((pattern) => pattern.test(origin));
|
|
8
9
|
}
|
|
9
10
|
function isAllowedEditorMessage(event) {
|
|
10
11
|
if (typeof window === "undefined" || window.self === window.top) {
|
package/buildMetadata.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const BUILD_METADATA = {
|
|
2
2
|
"packageName": "@replohq/sandbox-runtime",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.3",
|
|
4
4
|
"branch": "HEAD",
|
|
5
|
-
"commit": "
|
|
6
|
-
"builtAt": "2026-
|
|
5
|
+
"commit": "3a43b7ccb4b4143e6b0cbe1c5678c4702deb8b9d",
|
|
6
|
+
"builtAt": "2026-10-07T15:54:30.287Z"
|
|
7
7
|
};
|
package/capturePage.d.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
export declare function parseYouTubeId(src: string): string | null;
|
|
2
2
|
export declare function parseVimeoId(src: string): string | null;
|
|
3
|
+
/** The srcset candidate a browser would pick for `width` CSS pixels. */
|
|
4
|
+
export declare function pickSrcsetCandidate({ srcset, width, pixelRatio, }: {
|
|
5
|
+
srcset: string;
|
|
6
|
+
width: number;
|
|
7
|
+
pixelRatio: number;
|
|
8
|
+
}): string | null;
|
|
3
9
|
/**
|
|
4
10
|
* Draws the page's first screen (from the document top, regardless of scroll)
|
|
5
11
|
* into an exact width×height JPEG. Videos and YouTube/Vimeo embeds, which the
|
package/capturePage.js
CHANGED
|
@@ -7,6 +7,7 @@ const VIDEO_LOAD_TIMEOUT_MS = 4e3;
|
|
|
7
7
|
const VIDEO_SEEK_TIMEOUT_MS = 1500;
|
|
8
8
|
const PLACEHOLDER_BACKGROUND = "#d9d9d6";
|
|
9
9
|
const IFRAME_PLACEHOLDER_MARKER = "repeating-linear-gradient(45deg";
|
|
10
|
+
const CAPTURE_SRC_ATTRIBUTE = "data-replo-capture-src";
|
|
10
11
|
const vimeoOembedSchema = z.object({ thumbnail_url: z.string() });
|
|
11
12
|
function parseYouTubeId(src) {
|
|
12
13
|
const match = src.match(
|
|
@@ -61,18 +62,96 @@ function videoFrameDataUrl(video) {
|
|
|
61
62
|
context.drawImage(video, 0, 0);
|
|
62
63
|
return canvas.toDataURL("image/jpeg", VIDEO_FRAME_QUALITY);
|
|
63
64
|
}
|
|
64
|
-
function
|
|
65
|
-
|
|
65
|
+
function isInFirstScreen({
|
|
66
|
+
rect,
|
|
66
67
|
height
|
|
67
68
|
}) {
|
|
68
|
-
const
|
|
69
|
-
|
|
69
|
+
const isRendered = rect.width > 0 || rect.height > 0;
|
|
70
|
+
const isInViewport = rect.bottom > 0 && rect.top < height;
|
|
71
|
+
return isRendered && (isInViewport || rect.top + window.scrollY < height);
|
|
72
|
+
}
|
|
73
|
+
function parseSrcset(srcset) {
|
|
74
|
+
const candidates = [];
|
|
75
|
+
const candidatePattern = /[\s,]*([^\s,][^\s]*)/y;
|
|
76
|
+
let position = 0;
|
|
77
|
+
while (position < srcset.length) {
|
|
78
|
+
candidatePattern.lastIndex = position;
|
|
79
|
+
const match = candidatePattern.exec(srcset);
|
|
80
|
+
if (!match?.[1]) {
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
position = candidatePattern.lastIndex;
|
|
84
|
+
if (match[1].endsWith(",")) {
|
|
85
|
+
candidates.push({ url: match[1].replace(/,+$/, ""), descriptor: "" });
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
const commaIndex = srcset.indexOf(",", position);
|
|
89
|
+
const descriptorEnd = commaIndex === -1 ? srcset.length : commaIndex;
|
|
90
|
+
candidates.push({
|
|
91
|
+
url: match[1],
|
|
92
|
+
descriptor: srcset.slice(position, descriptorEnd).trim()
|
|
93
|
+
});
|
|
94
|
+
position = descriptorEnd + 1;
|
|
95
|
+
}
|
|
96
|
+
return candidates;
|
|
97
|
+
}
|
|
98
|
+
function pickSrcsetCandidate({
|
|
99
|
+
srcset,
|
|
100
|
+
width,
|
|
101
|
+
pixelRatio
|
|
102
|
+
}) {
|
|
103
|
+
const candidates = parseSrcset(srcset).map(({ url, descriptor }) => {
|
|
104
|
+
const widthMatch = /^(\d+)w$/i.exec(descriptor);
|
|
105
|
+
if (widthMatch) {
|
|
106
|
+
return { url, density: Number(widthMatch[1]) / width };
|
|
107
|
+
}
|
|
108
|
+
const densityMatch = /^(\d*\.?\d+)x$/i.exec(descriptor);
|
|
109
|
+
return { url, density: densityMatch ? Number(densityMatch[1]) : 1 };
|
|
110
|
+
}).sort((left, right) => left.density - right.density);
|
|
111
|
+
const chosen = candidates.find((candidate) => candidate.density >= pixelRatio) ?? candidates.at(-1);
|
|
112
|
+
return chosen?.url ?? null;
|
|
113
|
+
}
|
|
114
|
+
const DECODABLE_IMAGE_TYPE = /^image\/(avif|webp|jpeg|png|gif|svg\+xml)$/i;
|
|
115
|
+
function getActiveSrcset(image) {
|
|
116
|
+
if (image.parentElement?.tagName === "PICTURE") {
|
|
117
|
+
for (const source of image.parentElement.querySelectorAll(
|
|
118
|
+
":scope > source[srcset]"
|
|
119
|
+
)) {
|
|
120
|
+
const media = source.getAttribute("media");
|
|
121
|
+
const type = source.getAttribute("type");
|
|
122
|
+
if (media && !window.matchMedia(media).matches) {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (type && !DECODABLE_IMAGE_TYPE.test(type.trim())) {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
return source.getAttribute("srcset");
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return image.getAttribute("srcset");
|
|
132
|
+
}
|
|
133
|
+
function getRepairedSource({
|
|
134
|
+
image,
|
|
135
|
+
rect
|
|
136
|
+
}) {
|
|
137
|
+
if (image.currentSrc) {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
const srcset = getActiveSrcset(image);
|
|
141
|
+
if (!srcset) {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
return pickSrcsetCandidate({
|
|
145
|
+
srcset,
|
|
146
|
+
width: rect.width || window.innerWidth,
|
|
147
|
+
pixelRatio: 1
|
|
148
|
+
});
|
|
70
149
|
}
|
|
71
150
|
async function readVideoFrame({
|
|
72
151
|
video,
|
|
73
152
|
height
|
|
74
153
|
}) {
|
|
75
|
-
if (!
|
|
154
|
+
if (!isInFirstScreen({ rect: video.getBoundingClientRect(), height })) {
|
|
76
155
|
return null;
|
|
77
156
|
}
|
|
78
157
|
if (video.readyState >= HTMLMediaElement.HAVE_CURRENT_DATA && isCanvasReadable(video)) {
|
|
@@ -148,6 +227,20 @@ function createStandInsPlugin({
|
|
|
148
227
|
return;
|
|
149
228
|
}
|
|
150
229
|
for (const image of clone.querySelectorAll("img")) {
|
|
230
|
+
const captureSrc = image.getAttribute(CAPTURE_SRC_ATTRIBUTE);
|
|
231
|
+
if (captureSrc) {
|
|
232
|
+
image.removeAttribute(CAPTURE_SRC_ATTRIBUTE);
|
|
233
|
+
image.removeAttribute("srcset");
|
|
234
|
+
image.removeAttribute("sizes");
|
|
235
|
+
image.setAttribute("src", captureSrc);
|
|
236
|
+
if (image.parentElement?.tagName === "PICTURE") {
|
|
237
|
+
for (const source of image.parentElement.querySelectorAll(
|
|
238
|
+
":scope > source"
|
|
239
|
+
)) {
|
|
240
|
+
source.remove();
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
151
244
|
const objectFit = objectFitByFrame.get(image.getAttribute("src") ?? "");
|
|
152
245
|
if (objectFit) {
|
|
153
246
|
image.style.objectFit = objectFit;
|
|
@@ -221,10 +314,25 @@ async function capturePage({
|
|
|
221
314
|
video.setAttribute("poster", frame);
|
|
222
315
|
objectFitByFrame.set(frame, getComputedStyle(video).objectFit);
|
|
223
316
|
});
|
|
317
|
+
const offscreenImages = /* @__PURE__ */ new Set();
|
|
318
|
+
const repairedImages = [];
|
|
319
|
+
for (const image of document.querySelectorAll("img")) {
|
|
320
|
+
const rect = image.getBoundingClientRect();
|
|
321
|
+
if (!isInFirstScreen({ rect, height })) {
|
|
322
|
+
offscreenImages.add(image);
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
const repairedSource = getRepairedSource({ image, rect });
|
|
326
|
+
if (repairedSource) {
|
|
327
|
+
image.setAttribute(CAPTURE_SRC_ATTRIBUTE, repairedSource);
|
|
328
|
+
repairedImages.push(image);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
224
331
|
try {
|
|
225
332
|
const raw = await snapdom.toRaw(document.body, {
|
|
226
333
|
scale: 1,
|
|
227
334
|
embedFonts: true,
|
|
335
|
+
exclude: (element) => offscreenImages.has(element),
|
|
228
336
|
plugins: [createStandInsPlugin({ objectFitByFrame, iframeThumbnails })]
|
|
229
337
|
});
|
|
230
338
|
const image = new Image();
|
|
@@ -245,6 +353,9 @@ async function capturePage({
|
|
|
245
353
|
context.drawImage(image, 0, 0);
|
|
246
354
|
return await canvasToJpeg(canvas);
|
|
247
355
|
} finally {
|
|
356
|
+
for (const image of repairedImages) {
|
|
357
|
+
image.removeAttribute(CAPTURE_SRC_ATTRIBUTE);
|
|
358
|
+
}
|
|
248
359
|
for (const { video, poster } of originalPosters) {
|
|
249
360
|
if (poster === null) {
|
|
250
361
|
video.removeAttribute("poster");
|
|
@@ -257,5 +368,6 @@ async function capturePage({
|
|
|
257
368
|
export {
|
|
258
369
|
capturePage,
|
|
259
370
|
parseVimeoId,
|
|
260
|
-
parseYouTubeId
|
|
371
|
+
parseYouTubeId,
|
|
372
|
+
pickSrcsetCandidate
|
|
261
373
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { exhaustiveSwitch } from './chunk-
|
|
1
|
+
import { exhaustiveSwitch } from './chunk-PH3S6LJI.mjs';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
|
|
4
4
|
function parseJsonOrNull(json) {
|
|
@@ -120,6 +120,10 @@ var selectModeImageSchema = z.object({
|
|
|
120
120
|
previewUrl: z.string().nullable(),
|
|
121
121
|
sources: z.array(selectModeImageSourceSchema)
|
|
122
122
|
}).describe("SelectModeImage");
|
|
123
|
+
var selectModeVideoSchema = z.object({
|
|
124
|
+
src: z.string(),
|
|
125
|
+
currentSrc: z.string()
|
|
126
|
+
}).describe("SelectModeVideo");
|
|
123
127
|
var selectedElementSchema = z.object({
|
|
124
128
|
kind: z.literal("react-element"),
|
|
125
129
|
selector: z.string(),
|
|
@@ -132,7 +136,11 @@ var selectedElementSchema = z.object({
|
|
|
132
136
|
textMetrics: selectModeTextMetricsSchema.nullable(),
|
|
133
137
|
outerHTML: z.string(),
|
|
134
138
|
image: selectModeImageSchema.optional(),
|
|
139
|
+
video: selectModeVideoSchema.optional(),
|
|
135
140
|
definedStyles: z.array(selectModeDefinedStyleSchema).default([]),
|
|
141
|
+
authoredStyles: z.record(z.string(), z.string()).default({}).describe(
|
|
142
|
+
"Authored CSS value of the winning declaration per control property, custom properties expanded (e.g. 1.5rem for text-2xl at a wide viewport)."
|
|
143
|
+
),
|
|
136
144
|
inheritedStyles: z.record(z.string(), z.string()).default({}),
|
|
137
145
|
clickPosition: selectModeClickPositionSchema,
|
|
138
146
|
sourceLocation: selectModeSourceLocationSchema.optional(),
|
|
@@ -238,4 +246,4 @@ var selectModeSelectionSchema = z.discriminatedUnion("type", [
|
|
|
238
246
|
})
|
|
239
247
|
]).describe("SelectModeSelection");
|
|
240
248
|
|
|
241
|
-
export { SELECT_MODE_SELECTABLE_ATTRIBUTE, SELECT_MODE_SELECTABLE_PAYLOAD_ATTRIBUTE, displayModeSchema, getIframeOffset, isSelectedSection, readSelectablePayload, selectModeBoundingRectSchema, selectModeClickPositionSchema, selectModeDefinedStyleSchema, selectModeFiberChainEntrySchema, selectModeFormatCommandSchema, selectModeHoverRectSchema, selectModeImageSchema, selectModeImageScopeSchema, selectModeImageSourceSchema, selectModeInlineTextStatusSchema, selectModeOptimisticUpdatePayloadSchema, selectModeSelectionRectSchema, selectModeSelectionSchema, selectModeSelectionTypeSchema, selectModeSourceLocationSchema, selectModeStyleAtRuleSchema, selectModeStyleVariantSchema, selectModeTextMetricsSchema, selectModeTiptapActiveMarksSchema, selectableDataPayloadSchema, selectableDataSchema, selectablePlanDataSchema, selectablePlanPayloadSchema, selectedElementSchema, transformPoint, transformRect, transformSelectableData, transformSelectedElement };
|
|
249
|
+
export { SELECT_MODE_SELECTABLE_ATTRIBUTE, SELECT_MODE_SELECTABLE_PAYLOAD_ATTRIBUTE, displayModeSchema, getIframeOffset, isSelectedSection, readSelectablePayload, selectModeBoundingRectSchema, selectModeClickPositionSchema, selectModeDefinedStyleSchema, selectModeFiberChainEntrySchema, selectModeFormatCommandSchema, selectModeHoverRectSchema, selectModeImageSchema, selectModeImageScopeSchema, selectModeImageSourceSchema, selectModeInlineTextStatusSchema, selectModeOptimisticUpdatePayloadSchema, selectModeSelectionRectSchema, selectModeSelectionSchema, selectModeSelectionTypeSchema, selectModeSourceLocationSchema, selectModeStyleAtRuleSchema, selectModeStyleVariantSchema, selectModeTextMetricsSchema, selectModeTiptapActiveMarksSchema, selectModeVideoSchema, selectableDataPayloadSchema, selectableDataSchema, selectablePlanDataSchema, selectablePlanPayloadSchema, selectedElementSchema, transformPoint, transformRect, transformSelectableData, transformSelectedElement };
|
|
@@ -1391,6 +1391,26 @@ function formatFileSize(byteCount, decimalPlaces = 0) {
|
|
|
1391
1391
|
var sleep = async (ms) => {
|
|
1392
1392
|
return await new Promise((resolve) => setTimeout(resolve, ms));
|
|
1393
1393
|
};
|
|
1394
|
+
function sleepWithSignal({
|
|
1395
|
+
delayMs,
|
|
1396
|
+
signal
|
|
1397
|
+
}) {
|
|
1398
|
+
if (signal === null) {
|
|
1399
|
+
return sleep(delayMs);
|
|
1400
|
+
}
|
|
1401
|
+
signal.throwIfAborted();
|
|
1402
|
+
return new Promise((resolve, reject) => {
|
|
1403
|
+
const onAbort = () => {
|
|
1404
|
+
clearTimeout(timeoutId);
|
|
1405
|
+
reject(signal.reason);
|
|
1406
|
+
};
|
|
1407
|
+
const timeoutId = setTimeout(() => {
|
|
1408
|
+
signal.removeEventListener("abort", onAbort);
|
|
1409
|
+
resolve();
|
|
1410
|
+
}, delayMs);
|
|
1411
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
1412
|
+
});
|
|
1413
|
+
}
|
|
1394
1414
|
function errorMessage(error) {
|
|
1395
1415
|
if (error instanceof Error) {
|
|
1396
1416
|
return error.message;
|
|
@@ -1402,4 +1422,4 @@ function errorMessage(error) {
|
|
|
1402
1422
|
return String(error);
|
|
1403
1423
|
}
|
|
1404
1424
|
|
|
1405
|
-
export { coerceNumberToString, deepCloneAndMergeReplacingArrays, errorMessage, exhaustiveSwitch, formatFileSize, getFromRecordOrNull, hasOwnProperty12 as hasOwnProperty, invariant, isEmpty2 as isEmpty, isFunction_default, isNotNullish, isNullish, isPrimitive, isString_default, mergeReplacingArrays, mergeReplacingObjects, noop, preventDefault, sleep, warning };
|
|
1425
|
+
export { coerceNumberToString, deepCloneAndMergeReplacingArrays, errorMessage, exhaustiveSwitch, formatFileSize, getFromRecordOrNull, hasOwnProperty12 as hasOwnProperty, invariant, isEmpty2 as isEmpty, isFunction_default, isNotNullish, isNullish, isPrimitive, isString_default, mergeReplacingArrays, mergeReplacingObjects, noop, preventDefault, sleep, sleepWithSignal, warning };
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@replohq/sandbox-runtime",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.3",
|
|
4
4
|
"reploBuild": {
|
|
5
5
|
"packageName": "@replohq/sandbox-runtime",
|
|
6
|
-
"version": "1.10.
|
|
6
|
+
"version": "1.10.3",
|
|
7
7
|
"branch": "HEAD",
|
|
8
|
-
"commit": "
|
|
9
|
-
"builtAt": "2026-
|
|
8
|
+
"commit": "3a43b7ccb4b4143e6b0cbe1c5678c4702deb8b9d",
|
|
9
|
+
"builtAt": "2026-10-07T15:54:30.287Z"
|
|
10
10
|
},
|
|
11
11
|
"description": "Replo sandbox runtime — editor integration for agent-built Next.js sites.",
|
|
12
12
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -3,11 +3,12 @@ import {
|
|
|
3
3
|
SELECT_MODE_SELECTABLE_ATTRIBUTE,
|
|
4
4
|
SELECT_MODE_SELECTABLE_PAYLOAD_ATTRIBUTE
|
|
5
5
|
} from "../../_vendor/schemas/selectMode.mjs";
|
|
6
|
+
import { z } from "zod";
|
|
6
7
|
import { getFiberChain } from "../fiber";
|
|
7
8
|
import { getImageDescriptor } from "../imageSources";
|
|
8
9
|
import { skipInlineTextMarkElements } from "../inlineTextMarks";
|
|
9
10
|
import { getElementBoundingRect } from "../interactions/selectionGeometry";
|
|
10
|
-
import {
|
|
11
|
+
import { getElementStyles, getInheritedStyles } from "./styleExtraction";
|
|
11
12
|
const SECTION_SELECTOR = 'section, article, aside, [role="region"]';
|
|
12
13
|
const SECTION_LABEL_LENGTH = 60;
|
|
13
14
|
function normalizeSectionLabel(value) {
|
|
@@ -217,11 +218,13 @@ function buildElementDescriptor({
|
|
|
217
218
|
if (selectableData) {
|
|
218
219
|
return selectableData;
|
|
219
220
|
}
|
|
221
|
+
const video = z.instanceof(HTMLVideoElement).safeParse(element);
|
|
220
222
|
const textMetrics = getTextMetrics(element);
|
|
221
223
|
const fiberChain = element instanceof HTMLElement ? getFiberChain(element) : [];
|
|
222
224
|
const sourceLocation = fiberChain[0]?.sourceLocation;
|
|
223
225
|
const trimmedText = getRenderedText(element);
|
|
224
226
|
const sectionLabel = findSectionLabel(section);
|
|
227
|
+
const { definedStyles, authoredStyles } = getElementStyles(element);
|
|
225
228
|
return {
|
|
226
229
|
kind: "react-element",
|
|
227
230
|
selector: buildSelector(element),
|
|
@@ -233,7 +236,12 @@ function buildElementDescriptor({
|
|
|
233
236
|
textMetrics,
|
|
234
237
|
outerHTML: element.outerHTML.slice(0, 4e3),
|
|
235
238
|
image: getImageDescriptor(element),
|
|
236
|
-
|
|
239
|
+
video: video.success ? {
|
|
240
|
+
src: video.data.getAttribute("src") ?? "",
|
|
241
|
+
currentSrc: video.data.currentSrc
|
|
242
|
+
} : void 0,
|
|
243
|
+
definedStyles,
|
|
244
|
+
authoredStyles,
|
|
237
245
|
inheritedStyles: getInheritedStyles(element),
|
|
238
246
|
clickPosition,
|
|
239
247
|
sourceLocation,
|
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
import type { SelectModeDefinedStyle } from "../../_vendor/schemas/generated/selectMode";
|
|
2
|
+
export declare function getElementStyles(element: Element): {
|
|
3
|
+
definedStyles: SelectModeDefinedStyle[];
|
|
4
|
+
authoredStyles: Record<string, string>;
|
|
5
|
+
};
|
|
2
6
|
export declare function getDefinedStyles(element: Element): SelectModeDefinedStyle[];
|
|
3
7
|
export declare function getInheritedStyles(element: Element): Record<string, string>;
|