@preprio/toolkit 0.5.0-rc.8 → 0.5.0-rc.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -851,7 +851,21 @@ The rest is about rendering:
851
851
  - Other values without a hidden edit link (video and other URLs): make
852
852
  them click-to-edit with
853
853
  `previewAttrs({ id, field }, { enabled: preview })` on the element that
854
- renders them.
854
+ renders them. Encoded text inside that element does not override it.
855
+ - Fields Prepr returns without an edit link, such as remote content, next
856
+ to a text field that has one: `stegaTarget(text, { field })` reads the
857
+ item and path from the text and points at the sibling field, ready for
858
+ `previewAttrs`. Use `products.items.2` to point at one entry.
859
+
860
+ ```tsx
861
+ // Each product card opens its row of the component's `products` field.
862
+ <article
863
+ {...previewAttrs(
864
+ stegaTarget(block.title, { field: `products.items.${index}` }),
865
+ { enabled: preview },
866
+ )}
867
+ >
868
+ ```
855
869
  - Where the page renders a linked item whose content comes from items nested
856
870
  inside it (for example a personalization or a shared section referenced
857
871
  from a stack), wrap it in an element with
@@ -31,7 +31,7 @@ __export(astro_exports, {
31
31
  module.exports = __toCommonJS(astro_exports);
32
32
 
33
33
  // src/version.ts
34
- var VERSION = "0.5.0-rc.8";
34
+ var VERSION = "0.5.0-rc.9";
35
35
 
36
36
  // src/core/features.ts
37
37
  function isEnabled(config) {
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var VERSION = "0.5.0-rc.8";
2
+ var VERSION = "0.5.0-rc.9";
3
3
 
4
4
  // src/core/features.ts
5
5
  function isEnabled(config) {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  VERSION,
3
3
  resolveFeatures
4
- } from "./chunk-Y4NMRYHE.js";
4
+ } from "./chunk-U27WFYP4.js";
5
5
 
6
6
  // src/core/server.ts
7
7
  var PreprError = class extends Error {
@@ -2,7 +2,7 @@ import {
2
2
  ALL_FEATURES_ENABLED,
3
3
  VERSION,
4
4
  resolveFeatures
5
- } from "./chunk-Y4NMRYHE.js";
5
+ } from "./chunk-U27WFYP4.js";
6
6
  import {
7
7
  createIframeBridge,
8
8
  isLocale,
@@ -530,6 +530,7 @@ function setOrRemove(element, name, value) {
530
530
  }
531
531
  }
532
532
  function tagEncodedElement(element, decoded) {
533
+ if (isSiteTagged(element)) return false;
533
534
  element.setAttribute("data-prepr-encoded", "");
534
535
  element.setAttribute("data-prepr-href", decoded.href);
535
536
  element.setAttribute("data-prepr-origin", decoded.origin);
@@ -543,6 +544,10 @@ function tagEncodedElement(element, decoded) {
543
544
  setOrRemove(element, "data-prepr-entry-id", entry);
544
545
  setOrRemove(element, AUTO_ENTRY_ATTR, entry && "true");
545
546
  }
547
+ return true;
548
+ }
549
+ function isSiteTagged(element) {
550
+ return element.hasAttribute("data-prepr-encoded") && !element.hasAttribute("data-prepr-href");
546
551
  }
547
552
  function readEditPayload(element) {
548
553
  return {
@@ -843,8 +848,7 @@ function createStegaAutoClean(options) {
843
848
  }
844
849
  pendingHidden.delete(textNode);
845
850
  if (shown.hasAttribute("data-prepr-encoded")) return false;
846
- tagEncodedElement(shown, info.decoded);
847
- return true;
851
+ return tagEncodedElement(shown, info.decoded);
848
852
  }
849
853
  try {
850
854
  const { cleaned: stripped, encoded } = vercelStegaSplit(textContent);
@@ -861,8 +865,7 @@ function createStegaAutoClean(options) {
861
865
  const target = resolveEditTarget(textNode);
862
866
  if (target) {
863
867
  pendingHidden.delete(textNode);
864
- tagEncodedElement(target, decoded);
865
- return true;
868
+ return tagEncodedElement(target, decoded);
866
869
  }
867
870
  pendingHidden.add(textNode);
868
871
  } catch (error) {
@@ -3162,6 +3165,7 @@ export {
3162
3165
  ONE_YEAR_SECONDS,
3163
3166
  HEADER_LIVE_RENDER,
3164
3167
  stegaClean,
3168
+ decodeStega,
3165
3169
  createToolbarStore,
3166
3170
  PreprToolbarElement,
3167
3171
  definePreprToolbar,
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var VERSION = "0.5.0-rc.8";
2
+ var VERSION = "0.5.0-rc.9";
3
3
 
4
4
  // src/core/features.ts
5
5
  function isEnabled(config) {
package/dist/index.cjs CHANGED
@@ -44,13 +44,14 @@ __export(src_exports, {
44
44
  setTrackingParam: () => setTrackingParam,
45
45
  startHtmlLivePreview: () => startHtmlLivePreview,
46
46
  stegaClean: () => stegaClean,
47
+ stegaTarget: () => stegaTarget,
47
48
  trackEvent: () => trackEvent,
48
49
  validatePreprToken: () => validatePreprToken
49
50
  });
50
51
  module.exports = __toCommonJS(src_exports);
51
52
 
52
53
  // src/version.ts
53
- var VERSION = "0.5.0-rc.8";
54
+ var VERSION = "0.5.0-rc.9";
54
55
 
55
56
  // src/core/features.ts
56
57
  function isEnabled(config) {
@@ -621,6 +622,7 @@ function setOrRemove(element, name, value) {
621
622
  }
622
623
  }
623
624
  function tagEncodedElement(element, decoded) {
625
+ if (isSiteTagged(element)) return false;
624
626
  element.setAttribute("data-prepr-encoded", "");
625
627
  element.setAttribute("data-prepr-href", decoded.href);
626
628
  element.setAttribute("data-prepr-origin", decoded.origin);
@@ -634,6 +636,10 @@ function tagEncodedElement(element, decoded) {
634
636
  setOrRemove(element, "data-prepr-entry-id", entry);
635
637
  setOrRemove(element, AUTO_ENTRY_ATTR, entry && "true");
636
638
  }
639
+ return true;
640
+ }
641
+ function isSiteTagged(element) {
642
+ return element.hasAttribute("data-prepr-encoded") && !element.hasAttribute("data-prepr-href");
637
643
  }
638
644
  function readEditPayload(element) {
639
645
  return {
@@ -670,8 +676,7 @@ function createStegaAutoClean(options) {
670
676
  }
671
677
  pendingHidden.delete(textNode);
672
678
  if (shown.hasAttribute("data-prepr-encoded")) return false;
673
- tagEncodedElement(shown, info.decoded);
674
- return true;
679
+ return tagEncodedElement(shown, info.decoded);
675
680
  }
676
681
  try {
677
682
  const { cleaned: stripped, encoded } = (0, import_stega2.vercelStegaSplit)(textContent);
@@ -688,8 +693,7 @@ function createStegaAutoClean(options) {
688
693
  const target = resolveEditTarget(textNode);
689
694
  if (target) {
690
695
  pendingHidden.delete(textNode);
691
- tagEncodedElement(target, decoded);
692
- return true;
696
+ return tagEncodedElement(target, decoded);
693
697
  }
694
698
  pendingHidden.add(textNode);
695
699
  } catch (error) {
@@ -3557,7 +3561,7 @@ function createPreprPreview(opts = {}) {
3557
3561
 
3558
3562
  // src/core/preview-attrs.ts
3559
3563
  function previewAttrs(target, options) {
3560
- if (!options.enabled || !target.id || !target.field) return {};
3564
+ if (!options.enabled || !target?.id || !target.field) return {};
3561
3565
  const attrs = {
3562
3566
  "data-prepr-encoded": "",
3563
3567
  "data-prepr-id": target.id,
@@ -3567,6 +3571,25 @@ function previewAttrs(target, options) {
3567
3571
  if (target.entryId) attrs["data-prepr-entry-id"] = target.entryId;
3568
3572
  return attrs;
3569
3573
  }
3574
+ var URL_BASE = "https://prepr.invalid";
3575
+ function stegaTarget(value, options = {}) {
3576
+ const decoded = value ? decodeStega(value) : null;
3577
+ if (!decoded) return null;
3578
+ let url;
3579
+ try {
3580
+ url = new URL(decoded.href, URL_BASE);
3581
+ } catch {
3582
+ return null;
3583
+ }
3584
+ const id = decodeURIComponent(url.pathname.split("/").pop() ?? "");
3585
+ const field = url.searchParams.get("field");
3586
+ if (!id || !field) return null;
3587
+ return {
3588
+ id,
3589
+ field: options.field ? `${field.slice(0, field.lastIndexOf(".") + 1)}${options.field}` : field,
3590
+ locale: url.searchParams.get("locale")
3591
+ };
3592
+ }
3570
3593
 
3571
3594
  // src/core/live-preview/normalize-query.ts
3572
3595
  var import_stega6 = require("@vercel/stega");
@@ -5655,6 +5678,7 @@ function setTrackingParam(key, value) {
5655
5678
  setTrackingParam,
5656
5679
  startHtmlLivePreview,
5657
5680
  stegaClean,
5681
+ stegaTarget,
5658
5682
  trackEvent,
5659
5683
  validatePreprToken
5660
5684
  });
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.5.0-rc.8";
8
+ declare const VERSION = "0.5.0-rc.9";
9
9
 
10
10
  /**
11
11
  * Resolve a `PreprFeatures` bag to plain booleans, defaulting every omitted key
@@ -262,10 +262,34 @@ interface PreviewAttrsOptions {
262
262
  * <figure {...previewAttrs({ id: post._id, field: 'cover_image' }, { enabled: isPreview })}>
263
263
  * ```
264
264
  *
265
- * Returns an empty object when disabled or when there is no id, so it is safe
266
- * to spread unconditionally.
265
+ * Returns an empty object when disabled or when there is no target or id, so
266
+ * it is safe to spread unconditionally.
267
267
  */
268
- declare function previewAttrs(target: PreviewAttrsTarget, options: PreviewAttrsOptions): Record<string, string>;
268
+ declare function previewAttrs(target: PreviewAttrsTarget | null | undefined, options: PreviewAttrsOptions): Record<string, string>;
269
+ interface StegaTargetOptions {
270
+ /**
271
+ * A field next to the encoded one, in the same item or component, to target
272
+ * instead: a dotted path that replaces the encoded field's last segment
273
+ * (`products`, or `products.items.2` for one entry of it).
274
+ */
275
+ field?: string;
276
+ }
277
+ /**
278
+ * The edit target behind a text value Prepr returned with a hidden edit link,
279
+ * for {@link previewAttrs}. Reach for it when the field to edit carries no
280
+ * link of its own, such as remote content or a list of references, but a
281
+ * text field of the same component does: the component's title points the
282
+ * way to its `products`.
283
+ *
284
+ * ```tsx
285
+ * const products = stegaTarget(block.title, { field: 'products' });
286
+ * <article {...previewAttrs(products, { enabled: isPreview })}>
287
+ * ```
288
+ *
289
+ * Returns null for a value without an edit link (a production render, or a
290
+ * value Prepr does not encode). Works on the server and in the browser.
291
+ */
292
+ declare function stegaTarget(value: string | null | undefined, options?: StegaTargetOptions): PreviewAttrsTarget | null;
269
293
 
270
294
  /** Values a push may write. Everything else goes through refetch. */
271
295
  type LiveScalar = string | number | boolean;
@@ -488,4 +512,4 @@ interface PreprMiddlewareOptions {
488
512
  */
489
513
  declare function processPreprRequest(request: Request, opts?: PreprMiddlewareOptions): PreprMiddlewareResult;
490
514
 
491
- export { type CookieSpec, type CreatePreprPreviewOptions, type HtmlLivePreview, type HtmlLivePreviewOptions, type IframeBridgeOptions, type LivePatch, type NormalizeQueryOptions, PreprError, PreprErrorCode, PreprFeatures, PreprHeaders, type PreprMiddlewareOptions, type PreprMiddlewareResult, type PreprNavigationAdapter, type PreprPreviewController, PreprPreviewOptions, PreprSegment, PreprToolbarElement, PreprToolbarProps, PreprVariant, type PreviewAttrsOptions, type PreviewAttrsTarget, type QueryInput, ResolvedPreprFeatures, type ToolbarState, type ToolbarStore, VERSION, annotateEditLinks, createPreprPreview, createToolbarStore, definePreprToolbar, extractAccessToken, getActiveSegmentFromHeaders, getActiveVariantFromHeaders, getPreprEnvironmentSegments, getPreprHeadersFromHeaders, getPreprUUIDFromHeaders, getToolbarPropsFromHeaders, normalizeQuery, parsePatchLog, previewAttrs, processPreprRequest, readLiveLogFromRequest, resolveFeatures, startHtmlLivePreview, stegaClean, validatePreprToken };
515
+ export { type CookieSpec, type CreatePreprPreviewOptions, type HtmlLivePreview, type HtmlLivePreviewOptions, type IframeBridgeOptions, type LivePatch, type NormalizeQueryOptions, PreprError, PreprErrorCode, PreprFeatures, PreprHeaders, type PreprMiddlewareOptions, type PreprMiddlewareResult, type PreprNavigationAdapter, type PreprPreviewController, PreprPreviewOptions, PreprSegment, PreprToolbarElement, PreprToolbarProps, PreprVariant, type PreviewAttrsOptions, type PreviewAttrsTarget, type QueryInput, ResolvedPreprFeatures, type StegaTargetOptions, type ToolbarState, type ToolbarStore, VERSION, annotateEditLinks, createPreprPreview, createToolbarStore, definePreprToolbar, extractAccessToken, getActiveSegmentFromHeaders, getActiveVariantFromHeaders, getPreprEnvironmentSegments, getPreprHeadersFromHeaders, getPreprUUIDFromHeaders, getToolbarPropsFromHeaders, normalizeQuery, parsePatchLog, previewAttrs, processPreprRequest, readLiveLogFromRequest, resolveFeatures, startHtmlLivePreview, stegaClean, stegaTarget, validatePreprToken };
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.5.0-rc.8";
8
+ declare const VERSION = "0.5.0-rc.9";
9
9
 
10
10
  /**
11
11
  * Resolve a `PreprFeatures` bag to plain booleans, defaulting every omitted key
@@ -262,10 +262,34 @@ interface PreviewAttrsOptions {
262
262
  * <figure {...previewAttrs({ id: post._id, field: 'cover_image' }, { enabled: isPreview })}>
263
263
  * ```
264
264
  *
265
- * Returns an empty object when disabled or when there is no id, so it is safe
266
- * to spread unconditionally.
265
+ * Returns an empty object when disabled or when there is no target or id, so
266
+ * it is safe to spread unconditionally.
267
267
  */
268
- declare function previewAttrs(target: PreviewAttrsTarget, options: PreviewAttrsOptions): Record<string, string>;
268
+ declare function previewAttrs(target: PreviewAttrsTarget | null | undefined, options: PreviewAttrsOptions): Record<string, string>;
269
+ interface StegaTargetOptions {
270
+ /**
271
+ * A field next to the encoded one, in the same item or component, to target
272
+ * instead: a dotted path that replaces the encoded field's last segment
273
+ * (`products`, or `products.items.2` for one entry of it).
274
+ */
275
+ field?: string;
276
+ }
277
+ /**
278
+ * The edit target behind a text value Prepr returned with a hidden edit link,
279
+ * for {@link previewAttrs}. Reach for it when the field to edit carries no
280
+ * link of its own, such as remote content or a list of references, but a
281
+ * text field of the same component does: the component's title points the
282
+ * way to its `products`.
283
+ *
284
+ * ```tsx
285
+ * const products = stegaTarget(block.title, { field: 'products' });
286
+ * <article {...previewAttrs(products, { enabled: isPreview })}>
287
+ * ```
288
+ *
289
+ * Returns null for a value without an edit link (a production render, or a
290
+ * value Prepr does not encode). Works on the server and in the browser.
291
+ */
292
+ declare function stegaTarget(value: string | null | undefined, options?: StegaTargetOptions): PreviewAttrsTarget | null;
269
293
 
270
294
  /** Values a push may write. Everything else goes through refetch. */
271
295
  type LiveScalar = string | number | boolean;
@@ -488,4 +512,4 @@ interface PreprMiddlewareOptions {
488
512
  */
489
513
  declare function processPreprRequest(request: Request, opts?: PreprMiddlewareOptions): PreprMiddlewareResult;
490
514
 
491
- export { type CookieSpec, type CreatePreprPreviewOptions, type HtmlLivePreview, type HtmlLivePreviewOptions, type IframeBridgeOptions, type LivePatch, type NormalizeQueryOptions, PreprError, PreprErrorCode, PreprFeatures, PreprHeaders, type PreprMiddlewareOptions, type PreprMiddlewareResult, type PreprNavigationAdapter, type PreprPreviewController, PreprPreviewOptions, PreprSegment, PreprToolbarElement, PreprToolbarProps, PreprVariant, type PreviewAttrsOptions, type PreviewAttrsTarget, type QueryInput, ResolvedPreprFeatures, type ToolbarState, type ToolbarStore, VERSION, annotateEditLinks, createPreprPreview, createToolbarStore, definePreprToolbar, extractAccessToken, getActiveSegmentFromHeaders, getActiveVariantFromHeaders, getPreprEnvironmentSegments, getPreprHeadersFromHeaders, getPreprUUIDFromHeaders, getToolbarPropsFromHeaders, normalizeQuery, parsePatchLog, previewAttrs, processPreprRequest, readLiveLogFromRequest, resolveFeatures, startHtmlLivePreview, stegaClean, validatePreprToken };
515
+ export { type CookieSpec, type CreatePreprPreviewOptions, type HtmlLivePreview, type HtmlLivePreviewOptions, type IframeBridgeOptions, type LivePatch, type NormalizeQueryOptions, PreprError, PreprErrorCode, PreprFeatures, PreprHeaders, type PreprMiddlewareOptions, type PreprMiddlewareResult, type PreprNavigationAdapter, type PreprPreviewController, PreprPreviewOptions, PreprSegment, PreprToolbarElement, PreprToolbarProps, PreprVariant, type PreviewAttrsOptions, type PreviewAttrsTarget, type QueryInput, ResolvedPreprFeatures, type StegaTargetOptions, type ToolbarState, type ToolbarStore, VERSION, annotateEditLinks, createPreprPreview, createToolbarStore, definePreprToolbar, extractAccessToken, getActiveSegmentFromHeaders, getActiveVariantFromHeaders, getPreprEnvironmentSegments, getPreprHeadersFromHeaders, getPreprUUIDFromHeaders, getToolbarPropsFromHeaders, normalizeQuery, parsePatchLog, previewAttrs, processPreprRequest, readLiveLogFromRequest, resolveFeatures, startHtmlLivePreview, stegaClean, stegaTarget, validatePreprToken };
package/dist/index.js CHANGED
@@ -12,12 +12,13 @@ import {
12
12
  PreprToolbarElement,
13
13
  createPreprPreview,
14
14
  createToolbarStore,
15
+ decodeStega,
15
16
  definePreprToolbar,
16
17
  loadTrackingPixel,
17
18
  setTrackingParam,
18
19
  stegaClean,
19
20
  trackEvent
20
- } from "./chunk-4OXPPBVF.js";
21
+ } from "./chunk-H2GX6JD5.js";
21
22
  import {
22
23
  PreprError,
23
24
  extractAccessToken,
@@ -28,11 +29,11 @@ import {
28
29
  getPreprUUIDFromHeaders,
29
30
  getToolbarPropsFromHeaders,
30
31
  validatePreprToken
31
- } from "./chunk-VNKYFJJS.js";
32
+ } from "./chunk-CVVFPVYX.js";
32
33
  import {
33
34
  VERSION,
34
35
  resolveFeatures
35
- } from "./chunk-Y4NMRYHE.js";
36
+ } from "./chunk-U27WFYP4.js";
36
37
  import {
37
38
  createLiveBridge,
38
39
  createLiveStore
@@ -50,7 +51,7 @@ import {
50
51
 
51
52
  // src/core/preview-attrs.ts
52
53
  function previewAttrs(target, options) {
53
- if (!options.enabled || !target.id || !target.field) return {};
54
+ if (!options.enabled || !target?.id || !target.field) return {};
54
55
  const attrs = {
55
56
  "data-prepr-encoded": "",
56
57
  "data-prepr-id": target.id,
@@ -60,6 +61,25 @@ function previewAttrs(target, options) {
60
61
  if (target.entryId) attrs["data-prepr-entry-id"] = target.entryId;
61
62
  return attrs;
62
63
  }
64
+ var URL_BASE = "https://prepr.invalid";
65
+ function stegaTarget(value, options = {}) {
66
+ const decoded = value ? decodeStega(value) : null;
67
+ if (!decoded) return null;
68
+ let url;
69
+ try {
70
+ url = new URL(decoded.href, URL_BASE);
71
+ } catch {
72
+ return null;
73
+ }
74
+ const id = decodeURIComponent(url.pathname.split("/").pop() ?? "");
75
+ const field = url.searchParams.get("field");
76
+ if (!id || !field) return null;
77
+ return {
78
+ id,
79
+ field: options.field ? `${field.slice(0, field.lastIndexOf(".") + 1)}${options.field}` : field,
80
+ locale: url.searchParams.get("locale")
81
+ };
82
+ }
63
83
 
64
84
  // src/core/live-preview/edit-links.ts
65
85
  import {
@@ -498,6 +518,7 @@ export {
498
518
  setTrackingParam,
499
519
  startHtmlLivePreview,
500
520
  stegaClean,
521
+ stegaTarget,
501
522
  trackEvent,
502
523
  validatePreprToken
503
524
  };
@@ -587,6 +587,7 @@ function setOrRemove(element, name, value) {
587
587
  }
588
588
  }
589
589
  function tagEncodedElement(element, decoded) {
590
+ if (isSiteTagged(element)) return false;
590
591
  element.setAttribute("data-prepr-encoded", "");
591
592
  element.setAttribute("data-prepr-href", decoded.href);
592
593
  element.setAttribute("data-prepr-origin", decoded.origin);
@@ -600,6 +601,10 @@ function tagEncodedElement(element, decoded) {
600
601
  setOrRemove(element, "data-prepr-entry-id", entry);
601
602
  setOrRemove(element, AUTO_ENTRY_ATTR, entry && "true");
602
603
  }
604
+ return true;
605
+ }
606
+ function isSiteTagged(element) {
607
+ return element.hasAttribute("data-prepr-encoded") && !element.hasAttribute("data-prepr-href");
603
608
  }
604
609
  function readEditPayload(element) {
605
610
  return {
@@ -636,8 +641,7 @@ function createStegaAutoClean(options) {
636
641
  }
637
642
  pendingHidden.delete(textNode);
638
643
  if (shown.hasAttribute("data-prepr-encoded")) return false;
639
- tagEncodedElement(shown, info.decoded);
640
- return true;
644
+ return tagEncodedElement(shown, info.decoded);
641
645
  }
642
646
  try {
643
647
  const { cleaned: stripped, encoded } = (0, import_stega2.vercelStegaSplit)(textContent);
@@ -654,8 +658,7 @@ function createStegaAutoClean(options) {
654
658
  const target = resolveEditTarget(textNode);
655
659
  if (target) {
656
660
  pendingHidden.delete(textNode);
657
- tagEncodedElement(target, decoded);
658
- return true;
661
+ return tagEncodedElement(target, decoded);
659
662
  }
660
663
  pendingHidden.add(textNode);
661
664
  } catch (error) {
@@ -3525,7 +3528,7 @@ function createPreprPreview(opts = {}) {
3525
3528
  var import_react = require("react");
3526
3529
 
3527
3530
  // src/version.ts
3528
- var VERSION = "0.5.0-rc.8";
3531
+ var VERSION = "0.5.0-rc.9";
3529
3532
 
3530
3533
  // src/core/pixel.ts
3531
3534
  var PIXEL_SCRIPT_URL = "https://cdn.tracking.prepr.io/js/prepr.min.js";
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  createPreprPreview,
4
4
  loadTrackingPixel
5
- } from "../chunk-4OXPPBVF.js";
6
- import "../chunk-Y4NMRYHE.js";
5
+ } from "../chunk-H2GX6JD5.js";
6
+ import "../chunk-U27WFYP4.js";
7
7
  import "../chunk-URXSDJOU.js";
8
8
  import "../chunk-S3VT4UWM.js";
9
9
 
@@ -49,7 +49,7 @@ module.exports = __toCommonJS(nextjs_exports);
49
49
  var import_server = require("next/server");
50
50
 
51
51
  // src/version.ts
52
- var VERSION = "0.5.0-rc.8";
52
+ var VERSION = "0.5.0-rc.9";
53
53
 
54
54
  // src/core/constants.ts
55
55
  var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
@@ -2,7 +2,7 @@
2
2
  import { NextResponse } from "next/server";
3
3
 
4
4
  // src/version.ts
5
- var VERSION = "0.5.0-rc.8";
5
+ var VERSION = "0.5.0-rc.9";
6
6
 
7
7
  // src/core/constants.ts
8
8
  var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
@@ -1,8 +1,8 @@
1
1
  "use server";
2
2
  import {
3
3
  isPreviewFromHeaders
4
- } from "../chunk-VNKYFJJS.js";
5
- import "../chunk-Y4NMRYHE.js";
4
+ } from "../chunk-CVVFPVYX.js";
5
+ import "../chunk-U27WFYP4.js";
6
6
  import {
7
7
  parsePatchLog
8
8
  } from "../chunk-KD3GK6TO.js";
@@ -35,7 +35,7 @@ __export(nuxt_exports, {
35
35
  module.exports = __toCommonJS(nuxt_exports);
36
36
 
37
37
  // src/version.ts
38
- var VERSION = "0.5.0-rc.8";
38
+ var VERSION = "0.5.0-rc.9";
39
39
 
40
40
  // src/core/constants.ts
41
41
  var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var VERSION = "0.5.0-rc.8";
2
+ var VERSION = "0.5.0-rc.9";
3
3
 
4
4
  // src/core/constants.ts
5
5
  var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
@@ -586,6 +586,7 @@ function setOrRemove(element, name, value) {
586
586
  }
587
587
  }
588
588
  function tagEncodedElement(element, decoded) {
589
+ if (isSiteTagged(element)) return false;
589
590
  element.setAttribute("data-prepr-encoded", "");
590
591
  element.setAttribute("data-prepr-href", decoded.href);
591
592
  element.setAttribute("data-prepr-origin", decoded.origin);
@@ -599,6 +600,10 @@ function tagEncodedElement(element, decoded) {
599
600
  setOrRemove(element, "data-prepr-entry-id", entry);
600
601
  setOrRemove(element, AUTO_ENTRY_ATTR, entry && "true");
601
602
  }
603
+ return true;
604
+ }
605
+ function isSiteTagged(element) {
606
+ return element.hasAttribute("data-prepr-encoded") && !element.hasAttribute("data-prepr-href");
602
607
  }
603
608
  function readEditPayload(element) {
604
609
  return {
@@ -635,8 +640,7 @@ function createStegaAutoClean(options) {
635
640
  }
636
641
  pendingHidden.delete(textNode);
637
642
  if (shown.hasAttribute("data-prepr-encoded")) return false;
638
- tagEncodedElement(shown, info.decoded);
639
- return true;
643
+ return tagEncodedElement(shown, info.decoded);
640
644
  }
641
645
  try {
642
646
  const { cleaned: stripped, encoded } = (0, import_stega2.vercelStegaSplit)(textContent);
@@ -653,8 +657,7 @@ function createStegaAutoClean(options) {
653
657
  const target = resolveEditTarget(textNode);
654
658
  if (target) {
655
659
  pendingHidden.delete(textNode);
656
- tagEncodedElement(target, decoded);
657
- return true;
660
+ return tagEncodedElement(target, decoded);
658
661
  }
659
662
  pendingHidden.add(textNode);
660
663
  } catch (error) {
@@ -3521,7 +3524,7 @@ function createPreprPreview(opts = {}) {
3521
3524
  }
3522
3525
 
3523
3526
  // src/version.ts
3524
- var VERSION = "0.5.0-rc.8";
3527
+ var VERSION = "0.5.0-rc.9";
3525
3528
 
3526
3529
  // src/core/pixel.ts
3527
3530
  var PIXEL_SCRIPT_URL = "https://cdn.tracking.prepr.io/js/prepr.min.js";
@@ -562,6 +562,7 @@ function setOrRemove(element, name, value) {
562
562
  }
563
563
  }
564
564
  function tagEncodedElement(element, decoded) {
565
+ if (isSiteTagged(element)) return false;
565
566
  element.setAttribute("data-prepr-encoded", "");
566
567
  element.setAttribute("data-prepr-href", decoded.href);
567
568
  element.setAttribute("data-prepr-origin", decoded.origin);
@@ -575,6 +576,10 @@ function tagEncodedElement(element, decoded) {
575
576
  setOrRemove(element, "data-prepr-entry-id", entry);
576
577
  setOrRemove(element, AUTO_ENTRY_ATTR, entry && "true");
577
578
  }
579
+ return true;
580
+ }
581
+ function isSiteTagged(element) {
582
+ return element.hasAttribute("data-prepr-encoded") && !element.hasAttribute("data-prepr-href");
578
583
  }
579
584
  function readEditPayload(element) {
580
585
  return {
@@ -611,8 +616,7 @@ function createStegaAutoClean(options) {
611
616
  }
612
617
  pendingHidden.delete(textNode);
613
618
  if (shown.hasAttribute("data-prepr-encoded")) return false;
614
- tagEncodedElement(shown, info.decoded);
615
- return true;
619
+ return tagEncodedElement(shown, info.decoded);
616
620
  }
617
621
  try {
618
622
  const { cleaned: stripped, encoded } = vercelStegaSplit(textContent);
@@ -629,8 +633,7 @@ function createStegaAutoClean(options) {
629
633
  const target = resolveEditTarget(textNode);
630
634
  if (target) {
631
635
  pendingHidden.delete(textNode);
632
- tagEncodedElement(target, decoded);
633
- return true;
636
+ return tagEncodedElement(target, decoded);
634
637
  }
635
638
  pendingHidden.add(textNode);
636
639
  } catch (error) {
@@ -3497,7 +3500,7 @@ function createPreprPreview(opts = {}) {
3497
3500
  }
3498
3501
 
3499
3502
  // src/version.ts
3500
- var VERSION = "0.5.0-rc.8";
3503
+ var VERSION = "0.5.0-rc.9";
3501
3504
 
3502
3505
  // src/core/pixel.ts
3503
3506
  var PIXEL_SCRIPT_URL = "https://cdn.tracking.prepr.io/js/prepr.min.js";
@@ -35,7 +35,7 @@ __export(sveltekit_exports, {
35
35
  module.exports = __toCommonJS(sveltekit_exports);
36
36
 
37
37
  // src/version.ts
38
- var VERSION = "0.5.0-rc.8";
38
+ var VERSION = "0.5.0-rc.9";
39
39
 
40
40
  // src/core/constants.ts
41
41
  var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var VERSION = "0.5.0-rc.8";
2
+ var VERSION = "0.5.0-rc.9";
3
3
 
4
4
  // src/core/constants.ts
5
5
  var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@preprio/toolkit",
3
- "version": "0.5.0-rc.8",
3
+ "version": "0.5.0-rc.9",
4
4
  "description": "Prepr personalization, A/B testing and preview toolkit for React, Next.js, Nuxt, Astro, SvelteKit and Express",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Prepr B.V. (https://prepr.io)",