@preprio/toolkit 0.5.0-rc.1 → 0.6.0-alpha.0
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/README.md +300 -19
- package/dist/astro/chunk-3UVUDDNY.js +173 -0
- package/dist/astro/graphql.cjs +983 -0
- package/dist/astro/graphql.d.cts +231 -0
- package/dist/astro/graphql.d.ts +231 -0
- package/dist/astro/graphql.js +893 -0
- package/dist/astro/index-XT_z-RYT.d.cts +130 -0
- package/dist/astro/index-XT_z-RYT.d.ts +130 -0
- package/dist/astro/index.cjs +14 -1
- package/dist/astro/index.d.cts +1 -120
- package/dist/astro/index.d.ts +1 -120
- package/dist/astro/index.js +15 -153
- package/dist/{chunk-4JNKYIEV.js → chunk-BJ2LBLWO.js} +69 -268
- package/dist/chunk-DGZA7KX7.js +172 -0
- package/dist/chunk-YR7P4IWE.js +187 -0
- package/dist/graphql.cjs +894 -0
- package/dist/graphql.d.cts +231 -0
- package/dist/graphql.d.ts +231 -0
- package/dist/graphql.js +787 -0
- package/dist/index.cjs +74 -111
- package/dist/index.d.cts +11 -62
- package/dist/index.d.ts +11 -62
- package/dist/index.js +23 -167
- package/dist/nextjs/chunk-U4HXENF7.js +231 -0
- package/dist/nextjs/components.cjs +188 -114
- package/dist/nextjs/components.d.cts +33 -2
- package/dist/nextjs/components.d.ts +33 -2
- package/dist/nextjs/components.js +132 -4
- package/dist/nextjs/graphql.cjs +1315 -0
- package/dist/nextjs/graphql.d.cts +361 -0
- package/dist/nextjs/graphql.d.ts +361 -0
- package/dist/nextjs/graphql.js +1218 -0
- package/dist/nextjs/index.cjs +126 -6
- package/dist/nextjs/index.d.cts +53 -141
- package/dist/nextjs/index.d.ts +53 -141
- package/dist/nextjs/index.js +113 -203
- package/dist/nextjs/server-CjpELYvq.d.cts +156 -0
- package/dist/nextjs/server-CjpELYvq.d.ts +156 -0
- package/dist/nuxt/chunk-P6ENNAEE.js +417 -0
- package/dist/nuxt/graphql.cjs +990 -0
- package/dist/nuxt/graphql.d.cts +228 -0
- package/dist/nuxt/graphql.d.ts +228 -0
- package/dist/nuxt/graphql.js +894 -0
- package/dist/nuxt/index.cjs +14 -1
- package/dist/nuxt/index.d.cts +3 -148
- package/dist/nuxt/index.d.ts +3 -148
- package/dist/nuxt/index.js +15 -391
- package/dist/nuxt/server-8v6OHbsw.d.cts +158 -0
- package/dist/nuxt/server-8v6OHbsw.d.ts +158 -0
- package/dist/pixel-DwW7cXJm.d.cts +49 -0
- package/dist/pixel-DwW7cXJm.d.ts +49 -0
- package/dist/react/components.cjs +86 -112
- package/dist/react/components.js +86 -112
- package/dist/server-Brr1UgtW.d.ts +59 -0
- package/dist/server-DJuS3YU0.d.cts +59 -0
- package/dist/sveltekit/chunk-FSARVMG5.js +413 -0
- package/dist/sveltekit/graphql.cjs +996 -0
- package/dist/sveltekit/graphql.d.cts +233 -0
- package/dist/sveltekit/graphql.d.ts +233 -0
- package/dist/sveltekit/graphql.js +900 -0
- package/dist/sveltekit/index.cjs +14 -1
- package/dist/sveltekit/index.d.cts +3 -88
- package/dist/sveltekit/index.d.ts +3 -88
- package/dist/sveltekit/index.js +15 -387
- package/dist/sveltekit/server-CO847mEV.d.cts +98 -0
- package/dist/sveltekit/server-CO847mEV.d.ts +98 -0
- package/dist/{pixel-e1fUWl2Y.d.cts → types-BYH9XqmN.d.cts} +2 -50
- package/dist/{pixel-e1fUWl2Y.d.ts → types-BYH9XqmN.d.ts} +2 -50
- package/package.json +31 -1
package/dist/index.cjs
CHANGED
|
@@ -33,6 +33,7 @@ __export(src_exports, {
|
|
|
33
33
|
getPreprHeadersFromHeaders: () => getPreprHeadersFromHeaders,
|
|
34
34
|
getPreprUUIDFromHeaders: () => getPreprUUIDFromHeaders,
|
|
35
35
|
getToolbarPropsFromHeaders: () => getToolbarPropsFromHeaders,
|
|
36
|
+
isPersonalizedResponse: () => isPersonalizedResponse,
|
|
36
37
|
loadTrackingPixel: () => loadTrackingPixel,
|
|
37
38
|
processPreprRequest: () => processPreprRequest,
|
|
38
39
|
resolveFeatures: () => resolveFeatures,
|
|
@@ -44,7 +45,7 @@ __export(src_exports, {
|
|
|
44
45
|
module.exports = __toCommonJS(src_exports);
|
|
45
46
|
|
|
46
47
|
// src/version.ts
|
|
47
|
-
var VERSION = "0.
|
|
48
|
+
var VERSION = "0.6.0-alpha.0";
|
|
48
49
|
|
|
49
50
|
// src/core/features.ts
|
|
50
51
|
function isEnabled(config) {
|
|
@@ -312,7 +313,6 @@ function createElementCache(query, ttl = 1e3) {
|
|
|
312
313
|
}
|
|
313
314
|
|
|
314
315
|
// src/core/iframe-bridge.ts
|
|
315
|
-
var debug = createScopedLogger("iframe-bridge");
|
|
316
316
|
var EDITOR_BASE_DOMAIN = "prepr.io";
|
|
317
317
|
function isAllowedEditorOrigin(origin, allowed) {
|
|
318
318
|
if (allowed) return allowed.includes(origin);
|
|
@@ -330,7 +330,6 @@ function isAllowedEditorOrigin(origin, allowed) {
|
|
|
330
330
|
}
|
|
331
331
|
function createIframeBridge(store, options = {}) {
|
|
332
332
|
const allowedOrigins = options.allowedEditorOrigins;
|
|
333
|
-
const onScrollToField = options.onScrollToField;
|
|
334
333
|
let parentOrigin = null;
|
|
335
334
|
const onKeyDown = (event) => {
|
|
336
335
|
const key = event.key.toLowerCase();
|
|
@@ -354,15 +353,6 @@ function createIframeBridge(store, options = {}) {
|
|
|
354
353
|
const currentScrollY = window.scrollY || document.documentElement.scrollTop;
|
|
355
354
|
sendPreprEvent("getScrollPosition", { value: currentScrollY });
|
|
356
355
|
}
|
|
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
|
-
}
|
|
366
356
|
};
|
|
367
357
|
return {
|
|
368
358
|
start() {
|
|
@@ -387,7 +377,7 @@ var import_stega2 = require("@vercel/stega");
|
|
|
387
377
|
|
|
388
378
|
// src/core/stega/clean.ts
|
|
389
379
|
var import_stega = require("@vercel/stega");
|
|
390
|
-
var
|
|
380
|
+
var debug = createScopedLogger("stega:clean");
|
|
391
381
|
function stegaClean(text) {
|
|
392
382
|
if (!text) return text;
|
|
393
383
|
return (0, import_stega.vercelStegaClean)(text);
|
|
@@ -400,7 +390,7 @@ function decodeStega(str) {
|
|
|
400
390
|
return decoded;
|
|
401
391
|
}
|
|
402
392
|
} catch (error) {
|
|
403
|
-
|
|
393
|
+
debug.log("error decoding stega data", error);
|
|
404
394
|
const match = str.match(/{"origin.*?}/);
|
|
405
395
|
if (match) {
|
|
406
396
|
try {
|
|
@@ -409,7 +399,7 @@ function decodeStega(str) {
|
|
|
409
399
|
return decodedMatch;
|
|
410
400
|
}
|
|
411
401
|
} catch (innerError) {
|
|
412
|
-
|
|
402
|
+
debug.log("error decoding stega regex match", innerError);
|
|
413
403
|
}
|
|
414
404
|
}
|
|
415
405
|
}
|
|
@@ -445,37 +435,15 @@ function isRenderedElement(element) {
|
|
|
445
435
|
if (!style) return true;
|
|
446
436
|
return style.visibility !== "hidden" && style.display !== "none";
|
|
447
437
|
}
|
|
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
|
-
}
|
|
467
438
|
function tagEncodedElement(element, decoded) {
|
|
468
439
|
element.setAttribute("data-prepr-encoded", "");
|
|
469
440
|
element.setAttribute("data-prepr-href", decoded.href);
|
|
470
441
|
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);
|
|
475
442
|
}
|
|
476
443
|
|
|
477
444
|
// src/core/stega/auto-clean.ts
|
|
478
|
-
var
|
|
445
|
+
var debug2 = createScopedLogger("stega:auto-clean");
|
|
446
|
+
var HYDRATION_RETRY_MS = 100;
|
|
479
447
|
function createStegaAutoClean(options) {
|
|
480
448
|
const stripText = options?.enabled ?? true;
|
|
481
449
|
let observer = null;
|
|
@@ -484,8 +452,29 @@ function createStegaAutoClean(options) {
|
|
|
484
452
|
let pendingHidden = /* @__PURE__ */ new Set();
|
|
485
453
|
let pendingDirty = /* @__PURE__ */ new Set();
|
|
486
454
|
let debounceTimeout = null;
|
|
455
|
+
const isHydrated = options?.isHydrated;
|
|
456
|
+
let pendingHydration = /* @__PURE__ */ new Set();
|
|
457
|
+
let hydrationTimeout = null;
|
|
458
|
+
function retryPendingHydration() {
|
|
459
|
+
hydrationTimeout = null;
|
|
460
|
+
processing = true;
|
|
461
|
+
const batch = [...pendingHydration];
|
|
462
|
+
pendingHydration.clear();
|
|
463
|
+
batch.forEach((textNode) => {
|
|
464
|
+
if (textNode.isConnected) cleanTextNode(textNode);
|
|
465
|
+
});
|
|
466
|
+
processing = false;
|
|
467
|
+
}
|
|
487
468
|
function cleanTextNode(textNode) {
|
|
488
469
|
if (isIgnoredTextNode(textNode)) return false;
|
|
470
|
+
if (isHydrated && !isHydrated(textNode)) {
|
|
471
|
+
pendingHydration.add(textNode);
|
|
472
|
+
hydrationTimeout ?? (hydrationTimeout = setTimeout(
|
|
473
|
+
retryPendingHydration,
|
|
474
|
+
HYDRATION_RETRY_MS
|
|
475
|
+
));
|
|
476
|
+
return false;
|
|
477
|
+
}
|
|
489
478
|
const textContent = textNode.textContent;
|
|
490
479
|
const info = cleaned.get(textNode);
|
|
491
480
|
const settled = stripText ? info?.cleaned : info?.original;
|
|
@@ -518,7 +507,7 @@ function createStegaAutoClean(options) {
|
|
|
518
507
|
}
|
|
519
508
|
pendingHidden.add(textNode);
|
|
520
509
|
} catch (error) {
|
|
521
|
-
|
|
510
|
+
debug2.log("error cleaning text node", error);
|
|
522
511
|
}
|
|
523
512
|
return false;
|
|
524
513
|
}
|
|
@@ -604,13 +593,17 @@ function createStegaAutoClean(options) {
|
|
|
604
593
|
if (observer || typeof window === "undefined") return;
|
|
605
594
|
scanAndClean();
|
|
606
595
|
setupObserver();
|
|
607
|
-
|
|
596
|
+
debug2.log("stega auto-clean started");
|
|
608
597
|
}
|
|
609
598
|
function stop() {
|
|
610
599
|
if (debounceTimeout) {
|
|
611
600
|
clearTimeout(debounceTimeout);
|
|
612
601
|
debounceTimeout = null;
|
|
613
602
|
}
|
|
603
|
+
if (hydrationTimeout) {
|
|
604
|
+
clearTimeout(hydrationTimeout);
|
|
605
|
+
hydrationTimeout = null;
|
|
606
|
+
}
|
|
614
607
|
if (observer) {
|
|
615
608
|
observer.disconnect();
|
|
616
609
|
observer = null;
|
|
@@ -618,13 +611,14 @@ function createStegaAutoClean(options) {
|
|
|
618
611
|
cleaned = /* @__PURE__ */ new WeakMap();
|
|
619
612
|
pendingHidden = /* @__PURE__ */ new Set();
|
|
620
613
|
pendingDirty = /* @__PURE__ */ new Set();
|
|
621
|
-
|
|
614
|
+
pendingHydration = /* @__PURE__ */ new Set();
|
|
615
|
+
debug2.log("stega auto-clean stopped");
|
|
622
616
|
}
|
|
623
617
|
return { start, stop };
|
|
624
618
|
}
|
|
625
619
|
|
|
626
620
|
// src/core/stega/elements.ts
|
|
627
|
-
var
|
|
621
|
+
var debug3 = createScopedLogger("stega:elements");
|
|
628
622
|
var StegaElements = class {
|
|
629
623
|
constructor(decode = decodeStega) {
|
|
630
624
|
this.observer = null;
|
|
@@ -669,7 +663,7 @@ var StegaElements = class {
|
|
|
669
663
|
walkTextNodes(document.body, (textNode) => {
|
|
670
664
|
if (this.tagFromTextNode(textNode)) encodedCount++;
|
|
671
665
|
});
|
|
672
|
-
|
|
666
|
+
debug3.log("document scan complete, encoded", encodedCount, "elements");
|
|
673
667
|
this.elements = document.querySelectorAll("[data-prepr-encoded]");
|
|
674
668
|
}
|
|
675
669
|
/** `onUpdate` fires after each debounced batch, for refreshing derived state. */
|
|
@@ -725,9 +719,6 @@ var StegaElements = class {
|
|
|
725
719
|
element.removeAttribute("data-prepr-encoded");
|
|
726
720
|
element.removeAttribute("data-prepr-href");
|
|
727
721
|
element.removeAttribute("data-prepr-origin");
|
|
728
|
-
element.removeAttribute("data-prepr-id");
|
|
729
|
-
element.removeAttribute("data-prepr-field");
|
|
730
|
-
element.removeAttribute("data-prepr-locale");
|
|
731
722
|
element.classList.remove("prepr-overlay-active");
|
|
732
723
|
});
|
|
733
724
|
this.elements = void 0;
|
|
@@ -735,7 +726,7 @@ var StegaElements = class {
|
|
|
735
726
|
};
|
|
736
727
|
|
|
737
728
|
// src/core/stega/overlay.ts
|
|
738
|
-
var
|
|
729
|
+
var debug4 = createScopedLogger("stega:overlay");
|
|
739
730
|
var StegaOverlay = class {
|
|
740
731
|
constructor(onEdit) {
|
|
741
732
|
this.overlay = null;
|
|
@@ -780,8 +771,7 @@ var StegaOverlay = class {
|
|
|
780
771
|
const origin = element.getAttribute("data-prepr-origin");
|
|
781
772
|
const id = element.getAttribute("data-prepr-id") ?? void 0;
|
|
782
773
|
const field = element.getAttribute("data-prepr-field") ?? void 0;
|
|
783
|
-
|
|
784
|
-
debug5.log("showing overlay", { href, origin });
|
|
774
|
+
debug4.log("showing overlay", { href, origin });
|
|
785
775
|
const overlay = this.overlay;
|
|
786
776
|
overlay.style.display = "block";
|
|
787
777
|
overlay.style.top = `${rect.top + window.scrollY - 2}px`;
|
|
@@ -813,7 +803,7 @@ var StegaOverlay = class {
|
|
|
813
803
|
tooltip.style.left = `${left}px`;
|
|
814
804
|
});
|
|
815
805
|
tooltip.onclick = () => {
|
|
816
|
-
this.onEdit({ href, origin, id, field
|
|
806
|
+
this.onEdit({ href, origin, id, field });
|
|
817
807
|
};
|
|
818
808
|
}
|
|
819
809
|
this.currentElement = element;
|
|
@@ -853,7 +843,7 @@ var StegaOverlay = class {
|
|
|
853
843
|
};
|
|
854
844
|
|
|
855
845
|
// src/core/stega/proximity.ts
|
|
856
|
-
var
|
|
846
|
+
var debug5 = createScopedLogger("stega:proximity");
|
|
857
847
|
var StegaProximity = class {
|
|
858
848
|
constructor() {
|
|
859
849
|
this.highlighted = /* @__PURE__ */ new Set();
|
|
@@ -888,9 +878,9 @@ var StegaProximity = class {
|
|
|
888
878
|
);
|
|
889
879
|
const nodes = this.getEncodedElements();
|
|
890
880
|
nodes.forEach((el) => this.observer.observe(el));
|
|
891
|
-
|
|
881
|
+
debug5.log("observing", nodes.length, "encoded elements");
|
|
892
882
|
} catch (error) {
|
|
893
|
-
|
|
883
|
+
debug5.log("error setting up IntersectionObserver", error);
|
|
894
884
|
}
|
|
895
885
|
}
|
|
896
886
|
stopObserving() {
|
|
@@ -960,7 +950,7 @@ function removeStegaStyles() {
|
|
|
960
950
|
}
|
|
961
951
|
|
|
962
952
|
// src/core/stega/scan.ts
|
|
963
|
-
var
|
|
953
|
+
var debug6 = createScopedLogger("stega:scan");
|
|
964
954
|
var EDITOR_MODE_STYLES = "[data-prepr-encoded]{cursor:pointer}";
|
|
965
955
|
function createStegaController(opts) {
|
|
966
956
|
const tooltipEnabled = opts.tooltip ?? true;
|
|
@@ -993,13 +983,12 @@ function createStegaController(opts) {
|
|
|
993
983
|
href: encoded.getAttribute("data-prepr-href") ?? "",
|
|
994
984
|
origin: encoded.getAttribute("data-prepr-origin") ?? "",
|
|
995
985
|
id: encoded.getAttribute("data-prepr-id") ?? void 0,
|
|
996
|
-
field: encoded.getAttribute("data-prepr-field") ?? void 0
|
|
997
|
-
locale: encoded.getAttribute("data-prepr-locale") ?? void 0
|
|
986
|
+
field: encoded.getAttribute("data-prepr-field") ?? void 0
|
|
998
987
|
});
|
|
999
988
|
};
|
|
1000
989
|
const start = () => {
|
|
1001
990
|
if (initialized) {
|
|
1002
|
-
|
|
991
|
+
debug6.log("already initialized, skipping setup");
|
|
1003
992
|
return;
|
|
1004
993
|
}
|
|
1005
994
|
if (!tooltipEnabled) {
|
|
@@ -1009,7 +998,7 @@ function createStegaController(opts) {
|
|
|
1009
998
|
});
|
|
1010
999
|
document.addEventListener("click", handleClick, { capture: true });
|
|
1011
1000
|
initialized = true;
|
|
1012
|
-
|
|
1001
|
+
debug6.log("stega controller started (editor mode)");
|
|
1013
1002
|
return;
|
|
1014
1003
|
}
|
|
1015
1004
|
injectStegaStyles();
|
|
@@ -1040,7 +1029,7 @@ function createStegaController(opts) {
|
|
|
1040
1029
|
passive: true
|
|
1041
1030
|
});
|
|
1042
1031
|
initialized = true;
|
|
1043
|
-
|
|
1032
|
+
debug6.log("stega controller started");
|
|
1044
1033
|
};
|
|
1045
1034
|
const stop = () => {
|
|
1046
1035
|
if (!initialized) return;
|
|
@@ -1049,7 +1038,7 @@ function createStegaController(opts) {
|
|
|
1049
1038
|
elements.cleanup();
|
|
1050
1039
|
removeStegaStyles();
|
|
1051
1040
|
initialized = false;
|
|
1052
|
-
|
|
1041
|
+
debug6.log("stega controller stopped (editor mode)");
|
|
1053
1042
|
return;
|
|
1054
1043
|
}
|
|
1055
1044
|
if (throttledMouseMove) {
|
|
@@ -1069,43 +1058,11 @@ function createStegaController(opts) {
|
|
|
1069
1058
|
elements.cleanup();
|
|
1070
1059
|
removeStegaStyles();
|
|
1071
1060
|
initialized = false;
|
|
1072
|
-
|
|
1061
|
+
debug6.log("stega controller stopped");
|
|
1073
1062
|
};
|
|
1074
1063
|
return { start, stop };
|
|
1075
1064
|
}
|
|
1076
1065
|
|
|
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
|
-
|
|
1109
1066
|
// src/core/store.ts
|
|
1110
1067
|
var DEFAULT_STATE = {
|
|
1111
1068
|
locale: "en",
|
|
@@ -2218,7 +2175,7 @@ function definePreprToolbar() {
|
|
|
2218
2175
|
}
|
|
2219
2176
|
|
|
2220
2177
|
// src/core/create-preview.ts
|
|
2221
|
-
var
|
|
2178
|
+
var debug7 = createScopedLogger("create-preview");
|
|
2222
2179
|
var controllerStores = /* @__PURE__ */ new WeakMap();
|
|
2223
2180
|
function defaultNavigation() {
|
|
2224
2181
|
return {
|
|
@@ -2260,7 +2217,7 @@ function createPreprPreview(opts = {}) {
|
|
|
2260
2217
|
const search = new URLSearchParams(window.location.search);
|
|
2261
2218
|
const hideBar = search.get(PARAM_HIDE_BAR) === "true";
|
|
2262
2219
|
if (hideBar) {
|
|
2263
|
-
|
|
2220
|
+
debug7.log(`${PARAM_HIDE_BAR}=true \u2014 no visible toolbar`);
|
|
2264
2221
|
}
|
|
2265
2222
|
const mountUi = (options?.ui ?? true) && !isIframe && !hideBar;
|
|
2266
2223
|
const locale = resolveLocale(options);
|
|
@@ -2296,17 +2253,18 @@ function createPreprPreview(opts = {}) {
|
|
|
2296
2253
|
tooltip: mountUi,
|
|
2297
2254
|
// In the editor, ask the parent to focus the field instead of opening a new
|
|
2298
2255
|
// tab. Standalone previews keep the window.open behaviour.
|
|
2299
|
-
onEdit: ({ href, id, field
|
|
2256
|
+
onEdit: ({ href, origin, id, field }) => {
|
|
2300
2257
|
const safeHref = href ? safeEditUrl(href) : null;
|
|
2301
2258
|
if (href && !safeHref) {
|
|
2302
|
-
|
|
2259
|
+
debug7.warn("ignored edit request with unsupported href scheme");
|
|
2303
2260
|
return;
|
|
2304
2261
|
}
|
|
2305
2262
|
if (isIframe) {
|
|
2306
2263
|
sendPreprEvent("field_edit_requested", {
|
|
2264
|
+
href: safeHref ?? void 0,
|
|
2265
|
+
origin,
|
|
2307
2266
|
id,
|
|
2308
|
-
field
|
|
2309
|
-
locale: contentLocale
|
|
2267
|
+
field
|
|
2310
2268
|
});
|
|
2311
2269
|
} else if (safeHref) {
|
|
2312
2270
|
window.open(safeHref, "_blank", "noopener,noreferrer");
|
|
@@ -2314,7 +2272,8 @@ function createPreprPreview(opts = {}) {
|
|
|
2314
2272
|
}
|
|
2315
2273
|
});
|
|
2316
2274
|
const autoClean = createStegaAutoClean({
|
|
2317
|
-
enabled: options?.autoClean
|
|
2275
|
+
enabled: options?.autoClean,
|
|
2276
|
+
isHydrated: opts.isHydrated
|
|
2318
2277
|
});
|
|
2319
2278
|
autoClean.start();
|
|
2320
2279
|
const handleChange = createChangeHandler({
|
|
@@ -2333,15 +2292,7 @@ function createPreprPreview(opts = {}) {
|
|
|
2333
2292
|
handleChange(before, state);
|
|
2334
2293
|
});
|
|
2335
2294
|
const bridge = createIframeBridge(store, {
|
|
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
|
-
}
|
|
2295
|
+
allowedEditorOrigins: options?.allowedEditorOrigins
|
|
2345
2296
|
});
|
|
2346
2297
|
sendPreprEvent(
|
|
2347
2298
|
"getScrollPosition",
|
|
@@ -2361,13 +2312,20 @@ function createPreprPreview(opts = {}) {
|
|
|
2361
2312
|
bridge.stop();
|
|
2362
2313
|
}
|
|
2363
2314
|
el?.remove();
|
|
2364
|
-
|
|
2315
|
+
debug7.log("preview destroyed");
|
|
2365
2316
|
}
|
|
2366
2317
|
const controller = { destroy };
|
|
2367
2318
|
controllerStores.set(controller, store);
|
|
2368
2319
|
return controller;
|
|
2369
2320
|
}
|
|
2370
2321
|
|
|
2322
|
+
// src/core/personalization.ts
|
|
2323
|
+
var PERSONALIZED_VARY = /\bPrepr-(Segments|ABTesting)/i;
|
|
2324
|
+
function isPersonalizedResponse(source) {
|
|
2325
|
+
const headers = "headers" in source ? source.headers : source;
|
|
2326
|
+
return PERSONALIZED_VARY.test(headers.get("vary") ?? "");
|
|
2327
|
+
}
|
|
2328
|
+
|
|
2371
2329
|
// src/core/server.ts
|
|
2372
2330
|
var PreprError = class extends Error {
|
|
2373
2331
|
constructor(message, code, context, originalError) {
|
|
@@ -2683,6 +2641,10 @@ function processFrameworkRequest(request, opts, framework) {
|
|
|
2683
2641
|
});
|
|
2684
2642
|
}
|
|
2685
2643
|
}
|
|
2644
|
+
if (requestHeaders.has("Prepr-Segments")) {
|
|
2645
|
+
requestHeaders.delete("Prepr-Customer-Id");
|
|
2646
|
+
requestHeaders.delete("Prepr-Customer-Id-Created");
|
|
2647
|
+
}
|
|
2686
2648
|
return { requestHeaders, responseCookies };
|
|
2687
2649
|
}
|
|
2688
2650
|
|
|
@@ -2765,6 +2727,7 @@ function setTrackingParam(key, value) {
|
|
|
2765
2727
|
getPreprHeadersFromHeaders,
|
|
2766
2728
|
getPreprUUIDFromHeaders,
|
|
2767
2729
|
getToolbarPropsFromHeaders,
|
|
2730
|
+
isPersonalizedResponse,
|
|
2768
2731
|
loadTrackingPixel,
|
|
2769
2732
|
processPreprRequest,
|
|
2770
2733
|
resolveFeatures,
|
package/dist/index.d.cts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { g as PreprEnvironment, h as PreprEventType, i as PreprFeatureConfig, j as PreprHeaderName,
|
|
1
|
+
import { b as PreprFeatures, R as ResolvedPreprFeatures, L as Locale, c as PreprSegment, d as PreprVariant, e as PreprToolbarProps, f as PreprPreviewOptions } from './types-BYH9XqmN.cjs';
|
|
2
|
+
export { g as PreprEnvironment, a as PreprErrorCode, h as PreprEventType, i as PreprFeatureConfig, j as PreprHeaderName, P as PreprHeaders, k as PreprToolbarComponentProps, l as PreprToolbarOptions } from './types-BYH9XqmN.cjs';
|
|
3
|
+
export { P as PreprError, e as extractAccessToken, g as getActiveSegmentFromHeaders, a as getActiveVariantFromHeaders, b as getPreprEnvironmentSegments, c as getPreprHeadersFromHeaders, d as getPreprUUIDFromHeaders, f as getToolbarPropsFromHeaders, i as isPersonalizedResponse, v as validatePreprToken } from './server-DJuS3YU0.cjs';
|
|
4
|
+
export { P as PreprPixelConfig, l as loadTrackingPixel, s as setTrackingParam, t as trackEvent } from './pixel-DwW7cXJm.cjs';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Package version; must match package.json. Lives in its own leaf module so
|
|
6
8
|
* core can import it without cycling through the barrel.
|
|
7
9
|
*/
|
|
8
|
-
declare const VERSION = "0.
|
|
10
|
+
declare const VERSION = "0.6.0-alpha.0";
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
13
|
* Resolve a `PreprFeatures` bag to plain booleans, defaulting every omitted key
|
|
@@ -65,6 +67,11 @@ interface CreatePreprPreviewOptions {
|
|
|
65
67
|
props?: PreprToolbarProps;
|
|
66
68
|
options?: PreprPreviewOptions;
|
|
67
69
|
navigation?: PreprNavigationAdapter;
|
|
70
|
+
/**
|
|
71
|
+
* @internal Supplied by framework wrappers so stega stripping waits until
|
|
72
|
+
* the framework has hydrated the text it would change.
|
|
73
|
+
*/
|
|
74
|
+
isHydrated?: (node: Text) => boolean;
|
|
68
75
|
}
|
|
69
76
|
interface PreprPreviewController {
|
|
70
77
|
destroy(): void;
|
|
@@ -137,72 +144,14 @@ declare class PreprToolbarElement extends HTMLElementBase {
|
|
|
137
144
|
/** Idempotent, including across bundles that each try to define the element. */
|
|
138
145
|
declare function definePreprToolbar(): void;
|
|
139
146
|
|
|
140
|
-
/** Which field the editor asked the preview to bring on screen. */
|
|
141
|
-
interface ScrollToFieldMessage {
|
|
142
|
-
field: string;
|
|
143
|
-
id?: string;
|
|
144
|
-
}
|
|
145
147
|
interface IframeBridgeOptions {
|
|
146
148
|
/**
|
|
147
149
|
* Replace the `*.prepr.io` wildcard with an exact origin list. Intended for
|
|
148
150
|
* self-hosted editors; when set, the wildcard no longer applies.
|
|
149
151
|
*/
|
|
150
152
|
allowedEditorOrigins?: string[];
|
|
151
|
-
/**
|
|
152
|
-
* Called when the editor selects a field and wants the preview to scroll to
|
|
153
|
-
* it. Only fires for messages from the handshaked editor origin. The bridge
|
|
154
|
-
* stays free of DOM lookups: the preview runtime supplies `scrollToField`.
|
|
155
|
-
*/
|
|
156
|
-
onScrollToField?: (message: ScrollToFieldMessage) => void;
|
|
157
153
|
}
|
|
158
154
|
|
|
159
|
-
/** Error thrown by the token helpers and the segments fetch. */
|
|
160
|
-
declare class PreprError extends Error {
|
|
161
|
-
readonly code: PreprErrorCode;
|
|
162
|
-
readonly context?: string | undefined;
|
|
163
|
-
readonly originalError?: Error | undefined;
|
|
164
|
-
constructor(message: string, code: PreprErrorCode, context?: string | undefined, originalError?: Error | undefined);
|
|
165
|
-
}
|
|
166
|
-
/** Prepr Customer ID, or null if the middleware did not run for this request. */
|
|
167
|
-
declare function getPreprUUIDFromHeaders(headers: Headers): string | null;
|
|
168
|
-
/** Active segment ID, or null when no segment is selected. */
|
|
169
|
-
declare function getActiveSegmentFromHeaders(headers: Headers): string | null;
|
|
170
|
-
/** Active A/B variant (`'A'`/`'B'`), or null when no test is running. */
|
|
171
|
-
declare function getActiveVariantFromHeaders(headers: Headers): string | null;
|
|
172
|
-
/**
|
|
173
|
-
* Collect the Prepr headers into a `PreprHeaders`. Lookups are case-insensitive
|
|
174
|
-
* per the Fetch spec, but the returned keys use the declared casing.
|
|
175
|
-
*/
|
|
176
|
-
declare function getPreprHeadersFromHeaders(headers: Headers): PreprHeaders;
|
|
177
|
-
/**
|
|
178
|
-
* Asserts `token` is the full `https://graphql.prepr.io/<token>` URL.
|
|
179
|
-
* @throws PreprError if the token is missing or not an HTTPS URL.
|
|
180
|
-
*/
|
|
181
|
-
declare function validatePreprToken(token: string): void;
|
|
182
|
-
/**
|
|
183
|
-
* Pulls the access token out of a GraphQL URL: `https://graphql.prepr.io/abc123`
|
|
184
|
-
* -> `abc123`.
|
|
185
|
-
* @throws PreprError if the URL is not a valid `graphql.prepr.io` URL.
|
|
186
|
-
*/
|
|
187
|
-
declare function extractAccessToken(graphqlUrl: string): string;
|
|
188
|
-
/**
|
|
189
|
-
* Fetches the environment's segments from the Prepr API.
|
|
190
|
-
*
|
|
191
|
-
* `token` must be a Prepr GraphQL URL with scope 'segments'.
|
|
192
|
-
* @throws PreprError if the token is invalid or the request fails.
|
|
193
|
-
*/
|
|
194
|
-
declare function getPreprEnvironmentSegments(token: string): Promise<PreprSegment[]>;
|
|
195
|
-
/**
|
|
196
|
-
* Never throws: a failed segments fetch yields an empty list so the toolbar
|
|
197
|
-
* still renders. The list is returned under both `segments` and the deprecated
|
|
198
|
-
* `data` alias.
|
|
199
|
-
*
|
|
200
|
-
* Pass the same `features` object you give the toolbar and the middleware: with
|
|
201
|
-
* segments disabled the `_Segments` request is skipped entirely, saving a
|
|
202
|
-
* round-trip per page.
|
|
203
|
-
*/
|
|
204
|
-
declare function getToolbarPropsFromHeaders(headers: Headers, token: string, features?: PreprFeatures): Promise<PreprToolbarProps>;
|
|
205
|
-
|
|
206
155
|
interface CookieSpec {
|
|
207
156
|
name: string;
|
|
208
157
|
value: string;
|
|
@@ -241,4 +190,4 @@ interface PreprMiddlewareOptions {
|
|
|
241
190
|
*/
|
|
242
191
|
declare function processPreprRequest(request: Request, opts?: PreprMiddlewareOptions): PreprMiddlewareResult;
|
|
243
192
|
|
|
244
|
-
export { type CookieSpec, type CreatePreprPreviewOptions, type IframeBridgeOptions,
|
|
193
|
+
export { type CookieSpec, type CreatePreprPreviewOptions, type IframeBridgeOptions, PreprFeatures, type PreprMiddlewareOptions, type PreprMiddlewareResult, type PreprNavigationAdapter, type PreprPreviewController, PreprPreviewOptions, PreprSegment, PreprToolbarElement, PreprToolbarProps, PreprVariant, ResolvedPreprFeatures, type ToolbarState, type ToolbarStore, VERSION, createPreprPreview, createToolbarStore, definePreprToolbar, processPreprRequest, resolveFeatures, stegaClean };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { g as PreprEnvironment, h as PreprEventType, i as PreprFeatureConfig, j as PreprHeaderName,
|
|
1
|
+
import { b as PreprFeatures, R as ResolvedPreprFeatures, L as Locale, c as PreprSegment, d as PreprVariant, e as PreprToolbarProps, f as PreprPreviewOptions } from './types-BYH9XqmN.js';
|
|
2
|
+
export { g as PreprEnvironment, a as PreprErrorCode, h as PreprEventType, i as PreprFeatureConfig, j as PreprHeaderName, P as PreprHeaders, k as PreprToolbarComponentProps, l as PreprToolbarOptions } from './types-BYH9XqmN.js';
|
|
3
|
+
export { P as PreprError, e as extractAccessToken, g as getActiveSegmentFromHeaders, a as getActiveVariantFromHeaders, b as getPreprEnvironmentSegments, c as getPreprHeadersFromHeaders, d as getPreprUUIDFromHeaders, f as getToolbarPropsFromHeaders, i as isPersonalizedResponse, v as validatePreprToken } from './server-Brr1UgtW.js';
|
|
4
|
+
export { P as PreprPixelConfig, l as loadTrackingPixel, s as setTrackingParam, t as trackEvent } from './pixel-DwW7cXJm.js';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Package version; must match package.json. Lives in its own leaf module so
|
|
6
8
|
* core can import it without cycling through the barrel.
|
|
7
9
|
*/
|
|
8
|
-
declare const VERSION = "0.
|
|
10
|
+
declare const VERSION = "0.6.0-alpha.0";
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
13
|
* Resolve a `PreprFeatures` bag to plain booleans, defaulting every omitted key
|
|
@@ -65,6 +67,11 @@ interface CreatePreprPreviewOptions {
|
|
|
65
67
|
props?: PreprToolbarProps;
|
|
66
68
|
options?: PreprPreviewOptions;
|
|
67
69
|
navigation?: PreprNavigationAdapter;
|
|
70
|
+
/**
|
|
71
|
+
* @internal Supplied by framework wrappers so stega stripping waits until
|
|
72
|
+
* the framework has hydrated the text it would change.
|
|
73
|
+
*/
|
|
74
|
+
isHydrated?: (node: Text) => boolean;
|
|
68
75
|
}
|
|
69
76
|
interface PreprPreviewController {
|
|
70
77
|
destroy(): void;
|
|
@@ -137,72 +144,14 @@ declare class PreprToolbarElement extends HTMLElementBase {
|
|
|
137
144
|
/** Idempotent, including across bundles that each try to define the element. */
|
|
138
145
|
declare function definePreprToolbar(): void;
|
|
139
146
|
|
|
140
|
-
/** Which field the editor asked the preview to bring on screen. */
|
|
141
|
-
interface ScrollToFieldMessage {
|
|
142
|
-
field: string;
|
|
143
|
-
id?: string;
|
|
144
|
-
}
|
|
145
147
|
interface IframeBridgeOptions {
|
|
146
148
|
/**
|
|
147
149
|
* Replace the `*.prepr.io` wildcard with an exact origin list. Intended for
|
|
148
150
|
* self-hosted editors; when set, the wildcard no longer applies.
|
|
149
151
|
*/
|
|
150
152
|
allowedEditorOrigins?: string[];
|
|
151
|
-
/**
|
|
152
|
-
* Called when the editor selects a field and wants the preview to scroll to
|
|
153
|
-
* it. Only fires for messages from the handshaked editor origin. The bridge
|
|
154
|
-
* stays free of DOM lookups: the preview runtime supplies `scrollToField`.
|
|
155
|
-
*/
|
|
156
|
-
onScrollToField?: (message: ScrollToFieldMessage) => void;
|
|
157
153
|
}
|
|
158
154
|
|
|
159
|
-
/** Error thrown by the token helpers and the segments fetch. */
|
|
160
|
-
declare class PreprError extends Error {
|
|
161
|
-
readonly code: PreprErrorCode;
|
|
162
|
-
readonly context?: string | undefined;
|
|
163
|
-
readonly originalError?: Error | undefined;
|
|
164
|
-
constructor(message: string, code: PreprErrorCode, context?: string | undefined, originalError?: Error | undefined);
|
|
165
|
-
}
|
|
166
|
-
/** Prepr Customer ID, or null if the middleware did not run for this request. */
|
|
167
|
-
declare function getPreprUUIDFromHeaders(headers: Headers): string | null;
|
|
168
|
-
/** Active segment ID, or null when no segment is selected. */
|
|
169
|
-
declare function getActiveSegmentFromHeaders(headers: Headers): string | null;
|
|
170
|
-
/** Active A/B variant (`'A'`/`'B'`), or null when no test is running. */
|
|
171
|
-
declare function getActiveVariantFromHeaders(headers: Headers): string | null;
|
|
172
|
-
/**
|
|
173
|
-
* Collect the Prepr headers into a `PreprHeaders`. Lookups are case-insensitive
|
|
174
|
-
* per the Fetch spec, but the returned keys use the declared casing.
|
|
175
|
-
*/
|
|
176
|
-
declare function getPreprHeadersFromHeaders(headers: Headers): PreprHeaders;
|
|
177
|
-
/**
|
|
178
|
-
* Asserts `token` is the full `https://graphql.prepr.io/<token>` URL.
|
|
179
|
-
* @throws PreprError if the token is missing or not an HTTPS URL.
|
|
180
|
-
*/
|
|
181
|
-
declare function validatePreprToken(token: string): void;
|
|
182
|
-
/**
|
|
183
|
-
* Pulls the access token out of a GraphQL URL: `https://graphql.prepr.io/abc123`
|
|
184
|
-
* -> `abc123`.
|
|
185
|
-
* @throws PreprError if the URL is not a valid `graphql.prepr.io` URL.
|
|
186
|
-
*/
|
|
187
|
-
declare function extractAccessToken(graphqlUrl: string): string;
|
|
188
|
-
/**
|
|
189
|
-
* Fetches the environment's segments from the Prepr API.
|
|
190
|
-
*
|
|
191
|
-
* `token` must be a Prepr GraphQL URL with scope 'segments'.
|
|
192
|
-
* @throws PreprError if the token is invalid or the request fails.
|
|
193
|
-
*/
|
|
194
|
-
declare function getPreprEnvironmentSegments(token: string): Promise<PreprSegment[]>;
|
|
195
|
-
/**
|
|
196
|
-
* Never throws: a failed segments fetch yields an empty list so the toolbar
|
|
197
|
-
* still renders. The list is returned under both `segments` and the deprecated
|
|
198
|
-
* `data` alias.
|
|
199
|
-
*
|
|
200
|
-
* Pass the same `features` object you give the toolbar and the middleware: with
|
|
201
|
-
* segments disabled the `_Segments` request is skipped entirely, saving a
|
|
202
|
-
* round-trip per page.
|
|
203
|
-
*/
|
|
204
|
-
declare function getToolbarPropsFromHeaders(headers: Headers, token: string, features?: PreprFeatures): Promise<PreprToolbarProps>;
|
|
205
|
-
|
|
206
155
|
interface CookieSpec {
|
|
207
156
|
name: string;
|
|
208
157
|
value: string;
|
|
@@ -241,4 +190,4 @@ interface PreprMiddlewareOptions {
|
|
|
241
190
|
*/
|
|
242
191
|
declare function processPreprRequest(request: Request, opts?: PreprMiddlewareOptions): PreprMiddlewareResult;
|
|
243
192
|
|
|
244
|
-
export { type CookieSpec, type CreatePreprPreviewOptions, type IframeBridgeOptions,
|
|
193
|
+
export { type CookieSpec, type CreatePreprPreviewOptions, type IframeBridgeOptions, PreprFeatures, type PreprMiddlewareOptions, type PreprMiddlewareResult, type PreprNavigationAdapter, type PreprPreviewController, PreprPreviewOptions, PreprSegment, PreprToolbarElement, PreprToolbarProps, PreprVariant, ResolvedPreprFeatures, type ToolbarState, type ToolbarStore, VERSION, createPreprPreview, createToolbarStore, definePreprToolbar, processPreprRequest, resolveFeatures, stegaClean };
|