@replohq/sandbox-runtime 1.7.8 → 1.7.10

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.
@@ -120,6 +120,13 @@ export declare class Uncommon_GloballyMappedError extends ReploError {
120
120
  userFacingDetails: ErrorUserFacingDetails;
121
121
  });
122
122
  }
123
+ /**
124
+ * The `userFacingDetails.key` publisher puts on its 404 for a missing project.
125
+ * It lives here rather than next to the error class because a caller across a
126
+ * service boundary (airlock) matches on it to tell "this project is gone" apart
127
+ * from any other 404 that URL could produce.
128
+ */
129
+ export declare const PROJECT_NOT_FOUND_ERROR_KEY = "errors.project.notFound";
123
130
  export declare class ReploValidationError extends ReploError {
124
131
  constructor(message: string);
125
132
  }
@@ -86,6 +86,7 @@ export type SelectableDataPayload = SelectablePlanPayload;
86
86
  export type SelectableData = SelectedElement | SelectablePlanData;
87
87
  export type SelectModeOptimisticUpdatePayload = {
88
88
  kind: "css";
89
+ fontSource?: "google" | "site";
89
90
  property: string;
90
91
  value: string | null;
91
92
  } | {
@@ -275,6 +275,10 @@ export declare function readSelectablePayload(rawPayload: string | null): {
275
275
  } | null;
276
276
  export declare const selectModeOptimisticUpdatePayloadSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
277
277
  kind: z.ZodLiteral<"css">;
278
+ fontSource: z.ZodOptional<z.ZodEnum<{
279
+ google: "google";
280
+ site: "site";
281
+ }>>;
278
282
  property: z.ZodString;
279
283
  value: z.ZodNullable<z.ZodString>;
280
284
  }, z.core.$strip>, z.ZodObject<{
@@ -1,4 +1,4 @@
1
- export { SELECT_MODE_SELECTABLE_ATTRIBUTE, SELECT_MODE_SELECTABLE_PAYLOAD_ATTRIBUTE, displayModeSchema, getIframeOffset, readSelectablePayload, selectModeBoundingRectSchema, selectModeClickPositionSchema, selectModeDefinedStyleSchema, selectModeFiberChainEntrySchema, selectModeFormatCommandSchema, selectModeInlineTextStatusSchema, selectModeOptimisticUpdatePayloadSchema, selectModeSelectionRectSchema, selectModeSelectionSchema, selectModeSelectionTypeSchema, selectModeSourceLocationSchema, selectModeStyleAtRuleSchema, selectModeStyleVariantSchema, selectModeTextMetricsSchema, selectModeTiptapActiveMarksSchema, selectableDataPayloadSchema, selectableDataSchema, selectablePlanDataSchema, selectablePlanPayloadSchema, selectedElementSchema, transformPoint, transformRect, transformSelectableData, transformSelectedElement } from '../../chunk-UOBGRB5I.mjs';
1
+ export { SELECT_MODE_SELECTABLE_ATTRIBUTE, SELECT_MODE_SELECTABLE_PAYLOAD_ATTRIBUTE, displayModeSchema, getIframeOffset, readSelectablePayload, selectModeBoundingRectSchema, selectModeClickPositionSchema, selectModeDefinedStyleSchema, selectModeFiberChainEntrySchema, selectModeFormatCommandSchema, selectModeInlineTextStatusSchema, selectModeOptimisticUpdatePayloadSchema, selectModeSelectionRectSchema, selectModeSelectionSchema, selectModeSelectionTypeSchema, selectModeSourceLocationSchema, selectModeStyleAtRuleSchema, selectModeStyleVariantSchema, selectModeTextMetricsSchema, selectModeTiptapActiveMarksSchema, selectableDataPayloadSchema, selectableDataSchema, selectablePlanDataSchema, selectablePlanPayloadSchema, selectedElementSchema, transformPoint, transformRect, transformSelectableData, transformSelectedElement } from '../../chunk-4T7WSMC3.mjs';
2
2
  import '../../chunk-JUKCUPQ6.mjs';
3
3
  import '../../chunk-FLYEIRFK.mjs';
4
4
  import '../../chunk-TESFJQID.mjs';
@@ -225,6 +225,10 @@ export declare const websiteBuilderToCanopyMethodConfig: {
225
225
  editId: z.ZodString;
226
226
  payload: z.ZodDiscriminatedUnion<[z.ZodObject<{
227
227
  kind: z.ZodLiteral<"css">;
228
+ fontSource: z.ZodOptional<z.ZodEnum<{
229
+ google: "google";
230
+ site: "site";
231
+ }>>;
228
232
  property: z.ZodString;
229
233
  value: z.ZodNullable<z.ZodString>;
230
234
  }, z.core.$strip>, z.ZodObject<{
@@ -723,6 +727,10 @@ export declare const selectModeParentMessageSchema: z.ZodDiscriminatedUnion<[z.Z
723
727
  editId: z.ZodString;
724
728
  payload: z.ZodDiscriminatedUnion<[z.ZodObject<{
725
729
  kind: z.ZodLiteral<"css">;
730
+ fontSource: z.ZodOptional<z.ZodEnum<{
731
+ google: "google";
732
+ site: "site";
733
+ }>>;
726
734
  property: z.ZodString;
727
735
  value: z.ZodNullable<z.ZodString>;
728
736
  }, z.core.$strip>, z.ZodObject<{
@@ -1,4 +1,4 @@
1
- import { selectedElementSchema, selectModeFormatCommandSchema, selectModeOptimisticUpdatePayloadSchema, selectModeSelectionTypeSchema, displayModeSchema, selectModeTiptapActiveMarksSchema, selectModeBoundingRectSchema, selectableDataSchema, selectModeSelectionRectSchema, selectModeClickPositionSchema } from '../../chunk-UOBGRB5I.mjs';
1
+ import { selectedElementSchema, selectModeFormatCommandSchema, selectModeOptimisticUpdatePayloadSchema, selectModeSelectionTypeSchema, displayModeSchema, selectModeTiptapActiveMarksSchema, selectModeBoundingRectSchema, selectableDataSchema, selectModeSelectionRectSchema, selectModeClickPositionSchema } from '../../chunk-4T7WSMC3.mjs';
2
2
  import '../../chunk-JUKCUPQ6.mjs';
3
3
  import '../../chunk-FLYEIRFK.mjs';
4
4
  import '../../chunk-TESFJQID.mjs';
package/buildMetadata.js CHANGED
@@ -1,7 +1,7 @@
1
1
  export const BUILD_METADATA = {
2
2
  "packageName": "@replohq/sandbox-runtime",
3
- "version": "1.7.8",
3
+ "version": "1.7.10",
4
4
  "branch": "HEAD",
5
- "commit": "3373cb130518e3250ca842e09a47b68ec42c48c0",
6
- "builtAt": "2026-09-19T01:22:45.241Z"
5
+ "commit": "228f4382ccb4fe484d0d2cd40b0d065ac6441fe2",
6
+ "builtAt": "2026-09-20T22:06:34.014Z"
7
7
  };
@@ -168,6 +168,7 @@ function readSelectablePayload(rawPayload) {
168
168
  var selectModeOptimisticUpdatePayloadSchema = z.discriminatedUnion("kind", [
169
169
  z.object({
170
170
  kind: z.literal("css"),
171
+ fontSource: z.enum(["google", "site"]).optional(),
171
172
  property: z.string(),
172
173
  value: z.string().nullable()
173
174
  }),
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@replohq/sandbox-runtime",
3
- "version": "1.7.8",
3
+ "version": "1.7.10",
4
4
  "reploBuild": {
5
5
  "packageName": "@replohq/sandbox-runtime",
6
- "version": "1.7.8",
6
+ "version": "1.7.10",
7
7
  "branch": "HEAD",
8
- "commit": "3373cb130518e3250ca842e09a47b68ec42c48c0",
9
- "builtAt": "2026-09-19T01:22:45.241Z"
8
+ "commit": "228f4382ccb4fe484d0d2cd40b0d065ac6441fe2",
9
+ "builtAt": "2026-09-20T22:06:34.014Z"
10
10
  },
11
11
  "description": "Replo sandbox runtime — editor integration for agent-built Next.js sites.",
12
12
  "license": "SEE LICENSE IN LICENSE",
@@ -110,7 +110,7 @@ function buildSelector(element) {
110
110
  const tag = currentElement.tagName.toLowerCase();
111
111
  const id = currentElement.id;
112
112
  if (id) {
113
- parts.unshift(`#${id}`);
113
+ parts.unshift(`#${CSS.escape(id)}`);
114
114
  break;
115
115
  }
116
116
  const parentElement = currentElement.parentElement;
@@ -1,4 +1,5 @@
1
1
  import { useCallback } from "react";
2
+ import { buildGoogleFontsCssUrl, quoteFontFamily } from "../../_vendor/replo-utils/lib/fonts.mjs";
2
3
  import { buildSelector } from "../descriptor/elementDescriptor";
3
4
  import {
4
5
  SELECT_MODE_OVERRIDE_ATTRIBUTE,
@@ -125,13 +126,74 @@ function restoreOriginalState({
125
126
  element.innerHTML = originalState.innerHTML;
126
127
  }
127
128
  }
129
+ function isBareFontFamilyName(value) {
130
+ const trimmed = value.trim();
131
+ if (trimmed.startsWith("var(") || trimmed === "inherit" || trimmed === "initial" || trimmed === "unset" || trimmed === "revert" || trimmed.includes(",")) {
132
+ return false;
133
+ }
134
+ return true;
135
+ }
136
+ function formatCssFontFamilyValue(value) {
137
+ const trimmed = value.trim();
138
+ if (!isBareFontFamilyName(trimmed)) {
139
+ return trimmed;
140
+ }
141
+ if (trimmed.startsWith("'") && trimmed.endsWith("'") || trimmed.startsWith('"') && trimmed.endsWith('"')) {
142
+ return trimmed;
143
+ }
144
+ return quoteFontFamily(trimmed);
145
+ }
146
+ function ensureGoogleFontStylesheet(family) {
147
+ if (!isBareFontFamilyName(family)) {
148
+ return null;
149
+ }
150
+ const bareFamily = family.replace(/^['"]|['"]$/gu, "");
151
+ if (!bareFamily) {
152
+ return null;
153
+ }
154
+ const existing = Array.from(
155
+ document.querySelectorAll("link[data-replo-select-font]")
156
+ ).find((link) => link.dataset.reploSelectFont === bareFamily);
157
+ if (!existing) {
158
+ const link = document.createElement("link");
159
+ link.rel = "stylesheet";
160
+ link.href = buildGoogleFontsCssUrl(bareFamily);
161
+ link.dataset.reploSelectFont = bareFamily;
162
+ document.head.append(link);
163
+ }
164
+ return bareFamily;
165
+ }
166
+ function removeUnusedGoogleFontStylesheet(family) {
167
+ const stillNeeded = getOverrideList().some(
168
+ (override) => override.injectedFontFamily === family
169
+ );
170
+ if (stillNeeded) {
171
+ return;
172
+ }
173
+ for (const link of document.querySelectorAll(
174
+ "link[data-replo-select-font]"
175
+ )) {
176
+ if (link.dataset.reploSelectFont === family) {
177
+ link.remove();
178
+ }
179
+ }
180
+ }
128
181
  function installCssRule(override) {
129
182
  if (override.payload.kind !== "css") {
130
183
  return;
131
184
  }
185
+ let cssValue = override.payload.value ?? "revert";
186
+ if (override.payload.property === "font-family" && override.payload.value) {
187
+ cssValue = formatCssFontFamilyValue(override.payload.value);
188
+ if (override.payload.fontSource === "google") {
189
+ override.injectedFontFamily = ensureGoogleFontStylesheet(
190
+ override.payload.value.trim()
191
+ );
192
+ }
193
+ }
132
194
  const style = document.createElement("style");
133
195
  style.dataset.reploSelectOverride = override.token;
134
- style.textContent = `[${SELECT_MODE_OVERRIDE_ATTRIBUTE}~="${override.token}"] { ${override.payload.property}: ${override.payload.value ?? "revert"} !important; }`;
196
+ style.textContent = `[${SELECT_MODE_OVERRIDE_ATTRIBUTE}~="${override.token}"] { ${override.payload.property}: ${cssValue} !important; }`;
135
197
  document.head.append(style);
136
198
  }
137
199
  function resolveTarget(target) {
@@ -185,9 +247,13 @@ function removeOverride({
185
247
  });
186
248
  }
187
249
  }
250
+ const injectedFontFamily = override.injectedFontFamily;
188
251
  setOverrideList(
189
252
  getOverrideList().filter((candidate) => candidate.editId !== editId)
190
253
  );
254
+ if (injectedFontFamily) {
255
+ removeUnusedGoogleFontStylesheet(injectedFontFamily);
256
+ }
191
257
  if (outcome === "failed") {
192
258
  for (const remainingOverride of getOverrideList()) {
193
259
  reapplyOverride({ override: remainingOverride, skipElement: null });
@@ -214,6 +280,7 @@ function useOptimisticOverrides() {
214
280
  const token = `override-${editId}`;
215
281
  const override = {
216
282
  editId,
283
+ injectedFontFamily: null,
217
284
  payload,
218
285
  registrationTimeout: window.setTimeout(() => {
219
286
  removeOverride({ editId, outcome: "failed" });