@preprio/toolkit 0.4.2 → 0.5.0-rc.1
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 +3 -3
- package/dist/astro/index.d.cts +3 -0
- package/dist/astro/index.d.ts +3 -0
- package/dist/astro/index.js +3 -3
- package/dist/{chunk-72BQJDDK.js → chunk-4JNKYIEV.js} +90 -12
- package/dist/index.cjs +112 -34
- package/dist/index.d.cts +14 -3
- package/dist/index.d.ts +14 -3
- package/dist/index.js +3 -3
- package/dist/nextjs/components.cjs +110 -32
- package/dist/nextjs/components.d.cts +1 -1
- package/dist/nextjs/components.d.ts +1 -1
- package/dist/nextjs/components.js +1 -1
- package/dist/nextjs/index.cjs +3 -3
- package/dist/nextjs/index.d.cts +3 -0
- package/dist/nextjs/index.d.ts +3 -0
- package/dist/nextjs/index.js +3 -3
- package/dist/nuxt/index.cjs +3 -3
- package/dist/nuxt/index.d.cts +3 -0
- package/dist/nuxt/index.d.ts +3 -0
- package/dist/nuxt/index.js +3 -3
- package/dist/{pixel-Wsfvw9G2.d.cts → pixel-e1fUWl2Y.d.cts} +4 -1
- package/dist/{pixel-Wsfvw9G2.d.ts → pixel-e1fUWl2Y.d.ts} +4 -1
- package/dist/react/components.cjs +110 -32
- package/dist/react/components.js +110 -32
- package/dist/sveltekit/index.cjs +3 -3
- package/dist/sveltekit/index.d.cts +3 -0
- package/dist/sveltekit/index.d.ts +3 -0
- package/dist/sveltekit/index.js +3 -3
- package/package.json +1 -1
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.
|
|
33
|
+
var VERSION = "0.5.0-rc.1";
|
|
34
34
|
|
|
35
35
|
// src/core/features.ts
|
|
36
36
|
function isEnabled(config) {
|
|
@@ -83,7 +83,7 @@ var PREPR_HEADER_KEYS = [
|
|
|
83
83
|
"Prepr-Visitor-IP",
|
|
84
84
|
"Prepr-Hubspot-Id",
|
|
85
85
|
"Prepr-Customer-Id-Created",
|
|
86
|
-
"
|
|
86
|
+
"User-Agent",
|
|
87
87
|
"Prepr-Package"
|
|
88
88
|
];
|
|
89
89
|
function getPreprHeadersFromHeaders(headers) {
|
|
@@ -272,7 +272,7 @@ function processFrameworkRequest(request, opts, framework) {
|
|
|
272
272
|
}
|
|
273
273
|
const userAgent = request.headers.get("user-agent");
|
|
274
274
|
if (userAgent) {
|
|
275
|
-
requestHeaders.set("
|
|
275
|
+
requestHeaders.set("User-Agent", sanitizeHeaderValue(userAgent));
|
|
276
276
|
}
|
|
277
277
|
const packageParts = [`@preprio/toolkit@${opts?.version ?? VERSION}`];
|
|
278
278
|
if (framework) packageParts.push(`framework=${framework}`);
|
package/dist/astro/index.d.cts
CHANGED
|
@@ -59,6 +59,9 @@ interface PreprHeaders {
|
|
|
59
59
|
readonly 'Prepr-Visitor-IP'?: string;
|
|
60
60
|
readonly 'Prepr-Hubspot-Id'?: string;
|
|
61
61
|
readonly 'Prepr-Customer-Id-Created'?: 'true';
|
|
62
|
+
/** The visitor's browser User-Agent, used by the API for device detection. */
|
|
63
|
+
readonly 'User-Agent'?: string;
|
|
64
|
+
/** @deprecated Never populated; the visitor's value is under `User-Agent`. */
|
|
62
65
|
readonly 'Prepr-User-Agent'?: string;
|
|
63
66
|
readonly 'Prepr-Package'?: string;
|
|
64
67
|
}
|
package/dist/astro/index.d.ts
CHANGED
|
@@ -59,6 +59,9 @@ interface PreprHeaders {
|
|
|
59
59
|
readonly 'Prepr-Visitor-IP'?: string;
|
|
60
60
|
readonly 'Prepr-Hubspot-Id'?: string;
|
|
61
61
|
readonly 'Prepr-Customer-Id-Created'?: 'true';
|
|
62
|
+
/** The visitor's browser User-Agent, used by the API for device detection. */
|
|
63
|
+
readonly 'User-Agent'?: string;
|
|
64
|
+
/** @deprecated Never populated; the visitor's value is under `User-Agent`. */
|
|
62
65
|
readonly 'Prepr-User-Agent'?: string;
|
|
63
66
|
readonly 'Prepr-Package'?: string;
|
|
64
67
|
}
|
package/dist/astro/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/version.ts
|
|
2
|
-
var VERSION = "0.
|
|
2
|
+
var VERSION = "0.5.0-rc.1";
|
|
3
3
|
|
|
4
4
|
// src/core/features.ts
|
|
5
5
|
function isEnabled(config) {
|
|
@@ -52,7 +52,7 @@ var PREPR_HEADER_KEYS = [
|
|
|
52
52
|
"Prepr-Visitor-IP",
|
|
53
53
|
"Prepr-Hubspot-Id",
|
|
54
54
|
"Prepr-Customer-Id-Created",
|
|
55
|
-
"
|
|
55
|
+
"User-Agent",
|
|
56
56
|
"Prepr-Package"
|
|
57
57
|
];
|
|
58
58
|
function getPreprHeadersFromHeaders(headers) {
|
|
@@ -241,7 +241,7 @@ function processFrameworkRequest(request, opts, framework) {
|
|
|
241
241
|
}
|
|
242
242
|
const userAgent = request.headers.get("user-agent");
|
|
243
243
|
if (userAgent) {
|
|
244
|
-
requestHeaders.set("
|
|
244
|
+
requestHeaders.set("User-Agent", sanitizeHeaderValue(userAgent));
|
|
245
245
|
}
|
|
246
246
|
const packageParts = [`@preprio/toolkit@${opts?.version ?? VERSION}`];
|
|
247
247
|
if (framework) packageParts.push(`framework=${framework}`);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/version.ts
|
|
2
|
-
var VERSION = "0.
|
|
2
|
+
var VERSION = "0.5.0-rc.1";
|
|
3
3
|
|
|
4
4
|
// src/core/features.ts
|
|
5
5
|
function isEnabled(config) {
|
|
@@ -186,10 +186,33 @@ function isRenderedElement(element) {
|
|
|
186
186
|
if (!style) return true;
|
|
187
187
|
return style.visibility !== "hidden" && style.display !== "none";
|
|
188
188
|
}
|
|
189
|
+
function parseEditHref(href) {
|
|
190
|
+
try {
|
|
191
|
+
const url = new URL(href, window.location.origin);
|
|
192
|
+
return {
|
|
193
|
+
id: url.pathname.split("/").pop() || void 0,
|
|
194
|
+
field: url.searchParams.get("field") || void 0,
|
|
195
|
+
locale: url.searchParams.get("locale") || void 0
|
|
196
|
+
};
|
|
197
|
+
} catch {
|
|
198
|
+
return {};
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
function setOrRemove(element, name, value) {
|
|
202
|
+
if (value) {
|
|
203
|
+
element.setAttribute(name, value);
|
|
204
|
+
} else {
|
|
205
|
+
element.removeAttribute(name);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
189
208
|
function tagEncodedElement(element, decoded) {
|
|
190
209
|
element.setAttribute("data-prepr-encoded", "");
|
|
191
210
|
element.setAttribute("data-prepr-href", decoded.href);
|
|
192
211
|
element.setAttribute("data-prepr-origin", decoded.origin);
|
|
212
|
+
const { id, field, locale } = parseEditHref(decoded.href);
|
|
213
|
+
setOrRemove(element, "data-prepr-id", id);
|
|
214
|
+
setOrRemove(element, "data-prepr-field", field);
|
|
215
|
+
setOrRemove(element, "data-prepr-locale", locale);
|
|
193
216
|
}
|
|
194
217
|
|
|
195
218
|
// src/core/stega/elements.ts
|
|
@@ -294,6 +317,9 @@ var StegaElements = class {
|
|
|
294
317
|
element.removeAttribute("data-prepr-encoded");
|
|
295
318
|
element.removeAttribute("data-prepr-href");
|
|
296
319
|
element.removeAttribute("data-prepr-origin");
|
|
320
|
+
element.removeAttribute("data-prepr-id");
|
|
321
|
+
element.removeAttribute("data-prepr-field");
|
|
322
|
+
element.removeAttribute("data-prepr-locale");
|
|
297
323
|
element.classList.remove("prepr-overlay-active");
|
|
298
324
|
});
|
|
299
325
|
this.elements = void 0;
|
|
@@ -346,6 +372,7 @@ var StegaOverlay = class {
|
|
|
346
372
|
const origin = element.getAttribute("data-prepr-origin");
|
|
347
373
|
const id = element.getAttribute("data-prepr-id") ?? void 0;
|
|
348
374
|
const field = element.getAttribute("data-prepr-field") ?? void 0;
|
|
375
|
+
const locale = element.getAttribute("data-prepr-locale") ?? void 0;
|
|
349
376
|
debug3.log("showing overlay", { href, origin });
|
|
350
377
|
const overlay = this.overlay;
|
|
351
378
|
overlay.style.display = "block";
|
|
@@ -378,7 +405,7 @@ var StegaOverlay = class {
|
|
|
378
405
|
tooltip.style.left = `${left}px`;
|
|
379
406
|
});
|
|
380
407
|
tooltip.onclick = () => {
|
|
381
|
-
this.onEdit({ href, origin, id, field });
|
|
408
|
+
this.onEdit({ href, origin, id, field, locale });
|
|
382
409
|
};
|
|
383
410
|
}
|
|
384
411
|
this.currentElement = element;
|
|
@@ -558,7 +585,8 @@ function createStegaController(opts) {
|
|
|
558
585
|
href: encoded.getAttribute("data-prepr-href") ?? "",
|
|
559
586
|
origin: encoded.getAttribute("data-prepr-origin") ?? "",
|
|
560
587
|
id: encoded.getAttribute("data-prepr-id") ?? void 0,
|
|
561
|
-
field: encoded.getAttribute("data-prepr-field") ?? void 0
|
|
588
|
+
field: encoded.getAttribute("data-prepr-field") ?? void 0,
|
|
589
|
+
locale: encoded.getAttribute("data-prepr-locale") ?? void 0
|
|
562
590
|
});
|
|
563
591
|
};
|
|
564
592
|
const start = () => {
|
|
@@ -788,6 +816,38 @@ function createStegaAutoClean(options) {
|
|
|
788
816
|
return { start, stop };
|
|
789
817
|
}
|
|
790
818
|
|
|
819
|
+
// src/core/stega/scroll-to-field.ts
|
|
820
|
+
var debug7 = createScopedLogger("stega:scroll");
|
|
821
|
+
var FLASH_DURATION_MS = 1200;
|
|
822
|
+
var flashTimeout = null;
|
|
823
|
+
function scrollToField(request) {
|
|
824
|
+
const { field, id } = request;
|
|
825
|
+
if (!field) return false;
|
|
826
|
+
const candidates = document.querySelectorAll(
|
|
827
|
+
"[data-prepr-encoded]"
|
|
828
|
+
);
|
|
829
|
+
let target = null;
|
|
830
|
+
for (const candidate of candidates) {
|
|
831
|
+
if (candidate.getAttribute("data-prepr-field") !== field) continue;
|
|
832
|
+
if (id && candidate.getAttribute("data-prepr-id") !== id) continue;
|
|
833
|
+
target = candidate;
|
|
834
|
+
break;
|
|
835
|
+
}
|
|
836
|
+
if (!target) {
|
|
837
|
+
debug7.log("no element found for field", field);
|
|
838
|
+
return false;
|
|
839
|
+
}
|
|
840
|
+
target.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
841
|
+
if (flashTimeout) clearTimeout(flashTimeout);
|
|
842
|
+
document.querySelectorAll(".prepr-overlay-active").forEach((el) => el.classList.remove("prepr-overlay-active"));
|
|
843
|
+
target.classList.add("prepr-overlay-active");
|
|
844
|
+
flashTimeout = setTimeout(() => {
|
|
845
|
+
target.classList.remove("prepr-overlay-active");
|
|
846
|
+
flashTimeout = null;
|
|
847
|
+
}, FLASH_DURATION_MS);
|
|
848
|
+
return true;
|
|
849
|
+
}
|
|
850
|
+
|
|
791
851
|
// src/core/store.ts
|
|
792
852
|
var DEFAULT_STATE = {
|
|
793
853
|
locale: "en",
|
|
@@ -1944,6 +2004,7 @@ function t2(key, locale, vars) {
|
|
|
1944
2004
|
}
|
|
1945
2005
|
|
|
1946
2006
|
// src/core/iframe-bridge.ts
|
|
2007
|
+
var debug8 = createScopedLogger("iframe-bridge");
|
|
1947
2008
|
var EDITOR_BASE_DOMAIN = "prepr.io";
|
|
1948
2009
|
function isAllowedEditorOrigin(origin, allowed) {
|
|
1949
2010
|
if (allowed) return allowed.includes(origin);
|
|
@@ -1961,6 +2022,7 @@ function isAllowedEditorOrigin(origin, allowed) {
|
|
|
1961
2022
|
}
|
|
1962
2023
|
function createIframeBridge(store, options = {}) {
|
|
1963
2024
|
const allowedOrigins = options.allowedEditorOrigins;
|
|
2025
|
+
const onScrollToField = options.onScrollToField;
|
|
1964
2026
|
let parentOrigin = null;
|
|
1965
2027
|
const onKeyDown = (event) => {
|
|
1966
2028
|
const key = event.key.toLowerCase();
|
|
@@ -1984,6 +2046,15 @@ function createIframeBridge(store, options = {}) {
|
|
|
1984
2046
|
const currentScrollY = window.scrollY || document.documentElement.scrollTop;
|
|
1985
2047
|
sendPreprEvent("getScrollPosition", { value: currentScrollY });
|
|
1986
2048
|
}
|
|
2049
|
+
if (data?.event === "prepr:scrollToField") {
|
|
2050
|
+
if (typeof data.field !== "string" || !data.field) return;
|
|
2051
|
+
if (data.id !== void 0 && typeof data.id !== "string") return;
|
|
2052
|
+
try {
|
|
2053
|
+
onScrollToField?.({ field: data.field, id: data.id });
|
|
2054
|
+
} catch (error) {
|
|
2055
|
+
debug8.warn("scrollToField handler failed", error);
|
|
2056
|
+
}
|
|
2057
|
+
}
|
|
1987
2058
|
};
|
|
1988
2059
|
return {
|
|
1989
2060
|
start() {
|
|
@@ -2102,7 +2173,7 @@ function splitPath(full) {
|
|
|
2102
2173
|
}
|
|
2103
2174
|
|
|
2104
2175
|
// src/core/create-preview.ts
|
|
2105
|
-
var
|
|
2176
|
+
var debug9 = createScopedLogger("create-preview");
|
|
2106
2177
|
var controllerStores = /* @__PURE__ */ new WeakMap();
|
|
2107
2178
|
function defaultNavigation() {
|
|
2108
2179
|
return {
|
|
@@ -2144,7 +2215,7 @@ function createPreprPreview(opts = {}) {
|
|
|
2144
2215
|
const search = new URLSearchParams(window.location.search);
|
|
2145
2216
|
const hideBar = search.get(PARAM_HIDE_BAR) === "true";
|
|
2146
2217
|
if (hideBar) {
|
|
2147
|
-
|
|
2218
|
+
debug9.log(`${PARAM_HIDE_BAR}=true \u2014 no visible toolbar`);
|
|
2148
2219
|
}
|
|
2149
2220
|
const mountUi = (options?.ui ?? true) && !isIframe && !hideBar;
|
|
2150
2221
|
const locale = resolveLocale(options);
|
|
@@ -2180,18 +2251,17 @@ function createPreprPreview(opts = {}) {
|
|
|
2180
2251
|
tooltip: mountUi,
|
|
2181
2252
|
// In the editor, ask the parent to focus the field instead of opening a new
|
|
2182
2253
|
// tab. Standalone previews keep the window.open behaviour.
|
|
2183
|
-
onEdit: ({ href,
|
|
2254
|
+
onEdit: ({ href, id, field, locale: contentLocale }) => {
|
|
2184
2255
|
const safeHref = href ? safeEditUrl(href) : null;
|
|
2185
2256
|
if (href && !safeHref) {
|
|
2186
|
-
|
|
2257
|
+
debug9.warn("ignored edit request with unsupported href scheme");
|
|
2187
2258
|
return;
|
|
2188
2259
|
}
|
|
2189
2260
|
if (isIframe) {
|
|
2190
2261
|
sendPreprEvent("field_edit_requested", {
|
|
2191
|
-
href: safeHref ?? void 0,
|
|
2192
|
-
origin,
|
|
2193
2262
|
id,
|
|
2194
|
-
field
|
|
2263
|
+
field,
|
|
2264
|
+
locale: contentLocale
|
|
2195
2265
|
});
|
|
2196
2266
|
} else if (safeHref) {
|
|
2197
2267
|
window.open(safeHref, "_blank", "noopener,noreferrer");
|
|
@@ -2218,7 +2288,15 @@ function createPreprPreview(opts = {}) {
|
|
|
2218
2288
|
handleChange(before, state);
|
|
2219
2289
|
});
|
|
2220
2290
|
const bridge = createIframeBridge(store, {
|
|
2221
|
-
allowedEditorOrigins: options?.allowedEditorOrigins
|
|
2291
|
+
allowedEditorOrigins: options?.allowedEditorOrigins,
|
|
2292
|
+
// The editor selecting a field scrolls the matching element into view. The
|
|
2293
|
+
// lookup relies on the attributes the stega scan writes, so it finds
|
|
2294
|
+
// nothing until encoded content has been tagged.
|
|
2295
|
+
onScrollToField: ({ field, id }) => {
|
|
2296
|
+
if (!scrollToField({ field, id })) {
|
|
2297
|
+
debug9.log("no element on this page renders field", field);
|
|
2298
|
+
}
|
|
2299
|
+
}
|
|
2222
2300
|
});
|
|
2223
2301
|
sendPreprEvent(
|
|
2224
2302
|
"getScrollPosition",
|
|
@@ -2238,7 +2316,7 @@ function createPreprPreview(opts = {}) {
|
|
|
2238
2316
|
bridge.stop();
|
|
2239
2317
|
}
|
|
2240
2318
|
el?.remove();
|
|
2241
|
-
|
|
2319
|
+
debug9.log("preview destroyed");
|
|
2242
2320
|
}
|
|
2243
2321
|
const controller = { destroy };
|
|
2244
2322
|
controllerStores.set(controller, store);
|
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.
|
|
47
|
+
var VERSION = "0.5.0-rc.1";
|
|
48
48
|
|
|
49
49
|
// src/core/features.ts
|
|
50
50
|
function isEnabled(config) {
|
|
@@ -312,6 +312,7 @@ function createElementCache(query, ttl = 1e3) {
|
|
|
312
312
|
}
|
|
313
313
|
|
|
314
314
|
// src/core/iframe-bridge.ts
|
|
315
|
+
var debug = createScopedLogger("iframe-bridge");
|
|
315
316
|
var EDITOR_BASE_DOMAIN = "prepr.io";
|
|
316
317
|
function isAllowedEditorOrigin(origin, allowed) {
|
|
317
318
|
if (allowed) return allowed.includes(origin);
|
|
@@ -329,6 +330,7 @@ function isAllowedEditorOrigin(origin, allowed) {
|
|
|
329
330
|
}
|
|
330
331
|
function createIframeBridge(store, options = {}) {
|
|
331
332
|
const allowedOrigins = options.allowedEditorOrigins;
|
|
333
|
+
const onScrollToField = options.onScrollToField;
|
|
332
334
|
let parentOrigin = null;
|
|
333
335
|
const onKeyDown = (event) => {
|
|
334
336
|
const key = event.key.toLowerCase();
|
|
@@ -352,6 +354,15 @@ function createIframeBridge(store, options = {}) {
|
|
|
352
354
|
const currentScrollY = window.scrollY || document.documentElement.scrollTop;
|
|
353
355
|
sendPreprEvent("getScrollPosition", { value: currentScrollY });
|
|
354
356
|
}
|
|
357
|
+
if (data?.event === "prepr:scrollToField") {
|
|
358
|
+
if (typeof data.field !== "string" || !data.field) return;
|
|
359
|
+
if (data.id !== void 0 && typeof data.id !== "string") return;
|
|
360
|
+
try {
|
|
361
|
+
onScrollToField?.({ field: data.field, id: data.id });
|
|
362
|
+
} catch (error) {
|
|
363
|
+
debug.warn("scrollToField handler failed", error);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
355
366
|
};
|
|
356
367
|
return {
|
|
357
368
|
start() {
|
|
@@ -376,7 +387,7 @@ var import_stega2 = require("@vercel/stega");
|
|
|
376
387
|
|
|
377
388
|
// src/core/stega/clean.ts
|
|
378
389
|
var import_stega = require("@vercel/stega");
|
|
379
|
-
var
|
|
390
|
+
var debug2 = createScopedLogger("stega:clean");
|
|
380
391
|
function stegaClean(text) {
|
|
381
392
|
if (!text) return text;
|
|
382
393
|
return (0, import_stega.vercelStegaClean)(text);
|
|
@@ -389,7 +400,7 @@ function decodeStega(str) {
|
|
|
389
400
|
return decoded;
|
|
390
401
|
}
|
|
391
402
|
} catch (error) {
|
|
392
|
-
|
|
403
|
+
debug2.log("error decoding stega data", error);
|
|
393
404
|
const match = str.match(/{"origin.*?}/);
|
|
394
405
|
if (match) {
|
|
395
406
|
try {
|
|
@@ -398,7 +409,7 @@ function decodeStega(str) {
|
|
|
398
409
|
return decodedMatch;
|
|
399
410
|
}
|
|
400
411
|
} catch (innerError) {
|
|
401
|
-
|
|
412
|
+
debug2.log("error decoding stega regex match", innerError);
|
|
402
413
|
}
|
|
403
414
|
}
|
|
404
415
|
}
|
|
@@ -434,14 +445,37 @@ function isRenderedElement(element) {
|
|
|
434
445
|
if (!style) return true;
|
|
435
446
|
return style.visibility !== "hidden" && style.display !== "none";
|
|
436
447
|
}
|
|
448
|
+
function parseEditHref(href) {
|
|
449
|
+
try {
|
|
450
|
+
const url = new URL(href, window.location.origin);
|
|
451
|
+
return {
|
|
452
|
+
id: url.pathname.split("/").pop() || void 0,
|
|
453
|
+
field: url.searchParams.get("field") || void 0,
|
|
454
|
+
locale: url.searchParams.get("locale") || void 0
|
|
455
|
+
};
|
|
456
|
+
} catch {
|
|
457
|
+
return {};
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
function setOrRemove(element, name, value) {
|
|
461
|
+
if (value) {
|
|
462
|
+
element.setAttribute(name, value);
|
|
463
|
+
} else {
|
|
464
|
+
element.removeAttribute(name);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
437
467
|
function tagEncodedElement(element, decoded) {
|
|
438
468
|
element.setAttribute("data-prepr-encoded", "");
|
|
439
469
|
element.setAttribute("data-prepr-href", decoded.href);
|
|
440
470
|
element.setAttribute("data-prepr-origin", decoded.origin);
|
|
471
|
+
const { id, field, locale } = parseEditHref(decoded.href);
|
|
472
|
+
setOrRemove(element, "data-prepr-id", id);
|
|
473
|
+
setOrRemove(element, "data-prepr-field", field);
|
|
474
|
+
setOrRemove(element, "data-prepr-locale", locale);
|
|
441
475
|
}
|
|
442
476
|
|
|
443
477
|
// src/core/stega/auto-clean.ts
|
|
444
|
-
var
|
|
478
|
+
var debug3 = createScopedLogger("stega:auto-clean");
|
|
445
479
|
function createStegaAutoClean(options) {
|
|
446
480
|
const stripText = options?.enabled ?? true;
|
|
447
481
|
let observer = null;
|
|
@@ -484,7 +518,7 @@ function createStegaAutoClean(options) {
|
|
|
484
518
|
}
|
|
485
519
|
pendingHidden.add(textNode);
|
|
486
520
|
} catch (error) {
|
|
487
|
-
|
|
521
|
+
debug3.log("error cleaning text node", error);
|
|
488
522
|
}
|
|
489
523
|
return false;
|
|
490
524
|
}
|
|
@@ -570,7 +604,7 @@ function createStegaAutoClean(options) {
|
|
|
570
604
|
if (observer || typeof window === "undefined") return;
|
|
571
605
|
scanAndClean();
|
|
572
606
|
setupObserver();
|
|
573
|
-
|
|
607
|
+
debug3.log("stega auto-clean started");
|
|
574
608
|
}
|
|
575
609
|
function stop() {
|
|
576
610
|
if (debounceTimeout) {
|
|
@@ -584,13 +618,13 @@ function createStegaAutoClean(options) {
|
|
|
584
618
|
cleaned = /* @__PURE__ */ new WeakMap();
|
|
585
619
|
pendingHidden = /* @__PURE__ */ new Set();
|
|
586
620
|
pendingDirty = /* @__PURE__ */ new Set();
|
|
587
|
-
|
|
621
|
+
debug3.log("stega auto-clean stopped");
|
|
588
622
|
}
|
|
589
623
|
return { start, stop };
|
|
590
624
|
}
|
|
591
625
|
|
|
592
626
|
// src/core/stega/elements.ts
|
|
593
|
-
var
|
|
627
|
+
var debug4 = createScopedLogger("stega:elements");
|
|
594
628
|
var StegaElements = class {
|
|
595
629
|
constructor(decode = decodeStega) {
|
|
596
630
|
this.observer = null;
|
|
@@ -635,7 +669,7 @@ var StegaElements = class {
|
|
|
635
669
|
walkTextNodes(document.body, (textNode) => {
|
|
636
670
|
if (this.tagFromTextNode(textNode)) encodedCount++;
|
|
637
671
|
});
|
|
638
|
-
|
|
672
|
+
debug4.log("document scan complete, encoded", encodedCount, "elements");
|
|
639
673
|
this.elements = document.querySelectorAll("[data-prepr-encoded]");
|
|
640
674
|
}
|
|
641
675
|
/** `onUpdate` fires after each debounced batch, for refreshing derived state. */
|
|
@@ -691,6 +725,9 @@ var StegaElements = class {
|
|
|
691
725
|
element.removeAttribute("data-prepr-encoded");
|
|
692
726
|
element.removeAttribute("data-prepr-href");
|
|
693
727
|
element.removeAttribute("data-prepr-origin");
|
|
728
|
+
element.removeAttribute("data-prepr-id");
|
|
729
|
+
element.removeAttribute("data-prepr-field");
|
|
730
|
+
element.removeAttribute("data-prepr-locale");
|
|
694
731
|
element.classList.remove("prepr-overlay-active");
|
|
695
732
|
});
|
|
696
733
|
this.elements = void 0;
|
|
@@ -698,7 +735,7 @@ var StegaElements = class {
|
|
|
698
735
|
};
|
|
699
736
|
|
|
700
737
|
// src/core/stega/overlay.ts
|
|
701
|
-
var
|
|
738
|
+
var debug5 = createScopedLogger("stega:overlay");
|
|
702
739
|
var StegaOverlay = class {
|
|
703
740
|
constructor(onEdit) {
|
|
704
741
|
this.overlay = null;
|
|
@@ -743,7 +780,8 @@ var StegaOverlay = class {
|
|
|
743
780
|
const origin = element.getAttribute("data-prepr-origin");
|
|
744
781
|
const id = element.getAttribute("data-prepr-id") ?? void 0;
|
|
745
782
|
const field = element.getAttribute("data-prepr-field") ?? void 0;
|
|
746
|
-
|
|
783
|
+
const locale = element.getAttribute("data-prepr-locale") ?? void 0;
|
|
784
|
+
debug5.log("showing overlay", { href, origin });
|
|
747
785
|
const overlay = this.overlay;
|
|
748
786
|
overlay.style.display = "block";
|
|
749
787
|
overlay.style.top = `${rect.top + window.scrollY - 2}px`;
|
|
@@ -775,7 +813,7 @@ var StegaOverlay = class {
|
|
|
775
813
|
tooltip.style.left = `${left}px`;
|
|
776
814
|
});
|
|
777
815
|
tooltip.onclick = () => {
|
|
778
|
-
this.onEdit({ href, origin, id, field });
|
|
816
|
+
this.onEdit({ href, origin, id, field, locale });
|
|
779
817
|
};
|
|
780
818
|
}
|
|
781
819
|
this.currentElement = element;
|
|
@@ -815,7 +853,7 @@ var StegaOverlay = class {
|
|
|
815
853
|
};
|
|
816
854
|
|
|
817
855
|
// src/core/stega/proximity.ts
|
|
818
|
-
var
|
|
856
|
+
var debug6 = createScopedLogger("stega:proximity");
|
|
819
857
|
var StegaProximity = class {
|
|
820
858
|
constructor() {
|
|
821
859
|
this.highlighted = /* @__PURE__ */ new Set();
|
|
@@ -850,9 +888,9 @@ var StegaProximity = class {
|
|
|
850
888
|
);
|
|
851
889
|
const nodes = this.getEncodedElements();
|
|
852
890
|
nodes.forEach((el) => this.observer.observe(el));
|
|
853
|
-
|
|
891
|
+
debug6.log("observing", nodes.length, "encoded elements");
|
|
854
892
|
} catch (error) {
|
|
855
|
-
|
|
893
|
+
debug6.log("error setting up IntersectionObserver", error);
|
|
856
894
|
}
|
|
857
895
|
}
|
|
858
896
|
stopObserving() {
|
|
@@ -922,7 +960,7 @@ function removeStegaStyles() {
|
|
|
922
960
|
}
|
|
923
961
|
|
|
924
962
|
// src/core/stega/scan.ts
|
|
925
|
-
var
|
|
963
|
+
var debug7 = createScopedLogger("stega:scan");
|
|
926
964
|
var EDITOR_MODE_STYLES = "[data-prepr-encoded]{cursor:pointer}";
|
|
927
965
|
function createStegaController(opts) {
|
|
928
966
|
const tooltipEnabled = opts.tooltip ?? true;
|
|
@@ -955,12 +993,13 @@ function createStegaController(opts) {
|
|
|
955
993
|
href: encoded.getAttribute("data-prepr-href") ?? "",
|
|
956
994
|
origin: encoded.getAttribute("data-prepr-origin") ?? "",
|
|
957
995
|
id: encoded.getAttribute("data-prepr-id") ?? void 0,
|
|
958
|
-
field: encoded.getAttribute("data-prepr-field") ?? void 0
|
|
996
|
+
field: encoded.getAttribute("data-prepr-field") ?? void 0,
|
|
997
|
+
locale: encoded.getAttribute("data-prepr-locale") ?? void 0
|
|
959
998
|
});
|
|
960
999
|
};
|
|
961
1000
|
const start = () => {
|
|
962
1001
|
if (initialized) {
|
|
963
|
-
|
|
1002
|
+
debug7.log("already initialized, skipping setup");
|
|
964
1003
|
return;
|
|
965
1004
|
}
|
|
966
1005
|
if (!tooltipEnabled) {
|
|
@@ -970,7 +1009,7 @@ function createStegaController(opts) {
|
|
|
970
1009
|
});
|
|
971
1010
|
document.addEventListener("click", handleClick, { capture: true });
|
|
972
1011
|
initialized = true;
|
|
973
|
-
|
|
1012
|
+
debug7.log("stega controller started (editor mode)");
|
|
974
1013
|
return;
|
|
975
1014
|
}
|
|
976
1015
|
injectStegaStyles();
|
|
@@ -1001,7 +1040,7 @@ function createStegaController(opts) {
|
|
|
1001
1040
|
passive: true
|
|
1002
1041
|
});
|
|
1003
1042
|
initialized = true;
|
|
1004
|
-
|
|
1043
|
+
debug7.log("stega controller started");
|
|
1005
1044
|
};
|
|
1006
1045
|
const stop = () => {
|
|
1007
1046
|
if (!initialized) return;
|
|
@@ -1010,7 +1049,7 @@ function createStegaController(opts) {
|
|
|
1010
1049
|
elements.cleanup();
|
|
1011
1050
|
removeStegaStyles();
|
|
1012
1051
|
initialized = false;
|
|
1013
|
-
|
|
1052
|
+
debug7.log("stega controller stopped (editor mode)");
|
|
1014
1053
|
return;
|
|
1015
1054
|
}
|
|
1016
1055
|
if (throttledMouseMove) {
|
|
@@ -1030,11 +1069,43 @@ function createStegaController(opts) {
|
|
|
1030
1069
|
elements.cleanup();
|
|
1031
1070
|
removeStegaStyles();
|
|
1032
1071
|
initialized = false;
|
|
1033
|
-
|
|
1072
|
+
debug7.log("stega controller stopped");
|
|
1034
1073
|
};
|
|
1035
1074
|
return { start, stop };
|
|
1036
1075
|
}
|
|
1037
1076
|
|
|
1077
|
+
// src/core/stega/scroll-to-field.ts
|
|
1078
|
+
var debug8 = createScopedLogger("stega:scroll");
|
|
1079
|
+
var FLASH_DURATION_MS = 1200;
|
|
1080
|
+
var flashTimeout = null;
|
|
1081
|
+
function scrollToField(request) {
|
|
1082
|
+
const { field, id } = request;
|
|
1083
|
+
if (!field) return false;
|
|
1084
|
+
const candidates = document.querySelectorAll(
|
|
1085
|
+
"[data-prepr-encoded]"
|
|
1086
|
+
);
|
|
1087
|
+
let target = null;
|
|
1088
|
+
for (const candidate of candidates) {
|
|
1089
|
+
if (candidate.getAttribute("data-prepr-field") !== field) continue;
|
|
1090
|
+
if (id && candidate.getAttribute("data-prepr-id") !== id) continue;
|
|
1091
|
+
target = candidate;
|
|
1092
|
+
break;
|
|
1093
|
+
}
|
|
1094
|
+
if (!target) {
|
|
1095
|
+
debug8.log("no element found for field", field);
|
|
1096
|
+
return false;
|
|
1097
|
+
}
|
|
1098
|
+
target.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
1099
|
+
if (flashTimeout) clearTimeout(flashTimeout);
|
|
1100
|
+
document.querySelectorAll(".prepr-overlay-active").forEach((el) => el.classList.remove("prepr-overlay-active"));
|
|
1101
|
+
target.classList.add("prepr-overlay-active");
|
|
1102
|
+
flashTimeout = setTimeout(() => {
|
|
1103
|
+
target.classList.remove("prepr-overlay-active");
|
|
1104
|
+
flashTimeout = null;
|
|
1105
|
+
}, FLASH_DURATION_MS);
|
|
1106
|
+
return true;
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1038
1109
|
// src/core/store.ts
|
|
1039
1110
|
var DEFAULT_STATE = {
|
|
1040
1111
|
locale: "en",
|
|
@@ -2147,7 +2218,7 @@ function definePreprToolbar() {
|
|
|
2147
2218
|
}
|
|
2148
2219
|
|
|
2149
2220
|
// src/core/create-preview.ts
|
|
2150
|
-
var
|
|
2221
|
+
var debug9 = createScopedLogger("create-preview");
|
|
2151
2222
|
var controllerStores = /* @__PURE__ */ new WeakMap();
|
|
2152
2223
|
function defaultNavigation() {
|
|
2153
2224
|
return {
|
|
@@ -2189,7 +2260,7 @@ function createPreprPreview(opts = {}) {
|
|
|
2189
2260
|
const search = new URLSearchParams(window.location.search);
|
|
2190
2261
|
const hideBar = search.get(PARAM_HIDE_BAR) === "true";
|
|
2191
2262
|
if (hideBar) {
|
|
2192
|
-
|
|
2263
|
+
debug9.log(`${PARAM_HIDE_BAR}=true \u2014 no visible toolbar`);
|
|
2193
2264
|
}
|
|
2194
2265
|
const mountUi = (options?.ui ?? true) && !isIframe && !hideBar;
|
|
2195
2266
|
const locale = resolveLocale(options);
|
|
@@ -2225,18 +2296,17 @@ function createPreprPreview(opts = {}) {
|
|
|
2225
2296
|
tooltip: mountUi,
|
|
2226
2297
|
// In the editor, ask the parent to focus the field instead of opening a new
|
|
2227
2298
|
// tab. Standalone previews keep the window.open behaviour.
|
|
2228
|
-
onEdit: ({ href,
|
|
2299
|
+
onEdit: ({ href, id, field, locale: contentLocale }) => {
|
|
2229
2300
|
const safeHref = href ? safeEditUrl(href) : null;
|
|
2230
2301
|
if (href && !safeHref) {
|
|
2231
|
-
|
|
2302
|
+
debug9.warn("ignored edit request with unsupported href scheme");
|
|
2232
2303
|
return;
|
|
2233
2304
|
}
|
|
2234
2305
|
if (isIframe) {
|
|
2235
2306
|
sendPreprEvent("field_edit_requested", {
|
|
2236
|
-
href: safeHref ?? void 0,
|
|
2237
|
-
origin,
|
|
2238
2307
|
id,
|
|
2239
|
-
field
|
|
2308
|
+
field,
|
|
2309
|
+
locale: contentLocale
|
|
2240
2310
|
});
|
|
2241
2311
|
} else if (safeHref) {
|
|
2242
2312
|
window.open(safeHref, "_blank", "noopener,noreferrer");
|
|
@@ -2263,7 +2333,15 @@ function createPreprPreview(opts = {}) {
|
|
|
2263
2333
|
handleChange(before, state);
|
|
2264
2334
|
});
|
|
2265
2335
|
const bridge = createIframeBridge(store, {
|
|
2266
|
-
allowedEditorOrigins: options?.allowedEditorOrigins
|
|
2336
|
+
allowedEditorOrigins: options?.allowedEditorOrigins,
|
|
2337
|
+
// The editor selecting a field scrolls the matching element into view. The
|
|
2338
|
+
// lookup relies on the attributes the stega scan writes, so it finds
|
|
2339
|
+
// nothing until encoded content has been tagged.
|
|
2340
|
+
onScrollToField: ({ field, id }) => {
|
|
2341
|
+
if (!scrollToField({ field, id })) {
|
|
2342
|
+
debug9.log("no element on this page renders field", field);
|
|
2343
|
+
}
|
|
2344
|
+
}
|
|
2267
2345
|
});
|
|
2268
2346
|
sendPreprEvent(
|
|
2269
2347
|
"getScrollPosition",
|
|
@@ -2283,7 +2361,7 @@ function createPreprPreview(opts = {}) {
|
|
|
2283
2361
|
bridge.stop();
|
|
2284
2362
|
}
|
|
2285
2363
|
el?.remove();
|
|
2286
|
-
|
|
2364
|
+
debug9.log("preview destroyed");
|
|
2287
2365
|
}
|
|
2288
2366
|
const controller = { destroy };
|
|
2289
2367
|
controllerStores.set(controller, store);
|
|
@@ -2323,7 +2401,7 @@ var PREPR_HEADER_KEYS = [
|
|
|
2323
2401
|
"Prepr-Visitor-IP",
|
|
2324
2402
|
"Prepr-Hubspot-Id",
|
|
2325
2403
|
"Prepr-Customer-Id-Created",
|
|
2326
|
-
"
|
|
2404
|
+
"User-Agent",
|
|
2327
2405
|
"Prepr-Package"
|
|
2328
2406
|
];
|
|
2329
2407
|
function getPreprHeadersFromHeaders(headers) {
|
|
@@ -2520,7 +2598,7 @@ function processFrameworkRequest(request, opts, framework) {
|
|
|
2520
2598
|
}
|
|
2521
2599
|
const userAgent = request.headers.get("user-agent");
|
|
2522
2600
|
if (userAgent) {
|
|
2523
|
-
requestHeaders.set("
|
|
2601
|
+
requestHeaders.set("User-Agent", sanitizeHeaderValue(userAgent));
|
|
2524
2602
|
}
|
|
2525
2603
|
const packageParts = [`@preprio/toolkit@${opts?.version ?? VERSION}`];
|
|
2526
2604
|
if (framework) packageParts.push(`framework=${framework}`);
|