@preprio/toolkit 0.6.0-alpha.6 → 0.6.0-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +138 -52
- package/dist/astro/{chunk-MWRA3732.js → chunk-3EXK2LHI.js} +1 -1
- package/dist/astro/graphql.cjs +58 -10
- package/dist/astro/graphql.d.cts +33 -38
- package/dist/astro/graphql.d.ts +33 -38
- package/dist/astro/graphql.js +59 -11
- package/dist/astro/index.cjs +1 -1
- package/dist/astro/index.js +1 -1
- package/dist/{chunk-OQGEL4TV.js → chunk-3QGWCYTL.js} +1 -1
- package/dist/{chunk-W6AVX6FI.js → chunk-PFJO4TYL.js} +52 -5
- package/dist/{chunk-Y7DWVOOY.js → chunk-U7TRFVK7.js} +1 -1
- package/dist/{chunk-NSQOGI5K.js → chunk-VQIPTUN4.js} +1 -1
- package/dist/graphql/codegen.cjs +51 -4
- package/dist/graphql/codegen.js +3 -3
- package/dist/graphql.cjs +89 -10
- package/dist/graphql.d.cts +69 -39
- package/dist/graphql.d.ts +69 -39
- package/dist/graphql.js +38 -9
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -3
- package/dist/nextjs/{chunk-PIQF5ZI5.js → chunk-CZK7SMBD.js} +58 -53
- package/dist/nextjs/components.cjs +175 -242
- package/dist/nextjs/components.d.cts +25 -21
- package/dist/nextjs/components.d.ts +25 -21
- package/dist/nextjs/components.js +167 -236
- package/dist/nextjs/graphql.cjs +372 -509
- package/dist/nextjs/graphql.d.cts +131 -135
- package/dist/nextjs/graphql.d.ts +131 -135
- package/dist/nextjs/graphql.js +307 -456
- package/dist/nextjs/index.cjs +114 -54
- package/dist/nextjs/index.d.cts +57 -33
- package/dist/nextjs/index.d.ts +57 -33
- package/dist/nextjs/index.js +108 -5
- package/dist/nuxt/{chunk-PF6GVWHV.js → chunk-JL33ENCM.js} +1 -1
- package/dist/nuxt/graphql.cjs +58 -10
- package/dist/nuxt/graphql.d.cts +33 -38
- package/dist/nuxt/graphql.d.ts +33 -38
- package/dist/nuxt/graphql.js +59 -11
- package/dist/nuxt/index.cjs +1 -1
- package/dist/nuxt/index.js +1 -1
- package/dist/react/components.cjs +1 -1
- package/dist/react/components.js +1 -1
- package/dist/sveltekit/{chunk-5K7HWMIF.js → chunk-S7S276V7.js} +1 -1
- package/dist/sveltekit/graphql.cjs +58 -10
- package/dist/sveltekit/graphql.d.cts +33 -38
- package/dist/sveltekit/graphql.d.ts +33 -38
- package/dist/sveltekit/graphql.js +59 -11
- package/dist/sveltekit/index.cjs +1 -1
- package/dist/sveltekit/index.js +1 -1
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { NextResponse } from "next/server";
|
|
3
3
|
|
|
4
4
|
// src/version.ts
|
|
5
|
-
var VERSION = "0.6.0-alpha.
|
|
5
|
+
var VERSION = "0.6.0-alpha.7";
|
|
6
6
|
|
|
7
7
|
// src/core/constants.ts
|
|
8
8
|
var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
|
|
@@ -426,55 +426,6 @@ function isPersonalizedResponse(source) {
|
|
|
426
426
|
return PERSONALIZED_VARY.test(headers2.get("vary") ?? "");
|
|
427
427
|
}
|
|
428
428
|
|
|
429
|
-
// src/nextjs/bucket.ts
|
|
430
|
-
var PREPR_BUCKET_COOKIE = "prepr_ab_bucket";
|
|
431
|
-
var isBucket = (value) => value === "A" || value === "B";
|
|
432
|
-
function setBucketCookie(request, response, bucket) {
|
|
433
|
-
response.cookies.set(PREPR_BUCKET_COOKIE, bucket, {
|
|
434
|
-
path: "/",
|
|
435
|
-
sameSite: "lax",
|
|
436
|
-
// Readable on purpose: PreprStack's inline switch reads it before first
|
|
437
|
-
// paint. It holds only "A" or "B".
|
|
438
|
-
httpOnly: false,
|
|
439
|
-
secure: request.nextUrl.protocol === "https:",
|
|
440
|
-
maxAge: 60 * 60 * 24 * 365
|
|
441
|
-
});
|
|
442
|
-
}
|
|
443
|
-
async function resolvePreprBucket(request, response, options) {
|
|
444
|
-
const stored = request.cookies.get(PREPR_BUCKET_COOKIE)?.value;
|
|
445
|
-
const forced = response.headers.get("x-middleware-request-prepr-abtesting") ?? request.cookies.get(COOKIE_VARIANT)?.value;
|
|
446
|
-
if (options.preview && isBucket(forced)) {
|
|
447
|
-
if (forced !== stored) setBucketCookie(request, response, forced);
|
|
448
|
-
return forced;
|
|
449
|
-
}
|
|
450
|
-
if (isBucket(stored)) return stored;
|
|
451
|
-
if (options.onlyIf) {
|
|
452
|
-
const needed = await Promise.resolve().then(options.onlyIf).catch(() => true);
|
|
453
|
-
if (!needed) return "A";
|
|
454
|
-
}
|
|
455
|
-
const customerId = request.cookies.get(COOKIE_UID)?.value ?? response.cookies.get(COOKIE_UID)?.value;
|
|
456
|
-
if (!customerId) return "A";
|
|
457
|
-
try {
|
|
458
|
-
const res = await fetch(options.url, {
|
|
459
|
-
method: "POST",
|
|
460
|
-
headers: {
|
|
461
|
-
"Content-Type": "application/json",
|
|
462
|
-
"Prepr-Customer-Id": customerId
|
|
463
|
-
},
|
|
464
|
-
body: JSON.stringify({ query: "{ __typename }" }),
|
|
465
|
-
cache: "no-store",
|
|
466
|
-
signal: AbortSignal.timeout(options.timeoutMs ?? 1500)
|
|
467
|
-
});
|
|
468
|
-
const bucket = res.headers.get("x-prepr-customer-bucket");
|
|
469
|
-
if (isBucket(bucket)) {
|
|
470
|
-
setBucketCookie(request, response, bucket);
|
|
471
|
-
return bucket;
|
|
472
|
-
}
|
|
473
|
-
} catch {
|
|
474
|
-
}
|
|
475
|
-
return "A";
|
|
476
|
-
}
|
|
477
|
-
|
|
478
429
|
// src/nextjs/draft.ts
|
|
479
430
|
import { cookies, draftMode } from "next/headers";
|
|
480
431
|
import { redirect } from "next/navigation";
|
|
@@ -525,6 +476,56 @@ function createPreprDraftRoute(options) {
|
|
|
525
476
|
};
|
|
526
477
|
}
|
|
527
478
|
|
|
479
|
+
// src/core/graphql/cache-tags.ts
|
|
480
|
+
var MAX_TAGS = 128;
|
|
481
|
+
var MAX_TAG_LENGTH = 256;
|
|
482
|
+
var PREPR_ANY_ITEM_TAG = "prepr:any";
|
|
483
|
+
var PREPR_SCHEMA_TAG = "prepr:schema";
|
|
484
|
+
var preprItemTag = (id) => `prepr:${id}`;
|
|
485
|
+
var NOT_ALPHANUMERIC = /[^a-z0-9]/g;
|
|
486
|
+
var preprModelTag = (model) => `prepr:model:${model.toLowerCase().replace(NOT_ALPHANUMERIC, "")}`;
|
|
487
|
+
function preprModelTagsFor(document, data, schema) {
|
|
488
|
+
const operation = document.definitions.find(
|
|
489
|
+
(definition) => definition.kind === "OperationDefinition" && definition.operation === "query"
|
|
490
|
+
);
|
|
491
|
+
const root = schema.types[schema.queryType];
|
|
492
|
+
if (!operation || !root) return [];
|
|
493
|
+
const models = (type) => {
|
|
494
|
+
const members = schema.types[type]?.possibleTypes ?? [];
|
|
495
|
+
return members.length > 0 ? members : [type];
|
|
496
|
+
};
|
|
497
|
+
const tags = /* @__PURE__ */ new Set();
|
|
498
|
+
for (const selection of operation.selectionSet.selections) {
|
|
499
|
+
if (selection.kind !== "Field") continue;
|
|
500
|
+
const type = root.fields[selection.name.value]?.type;
|
|
501
|
+
const info = type ? schema.types[type] : void 0;
|
|
502
|
+
if (!type || !info) continue;
|
|
503
|
+
const items = info.fields.items?.type;
|
|
504
|
+
const key = (selection.alias ?? selection.name).value;
|
|
505
|
+
const found = typeof data === "object" && data !== null && data[key] != null;
|
|
506
|
+
const affected = items ? models(items) : found ? [] : models(type);
|
|
507
|
+
for (const model of affected) tags.add(preprModelTag(model));
|
|
508
|
+
}
|
|
509
|
+
return [...tags];
|
|
510
|
+
}
|
|
511
|
+
function preprCacheTags(data) {
|
|
512
|
+
const tags = /* @__PURE__ */ new Set();
|
|
513
|
+
const stack = [data];
|
|
514
|
+
while (stack.length > 0) {
|
|
515
|
+
const value = stack.pop();
|
|
516
|
+
if (typeof value !== "object" || value === null) continue;
|
|
517
|
+
const id = value._id;
|
|
518
|
+
if (typeof id === "string" && id !== "") {
|
|
519
|
+
const tag = preprItemTag(id);
|
|
520
|
+
if (tag.length > MAX_TAG_LENGTH) return [PREPR_ANY_ITEM_TAG];
|
|
521
|
+
tags.add(tag);
|
|
522
|
+
if (tags.size > MAX_TAGS) return [PREPR_ANY_ITEM_TAG];
|
|
523
|
+
}
|
|
524
|
+
for (const child of Object.values(value)) stack.push(child);
|
|
525
|
+
}
|
|
526
|
+
return [...tags];
|
|
527
|
+
}
|
|
528
|
+
|
|
528
529
|
export {
|
|
529
530
|
createPreprMiddleware,
|
|
530
531
|
PreprError,
|
|
@@ -537,8 +538,12 @@ export {
|
|
|
537
538
|
getPreprHeaders,
|
|
538
539
|
getToolbarProps,
|
|
539
540
|
isPersonalizedResponse,
|
|
540
|
-
PREPR_BUCKET_COOKIE,
|
|
541
|
-
resolvePreprBucket,
|
|
542
541
|
preprDraftRedirect,
|
|
543
|
-
createPreprDraftRoute
|
|
542
|
+
createPreprDraftRoute,
|
|
543
|
+
PREPR_ANY_ITEM_TAG,
|
|
544
|
+
PREPR_SCHEMA_TAG,
|
|
545
|
+
preprItemTag,
|
|
546
|
+
preprModelTag,
|
|
547
|
+
preprModelTagsFor,
|
|
548
|
+
preprCacheTags
|
|
544
549
|
};
|
|
@@ -21,7 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
// src/nextjs/components.ts
|
|
22
22
|
var components_exports = {};
|
|
23
23
|
__export(components_exports, {
|
|
24
|
-
|
|
24
|
+
PreprDecisionApplier: () => PreprDecisionApplier,
|
|
25
25
|
PreprPersonalizationSwitch: () => PreprPersonalizationSwitch,
|
|
26
26
|
PreprToolbar: () => PreprToolbar,
|
|
27
27
|
PreprTrackingPixel: () => PreprTrackingPixel,
|
|
@@ -458,11 +458,11 @@ function createStegaAutoClean(options) {
|
|
|
458
458
|
const settled = stripText ? info?.cleaned : info?.original;
|
|
459
459
|
if (info && textContent === settled) {
|
|
460
460
|
if (!info.decoded) return false;
|
|
461
|
-
const
|
|
462
|
-
if (!
|
|
461
|
+
const shown2 = resolveEditTarget(textNode);
|
|
462
|
+
if (!shown2) return false;
|
|
463
463
|
pendingHidden.delete(textNode);
|
|
464
|
-
if (
|
|
465
|
-
tagEncodedElement(
|
|
464
|
+
if (shown2.hasAttribute("data-prepr-encoded")) return false;
|
|
465
|
+
tagEncodedElement(shown2, info.decoded);
|
|
466
466
|
return true;
|
|
467
467
|
}
|
|
468
468
|
try {
|
|
@@ -1055,7 +1055,7 @@ var DEFAULT_STATE = {
|
|
|
1055
1055
|
};
|
|
1056
1056
|
function createToolbarStore(initial = {}) {
|
|
1057
1057
|
let state = { ...DEFAULT_STATE, ...initial };
|
|
1058
|
-
const
|
|
1058
|
+
const listeners2 = /* @__PURE__ */ new Set();
|
|
1059
1059
|
function get() {
|
|
1060
1060
|
return state;
|
|
1061
1061
|
}
|
|
@@ -1064,14 +1064,14 @@ function createToolbarStore(initial = {}) {
|
|
|
1064
1064
|
const hasChange = keys.some((key) => patch[key] !== state[key]);
|
|
1065
1065
|
if (!hasChange) return;
|
|
1066
1066
|
state = { ...state, ...patch };
|
|
1067
|
-
for (const listener of
|
|
1067
|
+
for (const listener of listeners2) {
|
|
1068
1068
|
listener(state);
|
|
1069
1069
|
}
|
|
1070
1070
|
}
|
|
1071
1071
|
function subscribe(fn) {
|
|
1072
|
-
|
|
1072
|
+
listeners2.add(fn);
|
|
1073
1073
|
return () => {
|
|
1074
|
-
|
|
1074
|
+
listeners2.delete(fn);
|
|
1075
1075
|
};
|
|
1076
1076
|
}
|
|
1077
1077
|
return { get, set, subscribe };
|
|
@@ -2316,204 +2316,42 @@ function isReactHydrated(text) {
|
|
|
2316
2316
|
return true;
|
|
2317
2317
|
}
|
|
2318
2318
|
|
|
2319
|
-
// src/
|
|
2320
|
-
|
|
2321
|
-
var PREPR_REFRESH_HEADER = "Prepr-Refresh";
|
|
2322
|
-
var REFRESH_MAX_PATHS = 5;
|
|
2323
|
-
var SAFE_PATH = /^\/(?![/\\])[\w\-./%]{0,200}$/;
|
|
2324
|
-
function safePath(path) {
|
|
2325
|
-
return SAFE_PATH.test(path) ? path : void 0;
|
|
2326
|
-
}
|
|
2327
|
-
function isFresh(at, freshFor, now = Date.now()) {
|
|
2328
|
-
const age = now - at;
|
|
2329
|
-
return at > 0 && age >= 0 && age < freshFor;
|
|
2330
|
-
}
|
|
2331
|
-
function cleanEntries(entries) {
|
|
2332
|
-
const out = [];
|
|
2333
|
-
for (const entry of entries) {
|
|
2334
|
-
if (out.length === REFRESH_MAX_PATHS) break;
|
|
2335
|
-
if (safePath(entry.path) && !out.some((e2) => e2.path === entry.path)) {
|
|
2336
|
-
out.push(entry);
|
|
2337
|
-
}
|
|
2338
|
-
}
|
|
2339
|
-
return out;
|
|
2340
|
-
}
|
|
2341
|
-
function parseRefresh(raw) {
|
|
2342
|
-
return cleanEntries(
|
|
2343
|
-
(raw ?? "").split("|").map((pair) => {
|
|
2344
|
-
const split = pair.lastIndexOf("~");
|
|
2345
|
-
const at = Number(split < 0 ? "" : pair.slice(split + 1));
|
|
2346
|
-
return {
|
|
2347
|
-
path: split < 0 ? pair : pair.slice(0, split),
|
|
2348
|
-
at: Number.isFinite(at) && at > 0 ? Math.floor(at) : 0
|
|
2349
|
-
};
|
|
2350
|
-
})
|
|
2351
|
-
);
|
|
2352
|
-
}
|
|
2353
|
-
|
|
2354
|
-
// src/core/refresh-scheduler.ts
|
|
2355
|
-
var VIEW_DELAYS_MS = [3e3, 1e4];
|
|
2356
|
-
var INTENT_MIN_AGE_MS = 2e3;
|
|
2357
|
-
var INTENT_EVENTS = ["pointerover", "focusin", "touchstart"];
|
|
2358
|
-
var LISTENER = { capture: true, passive: true };
|
|
2359
|
-
var COOKIE_PATTERN = new RegExp(`(?:^|; )${PREPR_REFRESH_COOKIE}=([^;]*)`);
|
|
2360
|
-
var UNSUPPORTED_KEY = "prepr_refresh_unsupported";
|
|
2361
|
-
function readEntries() {
|
|
2362
|
-
const match = document.cookie.match(COOKIE_PATTERN);
|
|
2363
|
-
try {
|
|
2364
|
-
return parseRefresh(match ? decodeURIComponent(match[1]) : void 0);
|
|
2365
|
-
} catch {
|
|
2366
|
-
return [];
|
|
2367
|
-
}
|
|
2368
|
-
}
|
|
2369
|
-
function unsupported() {
|
|
2370
|
-
try {
|
|
2371
|
-
return sessionStorage.getItem(UNSUPPORTED_KEY) === "1";
|
|
2372
|
-
} catch {
|
|
2373
|
-
return false;
|
|
2374
|
-
}
|
|
2375
|
-
}
|
|
2376
|
-
function createPreprRefreshScheduler(options = {}) {
|
|
2377
|
-
const freshFor = options.freshFor ?? 1e4;
|
|
2378
|
-
let timers = [];
|
|
2379
|
-
let inFlight = false;
|
|
2380
|
-
let stopped = unsupported();
|
|
2381
|
-
function refresh() {
|
|
2382
|
-
if (inFlight || stopped) return;
|
|
2383
|
-
const paths = readEntries().map((entry) => entry.path);
|
|
2384
|
-
if (paths.length === 0) return;
|
|
2385
|
-
inFlight = true;
|
|
2386
|
-
const controller = new AbortController();
|
|
2387
|
-
fetch(location.pathname, {
|
|
2388
|
-
headers: { [PREPR_REFRESH_HEADER]: paths.join("|") },
|
|
2389
|
-
cache: "no-store",
|
|
2390
|
-
credentials: "same-origin",
|
|
2391
|
-
signal: controller.signal
|
|
2392
|
-
}).then((response) => {
|
|
2393
|
-
if (response.status === 204) return;
|
|
2394
|
-
stopped = true;
|
|
2395
|
-
controller.abort();
|
|
2396
|
-
try {
|
|
2397
|
-
sessionStorage.setItem(UNSUPPORTED_KEY, "1");
|
|
2398
|
-
} catch {
|
|
2399
|
-
}
|
|
2400
|
-
}).catch(() => void 0).finally(() => {
|
|
2401
|
-
inFlight = false;
|
|
2402
|
-
});
|
|
2403
|
-
}
|
|
2404
|
-
function onIntent(event) {
|
|
2405
|
-
const anchor = event.target?.closest?.("a[href]");
|
|
2406
|
-
if (!(anchor instanceof HTMLAnchorElement)) return;
|
|
2407
|
-
let url;
|
|
2408
|
-
try {
|
|
2409
|
-
url = new URL(anchor.href, location.href);
|
|
2410
|
-
} catch {
|
|
2411
|
-
return;
|
|
2412
|
-
}
|
|
2413
|
-
if (url.origin !== location.origin) return;
|
|
2414
|
-
const entry = readEntries().find((e2) => e2.path === url.pathname);
|
|
2415
|
-
if (entry && !isFresh(entry.at, INTENT_MIN_AGE_MS)) refresh();
|
|
2416
|
-
}
|
|
2417
|
-
function onVisibility() {
|
|
2418
|
-
if (document.visibilityState === "visible" && readEntries().some((entry) => !isFresh(entry.at, freshFor))) {
|
|
2419
|
-
refresh();
|
|
2420
|
-
}
|
|
2421
|
-
}
|
|
2422
|
-
for (const type of INTENT_EVENTS) {
|
|
2423
|
-
document.addEventListener(type, onIntent, LISTENER);
|
|
2424
|
-
}
|
|
2425
|
-
document.addEventListener("visibilitychange", onVisibility, {
|
|
2426
|
-
passive: true
|
|
2427
|
-
});
|
|
2428
|
-
return {
|
|
2429
|
-
view() {
|
|
2430
|
-
timers.forEach(clearTimeout);
|
|
2431
|
-
timers = VIEW_DELAYS_MS.map((delay) => setTimeout(refresh, delay));
|
|
2432
|
-
},
|
|
2433
|
-
stop() {
|
|
2434
|
-
timers.forEach(clearTimeout);
|
|
2435
|
-
timers = [];
|
|
2436
|
-
for (const type of INTENT_EVENTS) {
|
|
2437
|
-
document.removeEventListener(type, onIntent, LISTENER);
|
|
2438
|
-
}
|
|
2439
|
-
document.removeEventListener("visibilitychange", onVisibility);
|
|
2440
|
-
}
|
|
2441
|
-
};
|
|
2442
|
-
}
|
|
2443
|
-
|
|
2444
|
-
// src/nextjs/ab-switch.ts
|
|
2445
|
-
function applyPreprAbBucket() {
|
|
2446
|
-
const match = document.cookie.match(/(?:^|; )prepr_ab_bucket=([AB])(?:;|$)/);
|
|
2447
|
-
const bucket = match ? match[1] : "A";
|
|
2319
|
+
// src/nextjs/decision-switch.ts
|
|
2320
|
+
function applyPreprDecisions(decision) {
|
|
2448
2321
|
const state = window;
|
|
2449
|
-
|
|
2450
|
-
state.
|
|
2451
|
-
const
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
if (
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
if (viewState.__preprDecisionsView === current) return;
|
|
2471
|
-
viewState.__preprDecisionsView = current;
|
|
2472
|
-
const match = document.cookie.match(/(?:^|; )prepr_decisions=([^;]*)/);
|
|
2473
|
-
let raw;
|
|
2474
|
-
try {
|
|
2475
|
-
raw = match ? decodeURIComponent(match[1]) : "";
|
|
2476
|
-
} catch {
|
|
2477
|
-
raw = "";
|
|
2478
|
-
}
|
|
2479
|
-
const state = window;
|
|
2480
|
-
if (state.__preprDecisions === raw) return;
|
|
2481
|
-
state.__preprDecisions = raw;
|
|
2482
|
-
const id = /^[\w-]+$/;
|
|
2483
|
-
let css = "";
|
|
2484
|
-
raw.split("~").forEach((pair) => {
|
|
2485
|
-
const at = pair.indexOf(":");
|
|
2486
|
-
const group = pair.slice(0, at);
|
|
2487
|
-
if (at < 1 || !id.test(group)) return;
|
|
2488
|
-
const selector = '[data-prepr-group="' + group + '"]';
|
|
2489
|
-
css += selector + "{display:none!important}";
|
|
2490
|
-
pair.slice(at + 1).split("|").forEach((variant) => {
|
|
2491
|
-
if (id.test(variant)) {
|
|
2492
|
-
css += selector + '[data-prepr-variant="' + variant + '"]{display:contents!important}';
|
|
2493
|
-
}
|
|
2322
|
+
const key = location.pathname + location.search;
|
|
2323
|
+
if (decision !== void 0) state.__preprDecision = { key, value: decision };
|
|
2324
|
+
const current = state.__preprDecision;
|
|
2325
|
+
if (!current || current.key !== key) return false;
|
|
2326
|
+
document.querySelectorAll("[data-prepr-decision]").forEach((marker) => {
|
|
2327
|
+
marker.setAttribute("data-prepr-decided", "");
|
|
2328
|
+
});
|
|
2329
|
+
const defaults = current.value === "*";
|
|
2330
|
+
const chosen = {};
|
|
2331
|
+
current.value.split("~").forEach((pair) => {
|
|
2332
|
+
const colon = pair.indexOf(":");
|
|
2333
|
+
if (colon > 0)
|
|
2334
|
+
chosen[pair.slice(0, colon)] = pair.slice(colon + 1).split("|");
|
|
2335
|
+
});
|
|
2336
|
+
document.querySelectorAll("[data-prepr-v]").forEach((element) => {
|
|
2337
|
+
const nested = element.hasAttribute("data-prepr-nested");
|
|
2338
|
+
const show = defaults ? element.hasAttribute("data-prepr-default") : (element.getAttribute("data-prepr-v") || "").split(" ").every((token) => {
|
|
2339
|
+
const colon = token.indexOf(":");
|
|
2340
|
+
const variant = token.slice(colon + 1);
|
|
2341
|
+
const variants = chosen[token.slice(0, colon)];
|
|
2342
|
+
return !!variants && (nested ? variants[0] === variant : variants.indexOf(variant) >= 0);
|
|
2494
2343
|
});
|
|
2344
|
+
if (show) element.setAttribute("data-prepr-show", "");
|
|
2345
|
+
else element.removeAttribute("data-prepr-show");
|
|
2495
2346
|
});
|
|
2496
|
-
|
|
2497
|
-
if (!state.__preprDecisionSheet) {
|
|
2498
|
-
const sheet = new CSSStyleSheet();
|
|
2499
|
-
document.adoptedStyleSheets = document.adoptedStyleSheets.concat(sheet);
|
|
2500
|
-
state.__preprDecisionSheet = sheet;
|
|
2501
|
-
}
|
|
2502
|
-
state.__preprDecisionSheet.replaceSync(css);
|
|
2503
|
-
} catch {
|
|
2504
|
-
if (!state.__preprDecisionSheet) {
|
|
2505
|
-
state.__preprDecisionSheet = document.createElement("style");
|
|
2506
|
-
document.head.appendChild(state.__preprDecisionSheet);
|
|
2507
|
-
}
|
|
2508
|
-
state.__preprDecisionSheet.textContent = css;
|
|
2509
|
-
}
|
|
2347
|
+
return true;
|
|
2510
2348
|
}
|
|
2511
2349
|
|
|
2512
2350
|
// src/react/components.ts
|
|
2513
2351
|
var import_react = require("react");
|
|
2514
2352
|
|
|
2515
2353
|
// src/version.ts
|
|
2516
|
-
var VERSION = "0.6.0-alpha.
|
|
2354
|
+
var VERSION = "0.6.0-alpha.7";
|
|
2517
2355
|
|
|
2518
2356
|
// src/core/pixel.ts
|
|
2519
2357
|
var PIXEL_SCRIPT_URL = "https://cdn.tracking.prepr.io/js/prepr.min.js";
|
|
@@ -2588,62 +2426,152 @@ function PreprToolbar({
|
|
|
2588
2426
|
}, []);
|
|
2589
2427
|
return null;
|
|
2590
2428
|
}
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2429
|
+
var DECIDE_HEADER = "Prepr-Decide";
|
|
2430
|
+
var DECIDE_TIMEOUT_MS = 6e3;
|
|
2431
|
+
function requestDecision(key) {
|
|
2432
|
+
const pending = { key, value: null };
|
|
2433
|
+
pending.value = fetch(key, {
|
|
2434
|
+
headers: { [DECIDE_HEADER]: "1" },
|
|
2435
|
+
cache: "no-store",
|
|
2436
|
+
credentials: "same-origin",
|
|
2437
|
+
signal: AbortSignal.timeout(DECIDE_TIMEOUT_MS)
|
|
2438
|
+
}).then((response) => response.ok ? response.text() : "*").catch(() => "*").then((value) => {
|
|
2439
|
+
pending.result = value;
|
|
2440
|
+
try {
|
|
2441
|
+
sessionStorage.setItem(
|
|
2442
|
+
"prepr_decision",
|
|
2443
|
+
JSON.stringify({ key, value, at: Date.now() })
|
|
2444
|
+
);
|
|
2445
|
+
} catch {
|
|
2446
|
+
}
|
|
2447
|
+
return value;
|
|
2594
2448
|
});
|
|
2595
|
-
return
|
|
2449
|
+
return pending;
|
|
2450
|
+
}
|
|
2451
|
+
var pressed = null;
|
|
2452
|
+
var replaying = null;
|
|
2453
|
+
var shown = /* @__PURE__ */ new Map();
|
|
2454
|
+
var historyStep = false;
|
|
2455
|
+
var onPopState = () => {
|
|
2456
|
+
historyStep = true;
|
|
2457
|
+
};
|
|
2458
|
+
function linkTarget(event) {
|
|
2459
|
+
const anchor = event.target?.closest?.("a[href]");
|
|
2460
|
+
if (!(anchor instanceof HTMLAnchorElement)) return null;
|
|
2461
|
+
if (anchor.target && anchor.target !== "_self" || anchor.hasAttribute("download")) {
|
|
2462
|
+
return null;
|
|
2463
|
+
}
|
|
2464
|
+
const url = new URL(anchor.href, location.href);
|
|
2465
|
+
const key = url.pathname + url.search;
|
|
2466
|
+
if (url.origin !== location.origin || key === location.pathname + location.search) {
|
|
2467
|
+
return null;
|
|
2468
|
+
}
|
|
2469
|
+
return { anchor, key };
|
|
2596
2470
|
}
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2471
|
+
function onPointerDown(event) {
|
|
2472
|
+
if (event.button !== 0) return;
|
|
2473
|
+
const target = linkTarget(event);
|
|
2474
|
+
if (!target || pressed?.key === target.key && pressed.result === void 0) {
|
|
2475
|
+
return;
|
|
2476
|
+
}
|
|
2477
|
+
pressed = requestDecision(target.key);
|
|
2478
|
+
}
|
|
2479
|
+
function onClick(event) {
|
|
2480
|
+
const target = linkTarget(event);
|
|
2481
|
+
if (!target) return;
|
|
2482
|
+
if (replaying === target.anchor) {
|
|
2483
|
+
replaying = null;
|
|
2484
|
+
return;
|
|
2485
|
+
}
|
|
2486
|
+
if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
|
|
2487
|
+
return;
|
|
2488
|
+
}
|
|
2489
|
+
const pending = pressed && pressed.key === target.key ? pressed : requestDecision(target.key);
|
|
2490
|
+
pressed = null;
|
|
2491
|
+
const record = (value) => {
|
|
2492
|
+
window.__preprDecision = { key: target.key, value };
|
|
2493
|
+
};
|
|
2494
|
+
if (pending.result !== void 0) {
|
|
2495
|
+
record(pending.result);
|
|
2496
|
+
return;
|
|
2497
|
+
}
|
|
2498
|
+
event.preventDefault();
|
|
2499
|
+
event.stopImmediatePropagation();
|
|
2500
|
+
void pending.value.then((value) => {
|
|
2501
|
+
record(value);
|
|
2502
|
+
replaying = target.anchor;
|
|
2503
|
+
target.anchor.click();
|
|
2611
2504
|
});
|
|
2505
|
+
}
|
|
2506
|
+
var listeners = 0;
|
|
2507
|
+
function useDecisionRequests() {
|
|
2612
2508
|
(0, import_react2.useEffect)(() => {
|
|
2613
|
-
if (
|
|
2614
|
-
|
|
2615
|
-
|
|
2509
|
+
if (listeners++ === 0) {
|
|
2510
|
+
window.addEventListener("pointerdown", onPointerDown, true);
|
|
2511
|
+
window.addEventListener("click", onClick, true);
|
|
2512
|
+
window.addEventListener("popstate", onPopState);
|
|
2513
|
+
}
|
|
2616
2514
|
return () => {
|
|
2617
|
-
|
|
2618
|
-
|
|
2515
|
+
if (--listeners === 0) {
|
|
2516
|
+
window.removeEventListener("pointerdown", onPointerDown, true);
|
|
2517
|
+
window.removeEventListener("click", onClick, true);
|
|
2518
|
+
window.removeEventListener("popstate", onPopState);
|
|
2519
|
+
}
|
|
2619
2520
|
};
|
|
2620
|
-
}, [
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2521
|
+
}, []);
|
|
2522
|
+
}
|
|
2523
|
+
function PreprPersonalizationSwitch() {
|
|
2524
|
+
useDecisionRequests();
|
|
2525
|
+
return null;
|
|
2526
|
+
}
|
|
2527
|
+
function PreprDecisionApplier() {
|
|
2528
|
+
useDecisionRequests();
|
|
2529
|
+
(0, import_react2.useLayoutEffect)(() => {
|
|
2530
|
+
const key = location.pathname + location.search;
|
|
2531
|
+
const remember = () => {
|
|
2532
|
+
const state = window.__preprDecision;
|
|
2533
|
+
if (state) shown.set(key, state.value);
|
|
2534
|
+
};
|
|
2535
|
+
const previous = historyStep ? shown.get(key) : void 0;
|
|
2536
|
+
historyStep = false;
|
|
2537
|
+
if (applyPreprDecisions(previous)) {
|
|
2538
|
+
remember();
|
|
2539
|
+
return;
|
|
2540
|
+
}
|
|
2541
|
+
let live = true;
|
|
2542
|
+
const started = window.__preprPending;
|
|
2543
|
+
const value = started?.key === key ? started.value : requestDecision(key).value;
|
|
2544
|
+
void value.then((value2) => {
|
|
2545
|
+
if (live && location.pathname + location.search === key) {
|
|
2546
|
+
applyPreprDecisions(value2);
|
|
2547
|
+
remember();
|
|
2548
|
+
}
|
|
2549
|
+
});
|
|
2550
|
+
return () => {
|
|
2551
|
+
live = false;
|
|
2552
|
+
};
|
|
2553
|
+
});
|
|
2634
2554
|
return null;
|
|
2635
2555
|
}
|
|
2636
2556
|
var VARIANT_KEY_ATTRIBUTE = "data-prepr-variant-key";
|
|
2637
2557
|
function PreprVariantTracking({
|
|
2638
2558
|
variantKeys,
|
|
2639
|
-
ab,
|
|
2640
2559
|
children
|
|
2641
2560
|
}) {
|
|
2642
2561
|
const ref = (0, import_react2.useRef)(null);
|
|
2643
2562
|
const keys = variantKeys.join(" ");
|
|
2644
2563
|
(0, import_react2.useLayoutEffect)(() => {
|
|
2645
2564
|
let tagged = [];
|
|
2646
|
-
const
|
|
2565
|
+
const wrapper = ref.current?.closest("[data-prepr-v]");
|
|
2566
|
+
const shown2 = () => !wrapper || wrapper.hasAttribute("data-prepr-show");
|
|
2567
|
+
const untag = () => {
|
|
2568
|
+
for (const [element] of tagged)
|
|
2569
|
+
element.removeAttribute(VARIANT_KEY_ATTRIBUTE);
|
|
2570
|
+
tagged = [];
|
|
2571
|
+
};
|
|
2572
|
+
const tag = () => {
|
|
2573
|
+
if (!shown2()) return untag();
|
|
2574
|
+
if (tagged.length > 0) return;
|
|
2647
2575
|
const elements = [...ref.current?.children ?? []];
|
|
2648
2576
|
const list = keys.split(" ");
|
|
2649
2577
|
const pairs = elements.length === list.length ? elements.map((element, i2) => [element, list[i2]]) : elements.slice(0, 1).map((element) => [element, list[0]]);
|
|
@@ -2652,23 +2580,28 @@ function PreprVariantTracking({
|
|
|
2652
2580
|
element.setAttribute(VARIANT_KEY_ATTRIBUTE, key);
|
|
2653
2581
|
return true;
|
|
2654
2582
|
});
|
|
2583
|
+
};
|
|
2584
|
+
const timer = setTimeout(tag);
|
|
2585
|
+
const observer = wrapper && new MutationObserver(tag);
|
|
2586
|
+
observer?.observe(wrapper, {
|
|
2587
|
+
attributes: true,
|
|
2588
|
+
attributeFilter: ["data-prepr-show"]
|
|
2655
2589
|
});
|
|
2656
2590
|
return () => {
|
|
2657
2591
|
clearTimeout(timer);
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
}
|
|
2592
|
+
observer?.disconnect();
|
|
2593
|
+
untag();
|
|
2661
2594
|
};
|
|
2662
2595
|
}, [keys]);
|
|
2663
2596
|
return (0, import_react2.createElement)(
|
|
2664
2597
|
"div",
|
|
2665
|
-
|
|
2598
|
+
{ ref, style: { display: "contents" } },
|
|
2666
2599
|
children
|
|
2667
2600
|
);
|
|
2668
2601
|
}
|
|
2669
2602
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2670
2603
|
0 && (module.exports = {
|
|
2671
|
-
|
|
2604
|
+
PreprDecisionApplier,
|
|
2672
2605
|
PreprPersonalizationSwitch,
|
|
2673
2606
|
PreprToolbar,
|
|
2674
2607
|
PreprTrackingPixel,
|