@replohq/sandbox-runtime 1.7.7 → 1.7.9
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/schemas/componentPreview.mjs +1 -0
- package/_vendor/schemas/errors.d.ts +7 -0
- package/_vendor/schemas/generated/selectMode.d.ts +1 -0
- package/_vendor/schemas/loaderKeys.d.ts +2 -0
- package/_vendor/schemas/selectMode.d.ts +4 -0
- package/_vendor/schemas/selectMode.mjs +1 -1
- package/_vendor/schemas/selectModeIframeRpc.d.ts +8 -0
- package/_vendor/schemas/selectModeIframeRpc.mjs +1 -1
- package/buildMetadata.js +3 -3
- package/{chunk-UOBGRB5I.mjs → chunk-4T7WSMC3.mjs} +1 -0
- package/package.json +4 -4
- package/select-mode/EditorSelection.js +103 -49
- package/select-mode/fast-refresh-relay.d.ts +5 -0
- package/select-mode/fast-refresh-relay.js +6 -19
- package/select-mode/hooks/useOptimisticOverrides.js +68 -1
- package/select-mode/symbolicate.d.ts +2 -1
- package/select-mode/symbolicate.js +7 -1
|
@@ -6,6 +6,7 @@ var DATA_LOADER_KEYS = {
|
|
|
6
6
|
SHOPIFY_COLLECTION_PRODUCTS: "shopify_storefront.collection_products",
|
|
7
7
|
SHOPIFY_METAOBJECT: "shopify_storefront.metaobject",
|
|
8
8
|
SHOPIFY_METAOBJECTS: "shopify_storefront.metaobjects",
|
|
9
|
+
SHOPIFY_KACHING_BUNDLES: "shopify_storefront.kaching_bundles",
|
|
9
10
|
REPLO_PRODUCT: "replo_products.product",
|
|
10
11
|
OKENDO_PRODUCT_REVIEWS: "okendo.product_reviews",
|
|
11
12
|
OKENDO_PRODUCT_REVIEW_AGGREGATE: "okendo.product_review_aggregate",
|
|
@@ -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
|
} | {
|
|
@@ -16,6 +16,7 @@ export declare const DATA_LOADER_KEYS: {
|
|
|
16
16
|
readonly SHOPIFY_COLLECTION_PRODUCTS: "shopify_storefront.collection_products";
|
|
17
17
|
readonly SHOPIFY_METAOBJECT: "shopify_storefront.metaobject";
|
|
18
18
|
readonly SHOPIFY_METAOBJECTS: "shopify_storefront.metaobjects";
|
|
19
|
+
readonly SHOPIFY_KACHING_BUNDLES: "shopify_storefront.kaching_bundles";
|
|
19
20
|
readonly REPLO_PRODUCT: "replo_products.product";
|
|
20
21
|
readonly OKENDO_PRODUCT_REVIEWS: "okendo.product_reviews";
|
|
21
22
|
readonly OKENDO_PRODUCT_REVIEW_AGGREGATE: "okendo.product_review_aggregate";
|
|
@@ -43,6 +44,7 @@ export declare const dataLoaderKeySchema: z.ZodEnum<{
|
|
|
43
44
|
"shopify_storefront.collection_products": "shopify_storefront.collection_products";
|
|
44
45
|
"shopify_storefront.metaobject": "shopify_storefront.metaobject";
|
|
45
46
|
"shopify_storefront.metaobjects": "shopify_storefront.metaobjects";
|
|
47
|
+
"shopify_storefront.kaching_bundles": "shopify_storefront.kaching_bundles";
|
|
46
48
|
"replo_products.product": "replo_products.product";
|
|
47
49
|
"okendo.product_reviews": "okendo.product_reviews";
|
|
48
50
|
"okendo.product_review_aggregate": "okendo.product_review_aggregate";
|
|
@@ -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-
|
|
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-
|
|
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.
|
|
3
|
+
"version": "1.7.9",
|
|
4
4
|
"branch": "HEAD",
|
|
5
|
-
"commit": "
|
|
6
|
-
"builtAt": "2026-09-
|
|
5
|
+
"commit": "b01d429fa2ffd0346a2187126d2b7ea58e40441f",
|
|
6
|
+
"builtAt": "2026-09-20T05:20:23.775Z"
|
|
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.
|
|
3
|
+
"version": "1.7.9",
|
|
4
4
|
"reploBuild": {
|
|
5
5
|
"packageName": "@replohq/sandbox-runtime",
|
|
6
|
-
"version": "1.7.
|
|
6
|
+
"version": "1.7.9",
|
|
7
7
|
"branch": "HEAD",
|
|
8
|
-
"commit": "
|
|
9
|
-
"builtAt": "2026-09-
|
|
8
|
+
"commit": "b01d429fa2ffd0346a2187126d2b7ea58e40441f",
|
|
9
|
+
"builtAt": "2026-09-20T05:20:23.775Z"
|
|
10
10
|
},
|
|
11
11
|
"description": "Replo sandbox runtime — editor integration for agent-built Next.js sites.",
|
|
12
12
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -19,7 +19,10 @@ import { getDocumentScrollOffset } from "./interactions/selectionGeometry";
|
|
|
19
19
|
import { PREVIEW_RENDERED_EVENT } from "./previewRendered";
|
|
20
20
|
import { showElementSelectionFrames } from "./selectionFrame";
|
|
21
21
|
import { getConnectedSelectedElement } from "./selectModeSession";
|
|
22
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
isUserSourceLocation,
|
|
24
|
+
symbolicateSelectedElement
|
|
25
|
+
} from "./symbolicate";
|
|
23
26
|
function EditorSelection() {
|
|
24
27
|
const {
|
|
25
28
|
displayMode,
|
|
@@ -38,66 +41,117 @@ function EditorSelection() {
|
|
|
38
41
|
resolveSessionOverrides,
|
|
39
42
|
revertOverride
|
|
40
43
|
} = useOptimisticOverrides();
|
|
41
|
-
const postSelectedElementSnapshot = useCallback(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
44
|
+
const postSelectedElementSnapshot = useCallback(
|
|
45
|
+
({ clearMissing = false } = {}) => {
|
|
46
|
+
const session = interactionSessionRef.current;
|
|
47
|
+
if (session.type !== "element") {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
const element = getConnectedSelectedElement(session);
|
|
51
|
+
if (!element) {
|
|
52
|
+
if (!clearMissing) return false;
|
|
53
|
+
setSelectionType({ selectionType: "none" });
|
|
54
|
+
getWebsiteBuilderRpc()?.areaSelected({
|
|
55
|
+
rect: session.data.rect,
|
|
56
|
+
items: []
|
|
57
|
+
});
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
const siblingElements = getRepetitionSiblingElements({ element });
|
|
61
|
+
const descriptor = buildElementDescriptor({
|
|
62
|
+
element,
|
|
63
|
+
clickPosition: session.clickPosition ?? (session.data.kind === "react-element" ? session.data.clickPosition : { x: 0, y: 0 }),
|
|
64
|
+
siblingSelectors: siblingElements.map(buildSelector)
|
|
52
65
|
});
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
if (descriptor.kind !== "react-element") {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
const refreshedSession = {
|
|
70
|
+
...session,
|
|
71
|
+
element,
|
|
72
|
+
siblingElements,
|
|
73
|
+
data: session.data
|
|
74
|
+
};
|
|
75
|
+
interactionSessionRef.current = refreshedSession;
|
|
76
|
+
showElementSelectionFrames({
|
|
77
|
+
elements: [element, ...siblingElements],
|
|
78
|
+
scrollOffset: getDocumentScrollOffset()
|
|
79
|
+
});
|
|
80
|
+
void symbolicateSelectedElement(descriptor).then((symbolicated) => {
|
|
81
|
+
if (interactionSessionRef.current !== refreshedSession) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (symbolicated.sourceLocation && !isUserSourceLocation(symbolicated.sourceLocation)) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
refreshedSession.data = symbolicated;
|
|
88
|
+
getWebsiteBuilderRpc()?.elementSelected({ data: symbolicated });
|
|
89
|
+
});
|
|
90
|
+
return true;
|
|
91
|
+
},
|
|
92
|
+
[interactionSessionRef, setSelectionType]
|
|
93
|
+
);
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
let refreshTimeout;
|
|
96
|
+
let missingTimeout;
|
|
97
|
+
let observationTimeout;
|
|
98
|
+
const scheduleSnapshot = () => {
|
|
99
|
+
clearTimeout(refreshTimeout);
|
|
100
|
+
refreshTimeout = setTimeout(() => {
|
|
101
|
+
if (editingElementRef.current) return;
|
|
102
|
+
if (postSelectedElementSnapshot()) {
|
|
103
|
+
clearTimeout(missingTimeout);
|
|
104
|
+
missingTimeout = void 0;
|
|
105
|
+
} else if (!missingTimeout) {
|
|
106
|
+
const missingSession = interactionSessionRef.current;
|
|
107
|
+
missingTimeout = setTimeout(() => {
|
|
108
|
+
missingTimeout = void 0;
|
|
109
|
+
if (interactionSessionRef.current === missingSession) {
|
|
110
|
+
postSelectedElementSnapshot({ clearMissing: true });
|
|
111
|
+
}
|
|
112
|
+
}, 5e3);
|
|
113
|
+
}
|
|
114
|
+
}, 250);
|
|
69
115
|
};
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
void symbolicateSelectedElement(descriptor).then((symbolicated) => {
|
|
76
|
-
if (interactionSessionRef.current !== refreshedSession) {
|
|
77
|
-
return;
|
|
116
|
+
const observer = new MutationObserver((records) => {
|
|
117
|
+
const session = interactionSessionRef.current;
|
|
118
|
+
if (editingElementRef.current || session.type !== "element") return;
|
|
119
|
+
if (!session.element.isConnected || records.some((record) => session.element.contains(record.target))) {
|
|
120
|
+
scheduleSnapshot();
|
|
78
121
|
}
|
|
79
|
-
getWebsiteBuilderRpc()?.elementSelected({ data: symbolicated });
|
|
80
122
|
});
|
|
81
|
-
|
|
82
|
-
|
|
123
|
+
const watchRender = () => {
|
|
124
|
+
if (editingElementRef.current || interactionSessionRef.current.type !== "element")
|
|
125
|
+
return;
|
|
126
|
+
clearTimeout(observationTimeout);
|
|
127
|
+
observer.observe(document.body, {
|
|
128
|
+
subtree: true,
|
|
129
|
+
childList: true
|
|
130
|
+
});
|
|
131
|
+
observationTimeout = setTimeout(() => observer.disconnect(), 5e3);
|
|
132
|
+
scheduleSnapshot();
|
|
133
|
+
};
|
|
83
134
|
installFastRefreshRelay({
|
|
84
135
|
onComplete: () => {
|
|
85
136
|
reapplyOverrides({ skipElement: editingElementRef.current });
|
|
86
|
-
|
|
137
|
+
watchRender();
|
|
87
138
|
}
|
|
88
139
|
});
|
|
89
|
-
window.addEventListener(
|
|
90
|
-
PREVIEW_RENDERED_EVENT,
|
|
91
|
-
postSelectedElementSnapshot
|
|
92
|
-
);
|
|
140
|
+
window.addEventListener(PREVIEW_RENDERED_EVENT, watchRender);
|
|
93
141
|
return () => {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
);
|
|
142
|
+
clearTimeout(refreshTimeout);
|
|
143
|
+
clearTimeout(missingTimeout);
|
|
144
|
+
clearTimeout(observationTimeout);
|
|
145
|
+
observer.disconnect();
|
|
146
|
+
window.removeEventListener(PREVIEW_RENDERED_EVENT, watchRender);
|
|
98
147
|
installFastRefreshRelay();
|
|
99
148
|
};
|
|
100
|
-
}, [
|
|
149
|
+
}, [
|
|
150
|
+
editingElementRef,
|
|
151
|
+
interactionSessionRef,
|
|
152
|
+
postSelectedElementSnapshot,
|
|
153
|
+
reapplyOverrides
|
|
154
|
+
]);
|
|
101
155
|
useParentMessaging({
|
|
102
156
|
applyOptimisticUpdate,
|
|
103
157
|
markCommitted,
|
|
@@ -10,25 +10,12 @@ function installFastRefreshRelay({
|
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
12
|
hasInstalledFastRefreshRelay = true;
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
if (message.includes("[Fast Refresh] done")) {
|
|
21
|
-
getWebsiteBuilderRpc()?.fastRefreshComplete(void 0);
|
|
22
|
-
onFastRefreshComplete?.();
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
console.log = (...args) => {
|
|
26
|
-
relayIfFastRefreshComplete(...args);
|
|
27
|
-
originalLog(...args);
|
|
28
|
-
};
|
|
29
|
-
console.info = (...args) => {
|
|
30
|
-
relayIfFastRefreshComplete(...args);
|
|
31
|
-
originalInfo(...args);
|
|
13
|
+
const originalCallback = window.__NEXT_HMR_LATENCY_CB;
|
|
14
|
+
window.__NEXT_HMR_LATENCY_CB = (latencyMs) => {
|
|
15
|
+
invalidateSymbolicationCache();
|
|
16
|
+
getWebsiteBuilderRpc()?.fastRefreshComplete(void 0);
|
|
17
|
+
onFastRefreshComplete?.();
|
|
18
|
+
originalCallback?.(latencyMs);
|
|
32
19
|
};
|
|
33
20
|
}
|
|
34
21
|
export {
|
|
@@ -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}: ${
|
|
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" });
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import type { SelectedElement } from "../_vendor/schemas/generated/selectMode";
|
|
1
|
+
import type { SelectedElement, SelectModeSourceLocation } from "../_vendor/schemas/generated/selectMode";
|
|
2
2
|
export declare function invalidateSymbolicationCache(): void;
|
|
3
|
+
export declare function isUserSourceLocation(location: SelectModeSourceLocation | undefined): boolean;
|
|
3
4
|
export declare function symbolicateSelectedElement(selectedElement: SelectedElement): Promise<SelectedElement>;
|
|
@@ -186,9 +186,14 @@ function applyResolved({
|
|
|
186
186
|
componentName: original.componentName
|
|
187
187
|
};
|
|
188
188
|
}
|
|
189
|
+
function isUserSourceLocation(location) {
|
|
190
|
+
return Boolean(
|
|
191
|
+
location && !isLikelyCompiledLocation(location) && !isDependencyOrInternalPath(location.filePath)
|
|
192
|
+
);
|
|
193
|
+
}
|
|
189
194
|
function findUserSourceLocation(fiberChain) {
|
|
190
195
|
return fiberChain.find((entry) => {
|
|
191
|
-
return
|
|
196
|
+
return isUserSourceLocation(entry.sourceLocation);
|
|
192
197
|
})?.sourceLocation;
|
|
193
198
|
}
|
|
194
199
|
async function symbolicateSelectedElement(selectedElement) {
|
|
@@ -235,5 +240,6 @@ async function symbolicateSelectedElement(selectedElement) {
|
|
|
235
240
|
}
|
|
236
241
|
export {
|
|
237
242
|
invalidateSymbolicationCache,
|
|
243
|
+
isUserSourceLocation,
|
|
238
244
|
symbolicateSelectedElement
|
|
239
245
|
};
|