@preprio/toolkit 0.2.0-beta.5 → 0.2.0-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/astro/index.cjs +27 -10
- package/dist/astro/index.js +27 -10
- package/dist/{chunk-BYJ2JBGX.js → chunk-P6VTLWM4.js} +44 -38
- package/dist/index.cjs +71 -48
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +28 -11
- package/dist/nextjs/components.cjs +44 -38
- package/dist/nextjs/components.js +1 -1
- package/dist/nextjs/index.cjs +27 -10
- package/dist/nextjs/index.js +27 -10
- package/dist/nuxt/index.cjs +27 -10
- package/dist/nuxt/index.js +27 -10
- package/dist/react/components.cjs +44 -38
- package/dist/react/components.js +44 -38
- package/dist/sveltekit/index.cjs +27 -10
- package/dist/sveltekit/index.js +27 -10
- package/package.json +12 -12
package/dist/astro/index.cjs
CHANGED
|
@@ -30,7 +30,7 @@ __export(astro_exports, {
|
|
|
30
30
|
module.exports = __toCommonJS(astro_exports);
|
|
31
31
|
|
|
32
32
|
// src/version.ts
|
|
33
|
-
var VERSION = "0.2.0-beta.
|
|
33
|
+
var VERSION = "0.2.0-beta.7";
|
|
34
34
|
|
|
35
35
|
// src/core/features.ts
|
|
36
36
|
function isEnabled(config) {
|
|
@@ -193,6 +193,11 @@ var UTM_PARAMS = [
|
|
|
193
193
|
"utm_content",
|
|
194
194
|
"utm_campaign"
|
|
195
195
|
];
|
|
196
|
+
var MAX_HEADER_VALUE_LENGTH = 2048;
|
|
197
|
+
function sanitizeHeaderValue(value) {
|
|
198
|
+
const stripped = value.replace(/[\u0000-\u001f\u007f]/g, "");
|
|
199
|
+
return stripped.length > MAX_HEADER_VALUE_LENGTH ? stripped.slice(0, MAX_HEADER_VALUE_LENGTH) : stripped;
|
|
200
|
+
}
|
|
196
201
|
function serializeCookie(cookie) {
|
|
197
202
|
const parts = [
|
|
198
203
|
`${cookie.name}=${encodeURIComponent(cookie.value)}`,
|
|
@@ -224,6 +229,15 @@ function parseCookies(request) {
|
|
|
224
229
|
function processPreprRequest(request, opts) {
|
|
225
230
|
const requestHeaders = new Headers(request.headers);
|
|
226
231
|
const responseCookies = [];
|
|
232
|
+
const inboundPreprHeaders = [];
|
|
233
|
+
requestHeaders.forEach((_value, key) => {
|
|
234
|
+
if (key.toLowerCase().startsWith("prepr-")) {
|
|
235
|
+
inboundPreprHeaders.push(key);
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
for (const key of inboundPreprHeaders) {
|
|
239
|
+
requestHeaders.delete(key);
|
|
240
|
+
}
|
|
227
241
|
const requestCookies = parseCookies(request);
|
|
228
242
|
const url = new URL(request.url);
|
|
229
243
|
const searchParams = url.searchParams;
|
|
@@ -233,25 +247,28 @@ function processPreprRequest(request, opts) {
|
|
|
233
247
|
for (const key of UTM_PARAMS) {
|
|
234
248
|
const value = searchParams.get(key);
|
|
235
249
|
if (value !== null) {
|
|
236
|
-
requestHeaders.set(`Prepr-Context-${key}`, value);
|
|
250
|
+
requestHeaders.set(`Prepr-Context-${key}`, sanitizeHeaderValue(value));
|
|
237
251
|
}
|
|
238
252
|
}
|
|
239
253
|
const referer = request.headers.get("referer");
|
|
240
254
|
if (referer) {
|
|
241
|
-
requestHeaders.set(
|
|
255
|
+
requestHeaders.set(
|
|
256
|
+
"Prepr-Context-initial_referral",
|
|
257
|
+
sanitizeHeaderValue(referer)
|
|
258
|
+
);
|
|
242
259
|
}
|
|
243
260
|
const userAgent = request.headers.get("user-agent");
|
|
244
261
|
if (userAgent) {
|
|
245
|
-
requestHeaders.set("Prepr-User-Agent", userAgent);
|
|
262
|
+
requestHeaders.set("Prepr-User-Agent", sanitizeHeaderValue(userAgent));
|
|
246
263
|
}
|
|
247
264
|
requestHeaders.set("Prepr-Package", `@preprio/toolkit@${opts?.version ?? VERSION}`);
|
|
248
265
|
const ip = request.headers.get("Cf-Connecting-Ip") ?? request.headers.get("x-real-ip");
|
|
249
266
|
if (ip) {
|
|
250
|
-
requestHeaders.set("Prepr-Visitor-IP", ip);
|
|
267
|
+
requestHeaders.set("Prepr-Visitor-IP", sanitizeHeaderValue(ip));
|
|
251
268
|
}
|
|
252
269
|
const hutkCookie = requestCookies.get(COOKIE_HUBSPOT);
|
|
253
270
|
if (hutkCookie) {
|
|
254
|
-
requestHeaders.set("Prepr-Hubspot-Id", hutkCookie);
|
|
271
|
+
requestHeaders.set("Prepr-Hubspot-Id", sanitizeHeaderValue(hutkCookie));
|
|
255
272
|
}
|
|
256
273
|
let uid = requestCookies.get(COOKIE_UID);
|
|
257
274
|
if (!uid) {
|
|
@@ -291,16 +308,16 @@ function processPreprRequest(request, opts) {
|
|
|
291
308
|
if (!isLivePreview) {
|
|
292
309
|
const segmentCookie = features.segments ? requestCookies.get(COOKIE_SEGMENT) : void 0;
|
|
293
310
|
if (segmentCookie) {
|
|
294
|
-
requestHeaders.set("Prepr-Segments", segmentCookie);
|
|
311
|
+
requestHeaders.set("Prepr-Segments", sanitizeHeaderValue(segmentCookie));
|
|
295
312
|
}
|
|
296
313
|
const abCookie = features.abTesting ? requestCookies.get(COOKIE_VARIANT) : void 0;
|
|
297
314
|
if (abCookie) {
|
|
298
|
-
requestHeaders.set("Prepr-ABtesting", abCookie);
|
|
315
|
+
requestHeaders.set("Prepr-ABtesting", sanitizeHeaderValue(abCookie));
|
|
299
316
|
}
|
|
300
317
|
}
|
|
301
318
|
const previewAb = features.abTesting ? searchParams.get(PARAM_VARIANT) : null;
|
|
302
319
|
if (previewAb !== null) {
|
|
303
|
-
requestHeaders.set("Prepr-ABtesting", previewAb);
|
|
320
|
+
requestHeaders.set("Prepr-ABtesting", sanitizeHeaderValue(previewAb));
|
|
304
321
|
if (!isLivePreview) {
|
|
305
322
|
responseCookies.push({
|
|
306
323
|
name: COOKIE_VARIANT,
|
|
@@ -313,7 +330,7 @@ function processPreprRequest(request, opts) {
|
|
|
313
330
|
}
|
|
314
331
|
const previewSegment = features.segments ? searchParams.get(PARAM_SEGMENT) : null;
|
|
315
332
|
if (previewSegment !== null) {
|
|
316
|
-
requestHeaders.set("Prepr-Segments", previewSegment);
|
|
333
|
+
requestHeaders.set("Prepr-Segments", sanitizeHeaderValue(previewSegment));
|
|
317
334
|
if (!isLivePreview) {
|
|
318
335
|
responseCookies.push({
|
|
319
336
|
name: COOKIE_SEGMENT,
|
package/dist/astro/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/version.ts
|
|
2
|
-
var VERSION = "0.2.0-beta.
|
|
2
|
+
var VERSION = "0.2.0-beta.7";
|
|
3
3
|
|
|
4
4
|
// src/core/features.ts
|
|
5
5
|
function isEnabled(config) {
|
|
@@ -162,6 +162,11 @@ var UTM_PARAMS = [
|
|
|
162
162
|
"utm_content",
|
|
163
163
|
"utm_campaign"
|
|
164
164
|
];
|
|
165
|
+
var MAX_HEADER_VALUE_LENGTH = 2048;
|
|
166
|
+
function sanitizeHeaderValue(value) {
|
|
167
|
+
const stripped = value.replace(/[\u0000-\u001f\u007f]/g, "");
|
|
168
|
+
return stripped.length > MAX_HEADER_VALUE_LENGTH ? stripped.slice(0, MAX_HEADER_VALUE_LENGTH) : stripped;
|
|
169
|
+
}
|
|
165
170
|
function serializeCookie(cookie) {
|
|
166
171
|
const parts = [
|
|
167
172
|
`${cookie.name}=${encodeURIComponent(cookie.value)}`,
|
|
@@ -193,6 +198,15 @@ function parseCookies(request) {
|
|
|
193
198
|
function processPreprRequest(request, opts) {
|
|
194
199
|
const requestHeaders = new Headers(request.headers);
|
|
195
200
|
const responseCookies = [];
|
|
201
|
+
const inboundPreprHeaders = [];
|
|
202
|
+
requestHeaders.forEach((_value, key) => {
|
|
203
|
+
if (key.toLowerCase().startsWith("prepr-")) {
|
|
204
|
+
inboundPreprHeaders.push(key);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
for (const key of inboundPreprHeaders) {
|
|
208
|
+
requestHeaders.delete(key);
|
|
209
|
+
}
|
|
196
210
|
const requestCookies = parseCookies(request);
|
|
197
211
|
const url = new URL(request.url);
|
|
198
212
|
const searchParams = url.searchParams;
|
|
@@ -202,25 +216,28 @@ function processPreprRequest(request, opts) {
|
|
|
202
216
|
for (const key of UTM_PARAMS) {
|
|
203
217
|
const value = searchParams.get(key);
|
|
204
218
|
if (value !== null) {
|
|
205
|
-
requestHeaders.set(`Prepr-Context-${key}`, value);
|
|
219
|
+
requestHeaders.set(`Prepr-Context-${key}`, sanitizeHeaderValue(value));
|
|
206
220
|
}
|
|
207
221
|
}
|
|
208
222
|
const referer = request.headers.get("referer");
|
|
209
223
|
if (referer) {
|
|
210
|
-
requestHeaders.set(
|
|
224
|
+
requestHeaders.set(
|
|
225
|
+
"Prepr-Context-initial_referral",
|
|
226
|
+
sanitizeHeaderValue(referer)
|
|
227
|
+
);
|
|
211
228
|
}
|
|
212
229
|
const userAgent = request.headers.get("user-agent");
|
|
213
230
|
if (userAgent) {
|
|
214
|
-
requestHeaders.set("Prepr-User-Agent", userAgent);
|
|
231
|
+
requestHeaders.set("Prepr-User-Agent", sanitizeHeaderValue(userAgent));
|
|
215
232
|
}
|
|
216
233
|
requestHeaders.set("Prepr-Package", `@preprio/toolkit@${opts?.version ?? VERSION}`);
|
|
217
234
|
const ip = request.headers.get("Cf-Connecting-Ip") ?? request.headers.get("x-real-ip");
|
|
218
235
|
if (ip) {
|
|
219
|
-
requestHeaders.set("Prepr-Visitor-IP", ip);
|
|
236
|
+
requestHeaders.set("Prepr-Visitor-IP", sanitizeHeaderValue(ip));
|
|
220
237
|
}
|
|
221
238
|
const hutkCookie = requestCookies.get(COOKIE_HUBSPOT);
|
|
222
239
|
if (hutkCookie) {
|
|
223
|
-
requestHeaders.set("Prepr-Hubspot-Id", hutkCookie);
|
|
240
|
+
requestHeaders.set("Prepr-Hubspot-Id", sanitizeHeaderValue(hutkCookie));
|
|
224
241
|
}
|
|
225
242
|
let uid = requestCookies.get(COOKIE_UID);
|
|
226
243
|
if (!uid) {
|
|
@@ -260,16 +277,16 @@ function processPreprRequest(request, opts) {
|
|
|
260
277
|
if (!isLivePreview) {
|
|
261
278
|
const segmentCookie = features.segments ? requestCookies.get(COOKIE_SEGMENT) : void 0;
|
|
262
279
|
if (segmentCookie) {
|
|
263
|
-
requestHeaders.set("Prepr-Segments", segmentCookie);
|
|
280
|
+
requestHeaders.set("Prepr-Segments", sanitizeHeaderValue(segmentCookie));
|
|
264
281
|
}
|
|
265
282
|
const abCookie = features.abTesting ? requestCookies.get(COOKIE_VARIANT) : void 0;
|
|
266
283
|
if (abCookie) {
|
|
267
|
-
requestHeaders.set("Prepr-ABtesting", abCookie);
|
|
284
|
+
requestHeaders.set("Prepr-ABtesting", sanitizeHeaderValue(abCookie));
|
|
268
285
|
}
|
|
269
286
|
}
|
|
270
287
|
const previewAb = features.abTesting ? searchParams.get(PARAM_VARIANT) : null;
|
|
271
288
|
if (previewAb !== null) {
|
|
272
|
-
requestHeaders.set("Prepr-ABtesting", previewAb);
|
|
289
|
+
requestHeaders.set("Prepr-ABtesting", sanitizeHeaderValue(previewAb));
|
|
273
290
|
if (!isLivePreview) {
|
|
274
291
|
responseCookies.push({
|
|
275
292
|
name: COOKIE_VARIANT,
|
|
@@ -282,7 +299,7 @@ function processPreprRequest(request, opts) {
|
|
|
282
299
|
}
|
|
283
300
|
const previewSegment = features.segments ? searchParams.get(PARAM_SEGMENT) : null;
|
|
284
301
|
if (previewSegment !== null) {
|
|
285
|
-
requestHeaders.set("Prepr-Segments", previewSegment);
|
|
302
|
+
requestHeaders.set("Prepr-Segments", sanitizeHeaderValue(previewSegment));
|
|
286
303
|
if (!isLivePreview) {
|
|
287
304
|
responseCookies.push({
|
|
288
305
|
name: COOKIE_SEGMENT,
|
|
@@ -644,6 +644,8 @@ function createStegaAutoClean() {
|
|
|
644
644
|
function scanAndClean() {
|
|
645
645
|
processing = true;
|
|
646
646
|
walkTextNodes(document.body, cleanTextNode);
|
|
647
|
+
const title = vercelStegaSplit(document.title);
|
|
648
|
+
if (title.encoded) document.title = title.cleaned;
|
|
647
649
|
processing = false;
|
|
648
650
|
}
|
|
649
651
|
function collectAffected(mutations) {
|
|
@@ -689,15 +691,8 @@ function createStegaAutoClean() {
|
|
|
689
691
|
}
|
|
690
692
|
function start() {
|
|
691
693
|
if (observer || typeof window === "undefined") return;
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
setupObserver();
|
|
695
|
-
};
|
|
696
|
-
if ("requestIdleCallback" in window) {
|
|
697
|
-
window.requestIdleCallback(run);
|
|
698
|
-
} else {
|
|
699
|
-
setTimeout(run, 0);
|
|
700
|
-
}
|
|
694
|
+
scanAndClean();
|
|
695
|
+
setupObserver();
|
|
701
696
|
debug6.log("stega auto-clean started");
|
|
702
697
|
}
|
|
703
698
|
function stop() {
|
|
@@ -1909,7 +1904,10 @@ function createIframeBridge(store, options = {}) {
|
|
|
1909
1904
|
};
|
|
1910
1905
|
return {
|
|
1911
1906
|
start() {
|
|
1912
|
-
|
|
1907
|
+
const features = store?.get().features;
|
|
1908
|
+
sendPreprEvent("loaded", features ? { features } : void 0, {
|
|
1909
|
+
allowUntrustedTarget: true
|
|
1910
|
+
});
|
|
1913
1911
|
window.addEventListener("keydown", onKeyDown);
|
|
1914
1912
|
window.addEventListener("message", onMessage);
|
|
1915
1913
|
},
|
|
@@ -1931,7 +1929,7 @@ function cookieOpts() {
|
|
|
1931
1929
|
};
|
|
1932
1930
|
}
|
|
1933
1931
|
function createChangeHandler(deps) {
|
|
1934
|
-
const { store, stega,
|
|
1932
|
+
const { store, stega, features, editingEnabled } = deps;
|
|
1935
1933
|
function updateParams(patch) {
|
|
1936
1934
|
const [path, existing] = splitPath(deps.currentPath());
|
|
1937
1935
|
const params = new URLSearchParams(existing);
|
|
@@ -1994,16 +1992,17 @@ function createChangeHandler(deps) {
|
|
|
1994
1992
|
setCookie(COOKIE_PREVIEW_MODE, String(after.previewMode), cookieOpts());
|
|
1995
1993
|
setCookie(COOKIE_TOOLBAR_OPEN, "false", cookieOpts());
|
|
1996
1994
|
sendPreprEvent("preview_mode_toggled", { previewMode: after.previewMode });
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
1995
|
+
if (!after.isIframe) {
|
|
1996
|
+
const [path, existing] = splitPath(deps.currentPath());
|
|
1997
|
+
const params = new URLSearchParams(existing);
|
|
1998
|
+
if (params.has(PARAM_SEGMENT) || params.has(PARAM_VARIANT)) {
|
|
1999
|
+
params.delete(PARAM_SEGMENT);
|
|
2000
|
+
params.delete(PARAM_VARIANT);
|
|
2001
|
+
const query = params.toString();
|
|
2002
|
+
deps.navigate(query ? `${path}?${query}` : path);
|
|
2003
|
+
} else {
|
|
2004
|
+
deps.reload();
|
|
2005
|
+
}
|
|
2007
2006
|
}
|
|
2008
2007
|
}
|
|
2009
2008
|
if (before.toolbarOpen !== after.toolbarOpen) {
|
|
@@ -2026,6 +2025,14 @@ function defaultNavigation() {
|
|
|
2026
2025
|
currentPath: () => window.location.pathname + window.location.search
|
|
2027
2026
|
};
|
|
2028
2027
|
}
|
|
2028
|
+
function safeEditUrl(href) {
|
|
2029
|
+
try {
|
|
2030
|
+
const url = new URL(href, window.location.href);
|
|
2031
|
+
return url.protocol === "https:" || url.protocol === "http:" ? url.href : null;
|
|
2032
|
+
} catch {
|
|
2033
|
+
return null;
|
|
2034
|
+
}
|
|
2035
|
+
}
|
|
2029
2036
|
function buildSegments(data) {
|
|
2030
2037
|
return [{ _id: "all_other_users", name: "All other users" }, ...data];
|
|
2031
2038
|
}
|
|
@@ -2089,24 +2096,25 @@ function createPreprPreview(opts = {}) {
|
|
|
2089
2096
|
// In the editor, ask the parent to focus the field instead of opening a new
|
|
2090
2097
|
// tab. Standalone previews keep the window.open behaviour.
|
|
2091
2098
|
onEdit: ({ href, origin, id, field }) => {
|
|
2099
|
+
const safeHref = href ? safeEditUrl(href) : null;
|
|
2100
|
+
if (href && !safeHref) {
|
|
2101
|
+
debug7.warn("ignored edit request with unsupported href scheme");
|
|
2102
|
+
return;
|
|
2103
|
+
}
|
|
2092
2104
|
if (isIframe) {
|
|
2093
|
-
sendPreprEvent("field_edit_requested", {
|
|
2094
|
-
|
|
2095
|
-
|
|
2105
|
+
sendPreprEvent("field_edit_requested", {
|
|
2106
|
+
href: safeHref ?? void 0,
|
|
2107
|
+
origin,
|
|
2108
|
+
id,
|
|
2109
|
+
field
|
|
2110
|
+
});
|
|
2111
|
+
} else if (safeHref) {
|
|
2112
|
+
window.open(safeHref, "_blank", "noopener,noreferrer");
|
|
2096
2113
|
}
|
|
2097
2114
|
}
|
|
2098
2115
|
});
|
|
2099
2116
|
const autoClean = createStegaAutoClean();
|
|
2100
|
-
|
|
2101
|
-
function syncAutoClean(active) {
|
|
2102
|
-
if (active && !autoCleanActive) {
|
|
2103
|
-
autoClean.start();
|
|
2104
|
-
autoCleanActive = true;
|
|
2105
|
-
} else if (!active && autoCleanActive) {
|
|
2106
|
-
autoClean.stop();
|
|
2107
|
-
autoCleanActive = false;
|
|
2108
|
-
}
|
|
2109
|
-
}
|
|
2117
|
+
autoClean.start();
|
|
2110
2118
|
const handleChange = createChangeHandler({
|
|
2111
2119
|
store,
|
|
2112
2120
|
features,
|
|
@@ -2114,8 +2122,7 @@ function createPreprPreview(opts = {}) {
|
|
|
2114
2122
|
navigate: (url) => navigation.navigate(url),
|
|
2115
2123
|
currentPath: () => navigation.currentPath(),
|
|
2116
2124
|
reload: navigation.reload ?? (() => window.location.reload()),
|
|
2117
|
-
stega
|
|
2118
|
-
syncAutoClean
|
|
2125
|
+
stega
|
|
2119
2126
|
});
|
|
2120
2127
|
let prev = store.get();
|
|
2121
2128
|
const unsubscribe = store.subscribe((state) => {
|
|
@@ -2123,7 +2130,6 @@ function createPreprPreview(opts = {}) {
|
|
|
2123
2130
|
prev = state;
|
|
2124
2131
|
handleChange(before, state);
|
|
2125
2132
|
});
|
|
2126
|
-
syncAutoClean(store.get().previewMode);
|
|
2127
2133
|
const bridge = createIframeBridge(store, {
|
|
2128
2134
|
allowedEditorOrigins: options?.allowedEditorOrigins
|
|
2129
2135
|
});
|
|
@@ -2136,7 +2142,7 @@ function createPreprPreview(opts = {}) {
|
|
|
2136
2142
|
function destroy() {
|
|
2137
2143
|
unsubscribe();
|
|
2138
2144
|
stega.stop();
|
|
2139
|
-
|
|
2145
|
+
autoClean.stop();
|
|
2140
2146
|
if (isIframe) {
|
|
2141
2147
|
bridge.stop();
|
|
2142
2148
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -44,7 +44,7 @@ __export(src_exports, {
|
|
|
44
44
|
module.exports = __toCommonJS(src_exports);
|
|
45
45
|
|
|
46
46
|
// src/version.ts
|
|
47
|
-
var VERSION = "0.2.0-beta.
|
|
47
|
+
var VERSION = "0.2.0-beta.7";
|
|
48
48
|
|
|
49
49
|
// src/core/features.ts
|
|
50
50
|
function isEnabled(config) {
|
|
@@ -355,7 +355,10 @@ function createIframeBridge(store, options = {}) {
|
|
|
355
355
|
};
|
|
356
356
|
return {
|
|
357
357
|
start() {
|
|
358
|
-
|
|
358
|
+
const features = store?.get().features;
|
|
359
|
+
sendPreprEvent("loaded", features ? { features } : void 0, {
|
|
360
|
+
allowUntrustedTarget: true
|
|
361
|
+
});
|
|
359
362
|
window.addEventListener("keydown", onKeyDown);
|
|
360
363
|
window.addEventListener("message", onMessage);
|
|
361
364
|
},
|
|
@@ -461,6 +464,8 @@ function createStegaAutoClean() {
|
|
|
461
464
|
function scanAndClean() {
|
|
462
465
|
processing = true;
|
|
463
466
|
walkTextNodes(document.body, cleanTextNode);
|
|
467
|
+
const title = (0, import_stega2.vercelStegaSplit)(document.title);
|
|
468
|
+
if (title.encoded) document.title = title.cleaned;
|
|
464
469
|
processing = false;
|
|
465
470
|
}
|
|
466
471
|
function collectAffected(mutations) {
|
|
@@ -506,15 +511,8 @@ function createStegaAutoClean() {
|
|
|
506
511
|
}
|
|
507
512
|
function start() {
|
|
508
513
|
if (observer || typeof window === "undefined") return;
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
setupObserver();
|
|
512
|
-
};
|
|
513
|
-
if ("requestIdleCallback" in window) {
|
|
514
|
-
window.requestIdleCallback(run);
|
|
515
|
-
} else {
|
|
516
|
-
setTimeout(run, 0);
|
|
517
|
-
}
|
|
514
|
+
scanAndClean();
|
|
515
|
+
setupObserver();
|
|
518
516
|
debug2.log("stega auto-clean started");
|
|
519
517
|
}
|
|
520
518
|
function stop() {
|
|
@@ -1007,7 +1005,7 @@ function cookieOpts() {
|
|
|
1007
1005
|
};
|
|
1008
1006
|
}
|
|
1009
1007
|
function createChangeHandler(deps) {
|
|
1010
|
-
const { store, stega,
|
|
1008
|
+
const { store, stega, features, editingEnabled } = deps;
|
|
1011
1009
|
function updateParams(patch) {
|
|
1012
1010
|
const [path, existing] = splitPath(deps.currentPath());
|
|
1013
1011
|
const params = new URLSearchParams(existing);
|
|
@@ -1070,16 +1068,17 @@ function createChangeHandler(deps) {
|
|
|
1070
1068
|
setCookie(COOKIE_PREVIEW_MODE, String(after.previewMode), cookieOpts());
|
|
1071
1069
|
setCookie(COOKIE_TOOLBAR_OPEN, "false", cookieOpts());
|
|
1072
1070
|
sendPreprEvent("preview_mode_toggled", { previewMode: after.previewMode });
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1071
|
+
if (!after.isIframe) {
|
|
1072
|
+
const [path, existing] = splitPath(deps.currentPath());
|
|
1073
|
+
const params = new URLSearchParams(existing);
|
|
1074
|
+
if (params.has(PARAM_SEGMENT) || params.has(PARAM_VARIANT)) {
|
|
1075
|
+
params.delete(PARAM_SEGMENT);
|
|
1076
|
+
params.delete(PARAM_VARIANT);
|
|
1077
|
+
const query = params.toString();
|
|
1078
|
+
deps.navigate(query ? `${path}?${query}` : path);
|
|
1079
|
+
} else {
|
|
1080
|
+
deps.reload();
|
|
1081
|
+
}
|
|
1083
1082
|
}
|
|
1084
1083
|
}
|
|
1085
1084
|
if (before.toolbarOpen !== after.toolbarOpen) {
|
|
@@ -2074,6 +2073,14 @@ function defaultNavigation() {
|
|
|
2074
2073
|
currentPath: () => window.location.pathname + window.location.search
|
|
2075
2074
|
};
|
|
2076
2075
|
}
|
|
2076
|
+
function safeEditUrl(href) {
|
|
2077
|
+
try {
|
|
2078
|
+
const url = new URL(href, window.location.href);
|
|
2079
|
+
return url.protocol === "https:" || url.protocol === "http:" ? url.href : null;
|
|
2080
|
+
} catch {
|
|
2081
|
+
return null;
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2077
2084
|
function buildSegments(data) {
|
|
2078
2085
|
return [{ _id: "all_other_users", name: "All other users" }, ...data];
|
|
2079
2086
|
}
|
|
@@ -2137,24 +2144,25 @@ function createPreprPreview(opts = {}) {
|
|
|
2137
2144
|
// In the editor, ask the parent to focus the field instead of opening a new
|
|
2138
2145
|
// tab. Standalone previews keep the window.open behaviour.
|
|
2139
2146
|
onEdit: ({ href, origin, id, field }) => {
|
|
2147
|
+
const safeHref = href ? safeEditUrl(href) : null;
|
|
2148
|
+
if (href && !safeHref) {
|
|
2149
|
+
debug7.warn("ignored edit request with unsupported href scheme");
|
|
2150
|
+
return;
|
|
2151
|
+
}
|
|
2140
2152
|
if (isIframe) {
|
|
2141
|
-
sendPreprEvent("field_edit_requested", {
|
|
2142
|
-
|
|
2143
|
-
|
|
2153
|
+
sendPreprEvent("field_edit_requested", {
|
|
2154
|
+
href: safeHref ?? void 0,
|
|
2155
|
+
origin,
|
|
2156
|
+
id,
|
|
2157
|
+
field
|
|
2158
|
+
});
|
|
2159
|
+
} else if (safeHref) {
|
|
2160
|
+
window.open(safeHref, "_blank", "noopener,noreferrer");
|
|
2144
2161
|
}
|
|
2145
2162
|
}
|
|
2146
2163
|
});
|
|
2147
2164
|
const autoClean = createStegaAutoClean();
|
|
2148
|
-
|
|
2149
|
-
function syncAutoClean(active) {
|
|
2150
|
-
if (active && !autoCleanActive) {
|
|
2151
|
-
autoClean.start();
|
|
2152
|
-
autoCleanActive = true;
|
|
2153
|
-
} else if (!active && autoCleanActive) {
|
|
2154
|
-
autoClean.stop();
|
|
2155
|
-
autoCleanActive = false;
|
|
2156
|
-
}
|
|
2157
|
-
}
|
|
2165
|
+
autoClean.start();
|
|
2158
2166
|
const handleChange = createChangeHandler({
|
|
2159
2167
|
store,
|
|
2160
2168
|
features,
|
|
@@ -2162,8 +2170,7 @@ function createPreprPreview(opts = {}) {
|
|
|
2162
2170
|
navigate: (url) => navigation.navigate(url),
|
|
2163
2171
|
currentPath: () => navigation.currentPath(),
|
|
2164
2172
|
reload: navigation.reload ?? (() => window.location.reload()),
|
|
2165
|
-
stega
|
|
2166
|
-
syncAutoClean
|
|
2173
|
+
stega
|
|
2167
2174
|
});
|
|
2168
2175
|
let prev = store.get();
|
|
2169
2176
|
const unsubscribe = store.subscribe((state) => {
|
|
@@ -2171,7 +2178,6 @@ function createPreprPreview(opts = {}) {
|
|
|
2171
2178
|
prev = state;
|
|
2172
2179
|
handleChange(before, state);
|
|
2173
2180
|
});
|
|
2174
|
-
syncAutoClean(store.get().previewMode);
|
|
2175
2181
|
const bridge = createIframeBridge(store, {
|
|
2176
2182
|
allowedEditorOrigins: options?.allowedEditorOrigins
|
|
2177
2183
|
});
|
|
@@ -2184,7 +2190,7 @@ function createPreprPreview(opts = {}) {
|
|
|
2184
2190
|
function destroy() {
|
|
2185
2191
|
unsubscribe();
|
|
2186
2192
|
stega.stop();
|
|
2187
|
-
|
|
2193
|
+
autoClean.stop();
|
|
2188
2194
|
if (isIframe) {
|
|
2189
2195
|
bridge.stop();
|
|
2190
2196
|
}
|
|
@@ -2358,6 +2364,11 @@ var UTM_PARAMS = [
|
|
|
2358
2364
|
"utm_content",
|
|
2359
2365
|
"utm_campaign"
|
|
2360
2366
|
];
|
|
2367
|
+
var MAX_HEADER_VALUE_LENGTH = 2048;
|
|
2368
|
+
function sanitizeHeaderValue(value) {
|
|
2369
|
+
const stripped = value.replace(/[\u0000-\u001f\u007f]/g, "");
|
|
2370
|
+
return stripped.length > MAX_HEADER_VALUE_LENGTH ? stripped.slice(0, MAX_HEADER_VALUE_LENGTH) : stripped;
|
|
2371
|
+
}
|
|
2361
2372
|
function parseCookies(request) {
|
|
2362
2373
|
const cookies = /* @__PURE__ */ new Map();
|
|
2363
2374
|
const header = request.headers.get("cookie");
|
|
@@ -2375,6 +2386,15 @@ function parseCookies(request) {
|
|
|
2375
2386
|
function processPreprRequest(request, opts) {
|
|
2376
2387
|
const requestHeaders = new Headers(request.headers);
|
|
2377
2388
|
const responseCookies = [];
|
|
2389
|
+
const inboundPreprHeaders = [];
|
|
2390
|
+
requestHeaders.forEach((_value, key) => {
|
|
2391
|
+
if (key.toLowerCase().startsWith("prepr-")) {
|
|
2392
|
+
inboundPreprHeaders.push(key);
|
|
2393
|
+
}
|
|
2394
|
+
});
|
|
2395
|
+
for (const key of inboundPreprHeaders) {
|
|
2396
|
+
requestHeaders.delete(key);
|
|
2397
|
+
}
|
|
2378
2398
|
const requestCookies = parseCookies(request);
|
|
2379
2399
|
const url = new URL(request.url);
|
|
2380
2400
|
const searchParams = url.searchParams;
|
|
@@ -2384,25 +2404,28 @@ function processPreprRequest(request, opts) {
|
|
|
2384
2404
|
for (const key of UTM_PARAMS) {
|
|
2385
2405
|
const value = searchParams.get(key);
|
|
2386
2406
|
if (value !== null) {
|
|
2387
|
-
requestHeaders.set(`Prepr-Context-${key}`, value);
|
|
2407
|
+
requestHeaders.set(`Prepr-Context-${key}`, sanitizeHeaderValue(value));
|
|
2388
2408
|
}
|
|
2389
2409
|
}
|
|
2390
2410
|
const referer = request.headers.get("referer");
|
|
2391
2411
|
if (referer) {
|
|
2392
|
-
requestHeaders.set(
|
|
2412
|
+
requestHeaders.set(
|
|
2413
|
+
"Prepr-Context-initial_referral",
|
|
2414
|
+
sanitizeHeaderValue(referer)
|
|
2415
|
+
);
|
|
2393
2416
|
}
|
|
2394
2417
|
const userAgent = request.headers.get("user-agent");
|
|
2395
2418
|
if (userAgent) {
|
|
2396
|
-
requestHeaders.set("Prepr-User-Agent", userAgent);
|
|
2419
|
+
requestHeaders.set("Prepr-User-Agent", sanitizeHeaderValue(userAgent));
|
|
2397
2420
|
}
|
|
2398
2421
|
requestHeaders.set("Prepr-Package", `@preprio/toolkit@${opts?.version ?? VERSION}`);
|
|
2399
2422
|
const ip = request.headers.get("Cf-Connecting-Ip") ?? request.headers.get("x-real-ip");
|
|
2400
2423
|
if (ip) {
|
|
2401
|
-
requestHeaders.set("Prepr-Visitor-IP", ip);
|
|
2424
|
+
requestHeaders.set("Prepr-Visitor-IP", sanitizeHeaderValue(ip));
|
|
2402
2425
|
}
|
|
2403
2426
|
const hutkCookie = requestCookies.get(COOKIE_HUBSPOT);
|
|
2404
2427
|
if (hutkCookie) {
|
|
2405
|
-
requestHeaders.set("Prepr-Hubspot-Id", hutkCookie);
|
|
2428
|
+
requestHeaders.set("Prepr-Hubspot-Id", sanitizeHeaderValue(hutkCookie));
|
|
2406
2429
|
}
|
|
2407
2430
|
let uid = requestCookies.get(COOKIE_UID);
|
|
2408
2431
|
if (!uid) {
|
|
@@ -2442,16 +2465,16 @@ function processPreprRequest(request, opts) {
|
|
|
2442
2465
|
if (!isLivePreview) {
|
|
2443
2466
|
const segmentCookie = features.segments ? requestCookies.get(COOKIE_SEGMENT) : void 0;
|
|
2444
2467
|
if (segmentCookie) {
|
|
2445
|
-
requestHeaders.set("Prepr-Segments", segmentCookie);
|
|
2468
|
+
requestHeaders.set("Prepr-Segments", sanitizeHeaderValue(segmentCookie));
|
|
2446
2469
|
}
|
|
2447
2470
|
const abCookie = features.abTesting ? requestCookies.get(COOKIE_VARIANT) : void 0;
|
|
2448
2471
|
if (abCookie) {
|
|
2449
|
-
requestHeaders.set("Prepr-ABtesting", abCookie);
|
|
2472
|
+
requestHeaders.set("Prepr-ABtesting", sanitizeHeaderValue(abCookie));
|
|
2450
2473
|
}
|
|
2451
2474
|
}
|
|
2452
2475
|
const previewAb = features.abTesting ? searchParams.get(PARAM_VARIANT) : null;
|
|
2453
2476
|
if (previewAb !== null) {
|
|
2454
|
-
requestHeaders.set("Prepr-ABtesting", previewAb);
|
|
2477
|
+
requestHeaders.set("Prepr-ABtesting", sanitizeHeaderValue(previewAb));
|
|
2455
2478
|
if (!isLivePreview) {
|
|
2456
2479
|
responseCookies.push({
|
|
2457
2480
|
name: COOKIE_VARIANT,
|
|
@@ -2464,7 +2487,7 @@ function processPreprRequest(request, opts) {
|
|
|
2464
2487
|
}
|
|
2465
2488
|
const previewSegment = features.segments ? searchParams.get(PARAM_SEGMENT) : null;
|
|
2466
2489
|
if (previewSegment !== null) {
|
|
2467
|
-
requestHeaders.set("Prepr-Segments", previewSegment);
|
|
2490
|
+
requestHeaders.set("Prepr-Segments", sanitizeHeaderValue(previewSegment));
|
|
2468
2491
|
if (!isLivePreview) {
|
|
2469
2492
|
responseCookies.push({
|
|
2470
2493
|
name: COOKIE_SEGMENT,
|
package/dist/index.d.cts
CHANGED
|
@@ -5,7 +5,7 @@ export { g as PreprEnvironment, h as PreprEventType, i as PreprFeatureConfig, j
|
|
|
5
5
|
* Package version; must match package.json. Lives in its own leaf module so
|
|
6
6
|
* core can import it without cycling through the barrel.
|
|
7
7
|
*/
|
|
8
|
-
declare const VERSION = "0.2.0-beta.
|
|
8
|
+
declare const VERSION = "0.2.0-beta.7";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Resolve a `PreprFeatures` bag to plain booleans, defaulting every omitted key
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export { g as PreprEnvironment, h as PreprEventType, i as PreprFeatureConfig, j
|
|
|
5
5
|
* Package version; must match package.json. Lives in its own leaf module so
|
|
6
6
|
* core can import it without cycling through the barrel.
|
|
7
7
|
*/
|
|
8
|
-
declare const VERSION = "0.2.0-beta.
|
|
8
|
+
declare const VERSION = "0.2.0-beta.7";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Resolve a `PreprFeatures` bag to plain booleans, defaulting every omitted key
|