@preprio/toolkit 0.5.0-rc.5 → 0.5.0-rc.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 +133 -26
- package/dist/astro/index.cjs +126 -30
- package/dist/astro/index.js +130 -30
- package/dist/{chunk-3X55JL52.js → chunk-HVS5QLWG.js} +1 -1
- package/dist/{chunk-TG6N3C22.js → chunk-IPMB32AZ.js} +1 -1
- package/dist/{chunk-CMUFTCG3.js → chunk-JUXP5KRX.js} +1 -1
- package/dist/{chunk-74KY5EAM.js → chunk-KD3GK6TO.js} +2 -0
- package/dist/{chunk-SBLZANL5.js → chunk-SUAFASBB.js} +11 -3
- package/dist/codegen/index.cjs +82 -0
- package/dist/codegen/index.d.cts +70 -0
- package/dist/codegen/index.d.ts +70 -0
- package/dist/codegen/index.js +64 -0
- package/dist/index.cjs +133 -28
- package/dist/index.d.cts +14 -2
- package/dist/index.d.ts +14 -2
- package/dist/index.js +108 -6
- package/dist/{live-preview-H4643QYF.js → live-preview-DLXGXRE5.js} +2 -2
- package/dist/nextjs/components.cjs +11 -3
- package/dist/nextjs/components.js +2 -2
- package/dist/nextjs/index.cjs +124 -28
- package/dist/nextjs/index.js +128 -28
- package/dist/nextjs/live-action.js +3 -3
- package/dist/nextjs/live.js +1 -1
- package/dist/nuxt/chunk-BWPGO25E.js +340 -0
- package/dist/nuxt/index.cjs +1 -1
- package/dist/nuxt/index.js +1 -1
- package/dist/nuxt/{live-preview-O2ZTJNW4.js → live-preview-2RCU35W5.js} +6 -337
- package/dist/nuxt/live.cjs +1007 -911
- package/dist/nuxt/live.js +109 -5
- package/dist/react/components.cjs +11 -3
- package/dist/react/components.js +11 -3
- package/dist/sveltekit/chunk-BWPGO25E.js +340 -0
- package/dist/sveltekit/index.cjs +1 -1
- package/dist/sveltekit/index.js +1 -1
- package/dist/sveltekit/{live-preview-O2ZTJNW4.js → live-preview-2RCU35W5.js} +6 -337
- package/dist/sveltekit/live.cjs +1008 -909
- package/dist/sveltekit/live.js +118 -11
- package/package.json +11 -1
package/dist/index.cjs
CHANGED
|
@@ -23,6 +23,7 @@ __export(src_exports, {
|
|
|
23
23
|
PreprError: () => PreprError,
|
|
24
24
|
PreprToolbarElement: () => PreprToolbarElement,
|
|
25
25
|
VERSION: () => VERSION,
|
|
26
|
+
annotateEditLinks: () => annotateEditLinks,
|
|
26
27
|
createPreprPreview: () => createPreprPreview,
|
|
27
28
|
createToolbarStore: () => createToolbarStore,
|
|
28
29
|
definePreprToolbar: () => definePreprToolbar,
|
|
@@ -49,7 +50,7 @@ __export(src_exports, {
|
|
|
49
50
|
module.exports = __toCommonJS(src_exports);
|
|
50
51
|
|
|
51
52
|
// src/version.ts
|
|
52
|
-
var VERSION = "0.5.0-rc.
|
|
53
|
+
var VERSION = "0.5.0-rc.7";
|
|
53
54
|
|
|
54
55
|
// src/core/features.ts
|
|
55
56
|
function isEnabled(config) {
|
|
@@ -570,6 +571,7 @@ function decodeStega(str) {
|
|
|
570
571
|
|
|
571
572
|
// src/core/stega/dom.ts
|
|
572
573
|
var IGNORED_ANCESTORS = "script, style, noscript";
|
|
574
|
+
var AUTO_ENTRY_ATTR = "data-prepr-entry-auto";
|
|
573
575
|
function isIgnoredTextNode(node) {
|
|
574
576
|
if (node.parentElement?.closest(IGNORED_ANCESTORS)) return true;
|
|
575
577
|
return !node.textContent?.trim();
|
|
@@ -603,7 +605,9 @@ function parseEditHref(href) {
|
|
|
603
605
|
return {
|
|
604
606
|
id: url.pathname.split("/").pop() || void 0,
|
|
605
607
|
field: url.searchParams.get("field") || void 0,
|
|
606
|
-
locale: url.searchParams.get("locale") || void 0
|
|
608
|
+
locale: url.searchParams.get("locale") || void 0,
|
|
609
|
+
// Added by the toolkit's `annotateEditLinks`, not by Prepr.
|
|
610
|
+
entry: url.searchParams.get("entry") || void 0
|
|
607
611
|
};
|
|
608
612
|
} catch {
|
|
609
613
|
return {};
|
|
@@ -620,11 +624,16 @@ function tagEncodedElement(element, decoded) {
|
|
|
620
624
|
element.setAttribute("data-prepr-encoded", "");
|
|
621
625
|
element.setAttribute("data-prepr-href", decoded.href);
|
|
622
626
|
element.setAttribute("data-prepr-origin", decoded.origin);
|
|
623
|
-
const { id, field, locale } = parseEditHref(decoded.href);
|
|
627
|
+
const { id, field, locale, entry } = parseEditHref(decoded.href);
|
|
624
628
|
setOrRemove(element, "data-prepr-id", id);
|
|
625
629
|
const fieldHint = element.getAttribute("data-prepr-edit-target")?.trim() || void 0;
|
|
626
630
|
setOrRemove(element, "data-prepr-field", field ?? fieldHint);
|
|
627
631
|
setOrRemove(element, "data-prepr-locale", locale);
|
|
632
|
+
const siteEntry = element.hasAttribute("data-prepr-entry-id") && !element.hasAttribute(AUTO_ENTRY_ATTR);
|
|
633
|
+
if (!siteEntry) {
|
|
634
|
+
setOrRemove(element, "data-prepr-entry-id", entry);
|
|
635
|
+
setOrRemove(element, AUTO_ENTRY_ATTR, entry && "true");
|
|
636
|
+
}
|
|
628
637
|
}
|
|
629
638
|
function readEditPayload(element) {
|
|
630
639
|
return {
|
|
@@ -3593,14 +3602,14 @@ function indexSnapshot(data) {
|
|
|
3593
3602
|
const index = /* @__PURE__ */ new Map();
|
|
3594
3603
|
const visited = /* @__PURE__ */ new WeakSet();
|
|
3595
3604
|
const path = [];
|
|
3596
|
-
function
|
|
3605
|
+
function walk2(node) {
|
|
3597
3606
|
if (node === null || typeof node !== "object") return;
|
|
3598
3607
|
if (visited.has(node)) return;
|
|
3599
3608
|
visited.add(node);
|
|
3600
3609
|
if (Array.isArray(node)) {
|
|
3601
3610
|
for (let i2 = 0; i2 < node.length; i2++) {
|
|
3602
3611
|
path.push(i2);
|
|
3603
|
-
|
|
3612
|
+
walk2(node[i2]);
|
|
3604
3613
|
path.pop();
|
|
3605
3614
|
}
|
|
3606
3615
|
return;
|
|
@@ -3618,11 +3627,11 @@ function indexSnapshot(data) {
|
|
|
3618
3627
|
for (const key in record) {
|
|
3619
3628
|
if (!Object.prototype.hasOwnProperty.call(record, key)) continue;
|
|
3620
3629
|
path.push(key);
|
|
3621
|
-
|
|
3630
|
+
walk2(record[key]);
|
|
3622
3631
|
path.pop();
|
|
3623
3632
|
}
|
|
3624
3633
|
}
|
|
3625
|
-
|
|
3634
|
+
walk2(data);
|
|
3626
3635
|
return index;
|
|
3627
3636
|
}
|
|
3628
3637
|
|
|
@@ -4161,12 +4170,12 @@ function resolveFields(selections, typename, doc, options) {
|
|
|
4161
4170
|
}
|
|
4162
4171
|
};
|
|
4163
4172
|
const applies = (on, list) => conditionMatches(on, typename) || typename !== void 0 && typeConditions(list, doc).includes(typename);
|
|
4164
|
-
const
|
|
4173
|
+
const walk2 = (list, matched) => {
|
|
4165
4174
|
for (const s2 of list) {
|
|
4166
4175
|
if (s2.kind === "field") {
|
|
4167
4176
|
add(matched ? exact : loose, s2);
|
|
4168
4177
|
} else if (s2.kind === "inline") {
|
|
4169
|
-
|
|
4178
|
+
walk2(s2.selections, matched && applies(s2.on, s2.selections));
|
|
4170
4179
|
} else {
|
|
4171
4180
|
const fragment = doc.fragments.get(s2.name);
|
|
4172
4181
|
if (!fragment) continue;
|
|
@@ -4174,11 +4183,11 @@ function resolveFields(selections, typename, doc, options) {
|
|
|
4174
4183
|
if (walkedMatched.has(fragment)) continue;
|
|
4175
4184
|
if (!asMatched && walkedLoose.has(fragment)) continue;
|
|
4176
4185
|
(asMatched ? walkedMatched : walkedLoose).add(fragment);
|
|
4177
|
-
|
|
4186
|
+
walk2(fragment.selections, asMatched);
|
|
4178
4187
|
}
|
|
4179
4188
|
}
|
|
4180
4189
|
};
|
|
4181
|
-
|
|
4190
|
+
walk2(selections, true);
|
|
4182
4191
|
if (!options.strict) {
|
|
4183
4192
|
for (const [key, field] of loose) {
|
|
4184
4193
|
if (!exact.has(key)) exact.set(key, field);
|
|
@@ -4195,21 +4204,21 @@ function typeConditions(selections, doc) {
|
|
|
4195
4204
|
if (hit) return hit;
|
|
4196
4205
|
const names = /* @__PURE__ */ new Set();
|
|
4197
4206
|
const seen = /* @__PURE__ */ new Set();
|
|
4198
|
-
const
|
|
4207
|
+
const walk2 = (list) => {
|
|
4199
4208
|
for (const s2 of list) {
|
|
4200
4209
|
if (s2.kind === "inline") {
|
|
4201
4210
|
if (s2.on) names.add(s2.on);
|
|
4202
|
-
|
|
4211
|
+
walk2(s2.selections);
|
|
4203
4212
|
} else if (s2.kind === "spread") {
|
|
4204
4213
|
const fragment = doc.fragments.get(s2.name);
|
|
4205
4214
|
if (!fragment || seen.has(fragment)) continue;
|
|
4206
4215
|
seen.add(fragment);
|
|
4207
4216
|
names.add(fragment.on);
|
|
4208
|
-
|
|
4217
|
+
walk2(fragment.selections);
|
|
4209
4218
|
}
|
|
4210
4219
|
}
|
|
4211
4220
|
};
|
|
4212
|
-
|
|
4221
|
+
walk2(selections);
|
|
4213
4222
|
const conditions = [...names];
|
|
4214
4223
|
conditionsCache.set(selections, conditions);
|
|
4215
4224
|
return conditions;
|
|
@@ -4504,7 +4513,7 @@ function resolveTargets(root, doc, ownerPath, segments) {
|
|
|
4504
4513
|
let current = root;
|
|
4505
4514
|
const out = [];
|
|
4506
4515
|
const plain = /* @__PURE__ */ new Set();
|
|
4507
|
-
const
|
|
4516
|
+
const walk2 = (node, sel, i2, path) => {
|
|
4508
4517
|
if (i2 === segments.length) {
|
|
4509
4518
|
out.push(path);
|
|
4510
4519
|
return;
|
|
@@ -4514,10 +4523,10 @@ function resolveTargets(root, doc, ownerPath, segments) {
|
|
|
4514
4523
|
if (INDEX_SEGMENT3.test(segment)) {
|
|
4515
4524
|
const position = Number(segment);
|
|
4516
4525
|
if (position < node.length) {
|
|
4517
|
-
|
|
4526
|
+
walk2(node[position], sel, i2 + 1, [...path, position]);
|
|
4518
4527
|
}
|
|
4519
4528
|
} else if (segment === "items") {
|
|
4520
|
-
|
|
4529
|
+
walk2(node, sel, i2 + 1, path);
|
|
4521
4530
|
}
|
|
4522
4531
|
return;
|
|
4523
4532
|
}
|
|
@@ -4550,11 +4559,11 @@ function resolveTargets(root, doc, ownerPath, segments) {
|
|
|
4550
4559
|
current = writeAtPath(current, fieldPath, value);
|
|
4551
4560
|
}
|
|
4552
4561
|
}
|
|
4553
|
-
|
|
4562
|
+
walk2(value, field.selections, i2 + 1, fieldPath);
|
|
4554
4563
|
}
|
|
4555
|
-
if (!matched && segment === "items")
|
|
4564
|
+
if (!matched && segment === "items") walk2(node, sel, i2 + 1, path);
|
|
4556
4565
|
};
|
|
4557
|
-
|
|
4566
|
+
walk2(owner, selections, 0, ownerPath);
|
|
4558
4567
|
return { root: current, targets: out, plain };
|
|
4559
4568
|
}
|
|
4560
4569
|
var NON_ALPHANUMERIC = /[^a-z0-9]/gi;
|
|
@@ -4677,11 +4686,11 @@ function listKeysIn(result) {
|
|
|
4677
4686
|
if (!byType) {
|
|
4678
4687
|
byType = /* @__PURE__ */ new Map();
|
|
4679
4688
|
const seen = /* @__PURE__ */ new WeakSet();
|
|
4680
|
-
const
|
|
4689
|
+
const walk2 = (node) => {
|
|
4681
4690
|
if (node === null || typeof node !== "object" || seen.has(node)) return;
|
|
4682
4691
|
seen.add(node);
|
|
4683
4692
|
if (Array.isArray(node)) {
|
|
4684
|
-
node.forEach(
|
|
4693
|
+
node.forEach(walk2);
|
|
4685
4694
|
return;
|
|
4686
4695
|
}
|
|
4687
4696
|
const record = node;
|
|
@@ -4692,10 +4701,10 @@ function listKeysIn(result) {
|
|
|
4692
4701
|
if (!keys) byType.set(type, keys = /* @__PURE__ */ new Set());
|
|
4693
4702
|
keys.add(key);
|
|
4694
4703
|
}
|
|
4695
|
-
|
|
4704
|
+
walk2(value);
|
|
4696
4705
|
}
|
|
4697
4706
|
};
|
|
4698
|
-
|
|
4707
|
+
walk2(result);
|
|
4699
4708
|
listKeysCache.set(result, byType);
|
|
4700
4709
|
}
|
|
4701
4710
|
return byType.get(typename) ?? NO_KEYS;
|
|
@@ -4737,7 +4746,7 @@ function findEditLink(root) {
|
|
|
4737
4746
|
if (linkCache.has(root)) return linkCache.get(root) ?? null;
|
|
4738
4747
|
let found = null;
|
|
4739
4748
|
const seen = /* @__PURE__ */ new WeakSet();
|
|
4740
|
-
const
|
|
4749
|
+
const walk2 = (node) => {
|
|
4741
4750
|
if (found) return;
|
|
4742
4751
|
if (typeof node === "string") {
|
|
4743
4752
|
if (!(0, import_stega6.vercelStegaSplit)(node).encoded) return;
|
|
@@ -4752,13 +4761,108 @@ function findEditLink(root) {
|
|
|
4752
4761
|
}
|
|
4753
4762
|
if (node === null || typeof node !== "object" || seen.has(node)) return;
|
|
4754
4763
|
seen.add(node);
|
|
4755
|
-
for (const value of Object.values(node))
|
|
4764
|
+
for (const value of Object.values(node)) walk2(value);
|
|
4756
4765
|
};
|
|
4757
|
-
|
|
4766
|
+
walk2(root);
|
|
4758
4767
|
linkCache.set(root, found);
|
|
4759
4768
|
return found;
|
|
4760
4769
|
}
|
|
4761
4770
|
|
|
4771
|
+
// src/core/live-preview/edit-links.ts
|
|
4772
|
+
var import_stega7 = require("@vercel/stega");
|
|
4773
|
+
var ENTRY_PARAM = "entry";
|
|
4774
|
+
var TOP_LEVEL_ENTRY = /^[A-Za-z0-9_]+\.\d+$/;
|
|
4775
|
+
function entryIdOf(element) {
|
|
4776
|
+
if (!isRecord(element)) return void 0;
|
|
4777
|
+
if (typeof element._id === "string") return element._id;
|
|
4778
|
+
if (element.__typename !== "Assets" || !Array.isArray(element.items)) {
|
|
4779
|
+
return void 0;
|
|
4780
|
+
}
|
|
4781
|
+
const first = element.items[0];
|
|
4782
|
+
return isRecord(first) && typeof first._id === "string" ? first._id : void 0;
|
|
4783
|
+
}
|
|
4784
|
+
function isRecord(value) {
|
|
4785
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4786
|
+
}
|
|
4787
|
+
function annotate(value, ctx) {
|
|
4788
|
+
if (!ctx.entryId) return value;
|
|
4789
|
+
const { cleaned, encoded } = (0, import_stega7.vercelStegaSplit)(value);
|
|
4790
|
+
if (!encoded) return value;
|
|
4791
|
+
let payload;
|
|
4792
|
+
try {
|
|
4793
|
+
payload = (0, import_stega7.vercelStegaDecode)(encoded);
|
|
4794
|
+
} catch {
|
|
4795
|
+
return value;
|
|
4796
|
+
}
|
|
4797
|
+
if (typeof payload?.href !== "string") return value;
|
|
4798
|
+
let url;
|
|
4799
|
+
try {
|
|
4800
|
+
url = new URL(payload.href);
|
|
4801
|
+
} catch {
|
|
4802
|
+
return value;
|
|
4803
|
+
}
|
|
4804
|
+
if (url.searchParams.has(ENTRY_PARAM)) return value;
|
|
4805
|
+
url.searchParams.set(ENTRY_PARAM, ctx.entryId);
|
|
4806
|
+
const itemId = decodeURIComponent(url.pathname.split("/").pop() ?? "");
|
|
4807
|
+
if (!url.searchParams.has("field") && ctx.entryField && TOP_LEVEL_ENTRY.test(ctx.entryField) && itemId === ctx.entryOwnerId) {
|
|
4808
|
+
url.searchParams.set("field", ctx.entryField);
|
|
4809
|
+
}
|
|
4810
|
+
return (0, import_stega7.vercelStegaCombine)(
|
|
4811
|
+
cleaned,
|
|
4812
|
+
{ ...payload, href: url.toString() },
|
|
4813
|
+
false
|
|
4814
|
+
);
|
|
4815
|
+
}
|
|
4816
|
+
function walk(value, selections, ctx) {
|
|
4817
|
+
if (typeof value === "string") return annotate(value, ctx);
|
|
4818
|
+
if (Array.isArray(value)) {
|
|
4819
|
+
let changed2 = false;
|
|
4820
|
+
const next2 = value.map((element, index) => {
|
|
4821
|
+
const path = [...ctx.path, String(index)];
|
|
4822
|
+
const entryId = ctx.inAssets ? void 0 : entryIdOf(element);
|
|
4823
|
+
const entry = entryId ? {
|
|
4824
|
+
entryId,
|
|
4825
|
+
entryField: ctx.ownerId ? path.join(".") : void 0,
|
|
4826
|
+
entryOwnerId: ctx.ownerId,
|
|
4827
|
+
inAssets: isRecord(element) && element._id === void 0
|
|
4828
|
+
} : {};
|
|
4829
|
+
const out = walk(element, selections, { ...ctx, ...entry, path });
|
|
4830
|
+
if (out !== element) changed2 = true;
|
|
4831
|
+
return out;
|
|
4832
|
+
});
|
|
4833
|
+
return changed2 ? next2 : value;
|
|
4834
|
+
}
|
|
4835
|
+
if (!isRecord(value)) return value;
|
|
4836
|
+
const id = typeof value._id === "string" ? value._id : void 0;
|
|
4837
|
+
const typename = typeof value.__typename === "string" ? value.__typename : void 0;
|
|
4838
|
+
const fields = ctx.doc && selections ? collectFields(selections, typename, ctx.doc) : null;
|
|
4839
|
+
let changed = false;
|
|
4840
|
+
const next = {};
|
|
4841
|
+
for (const [key, child] of Object.entries(value)) {
|
|
4842
|
+
const field = fields?.get(key);
|
|
4843
|
+
const name = field?.name ?? key;
|
|
4844
|
+
const out = walk(child, field?.selections ?? null, {
|
|
4845
|
+
...ctx,
|
|
4846
|
+
ownerId: id ?? ctx.ownerId,
|
|
4847
|
+
path: id ? [name] : [...ctx.path, name]
|
|
4848
|
+
});
|
|
4849
|
+
if (out !== child) changed = true;
|
|
4850
|
+
next[key] = out;
|
|
4851
|
+
}
|
|
4852
|
+
return changed ? next : value;
|
|
4853
|
+
}
|
|
4854
|
+
function annotateEditLinks(result, query, operationName) {
|
|
4855
|
+
let doc = null;
|
|
4856
|
+
if (query !== void 0) {
|
|
4857
|
+
try {
|
|
4858
|
+
doc = readQueryDocument(query, operationName);
|
|
4859
|
+
} catch {
|
|
4860
|
+
doc = null;
|
|
4861
|
+
}
|
|
4862
|
+
}
|
|
4863
|
+
return walk(result, doc?.operation ?? null, { doc, path: [] });
|
|
4864
|
+
}
|
|
4865
|
+
|
|
4762
4866
|
// src/core/live-preview/bridge-events.ts
|
|
4763
4867
|
var debug12 = createScopedLogger("live-preview:bridge");
|
|
4764
4868
|
function createLiveBridge(store, options = {}) {
|
|
@@ -5530,6 +5634,7 @@ function setTrackingParam(key, value) {
|
|
|
5530
5634
|
PreprError,
|
|
5531
5635
|
PreprToolbarElement,
|
|
5532
5636
|
VERSION,
|
|
5637
|
+
annotateEditLinks,
|
|
5533
5638
|
createPreprPreview,
|
|
5534
5639
|
createToolbarStore,
|
|
5535
5640
|
definePreprToolbar,
|
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
|
+
declare const VERSION = "0.5.0-rc.7";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Resolve a `PreprFeatures` bag to plain booleans, defaulting every omitted key
|
|
@@ -355,6 +355,18 @@ declare function parsePatchLog(raw: unknown): LivePatch[];
|
|
|
355
355
|
*/
|
|
356
356
|
declare function normalizeQuery<T>(query: QueryInput, result: T, options?: NormalizeQueryOptions): T;
|
|
357
357
|
|
|
358
|
+
/**
|
|
359
|
+
* Adds the list entry each piece of text belongs to (a dynamic content
|
|
360
|
+
* entry, a repeated component) to its hidden edit link, so the visual editor
|
|
361
|
+
* can find the entry by id without `data-prepr-entry-id` on the page. A
|
|
362
|
+
* `Text` entry's link, which names no field, also gets the entry's field
|
|
363
|
+
* path, so `data-prepr-edit-target` is not needed to name it.
|
|
364
|
+
*
|
|
365
|
+
* Needs `_id` on the entries. Returns the result itself when nothing
|
|
366
|
+
* changed. Pass the query to name fields by their API name under aliases.
|
|
367
|
+
*/
|
|
368
|
+
declare function annotateEditLinks<T>(result: T, query?: QueryInput, operationName?: string): T;
|
|
369
|
+
|
|
358
370
|
interface HtmlLivePreviewOptions {
|
|
359
371
|
/**
|
|
360
372
|
* Replace the `*.prepr.io` editor-origin wildcard with an exact list, as
|
|
@@ -476,4 +488,4 @@ interface PreprMiddlewareOptions {
|
|
|
476
488
|
*/
|
|
477
489
|
declare function processPreprRequest(request: Request, opts?: PreprMiddlewareOptions): PreprMiddlewareResult;
|
|
478
490
|
|
|
479
|
-
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, createPreprPreview, createToolbarStore, definePreprToolbar, extractAccessToken, getActiveSegmentFromHeaders, getActiveVariantFromHeaders, getPreprEnvironmentSegments, getPreprHeadersFromHeaders, getPreprUUIDFromHeaders, getToolbarPropsFromHeaders, normalizeQuery, parsePatchLog, previewAttrs, processPreprRequest, readLiveLogFromRequest, resolveFeatures, startHtmlLivePreview, stegaClean, validatePreprToken };
|
|
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 };
|
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
|
+
declare const VERSION = "0.5.0-rc.7";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Resolve a `PreprFeatures` bag to plain booleans, defaulting every omitted key
|
|
@@ -355,6 +355,18 @@ declare function parsePatchLog(raw: unknown): LivePatch[];
|
|
|
355
355
|
*/
|
|
356
356
|
declare function normalizeQuery<T>(query: QueryInput, result: T, options?: NormalizeQueryOptions): T;
|
|
357
357
|
|
|
358
|
+
/**
|
|
359
|
+
* Adds the list entry each piece of text belongs to (a dynamic content
|
|
360
|
+
* entry, a repeated component) to its hidden edit link, so the visual editor
|
|
361
|
+
* can find the entry by id without `data-prepr-entry-id` on the page. A
|
|
362
|
+
* `Text` entry's link, which names no field, also gets the entry's field
|
|
363
|
+
* path, so `data-prepr-edit-target` is not needed to name it.
|
|
364
|
+
*
|
|
365
|
+
* Needs `_id` on the entries. Returns the result itself when nothing
|
|
366
|
+
* changed. Pass the query to name fields by their API name under aliases.
|
|
367
|
+
*/
|
|
368
|
+
declare function annotateEditLinks<T>(result: T, query?: QueryInput, operationName?: string): T;
|
|
369
|
+
|
|
358
370
|
interface HtmlLivePreviewOptions {
|
|
359
371
|
/**
|
|
360
372
|
* Replace the `*.prepr.io` editor-origin wildcard with an exact list, as
|
|
@@ -476,4 +488,4 @@ interface PreprMiddlewareOptions {
|
|
|
476
488
|
*/
|
|
477
489
|
declare function processPreprRequest(request: Request, opts?: PreprMiddlewareOptions): PreprMiddlewareResult;
|
|
478
490
|
|
|
479
|
-
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, createPreprPreview, createToolbarStore, definePreprToolbar, extractAccessToken, getActiveSegmentFromHeaders, getActiveVariantFromHeaders, getPreprEnvironmentSegments, getPreprHeadersFromHeaders, getPreprUUIDFromHeaders, getToolbarPropsFromHeaders, normalizeQuery, parsePatchLog, previewAttrs, processPreprRequest, readLiveLogFromRequest, resolveFeatures, startHtmlLivePreview, stegaClean, validatePreprToken };
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
setTrackingParam,
|
|
18
18
|
stegaClean,
|
|
19
19
|
trackEvent
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-SUAFASBB.js";
|
|
21
21
|
import {
|
|
22
22
|
PreprError,
|
|
23
23
|
extractAccessToken,
|
|
@@ -28,20 +28,22 @@ import {
|
|
|
28
28
|
getPreprUUIDFromHeaders,
|
|
29
29
|
getToolbarPropsFromHeaders,
|
|
30
30
|
validatePreprToken
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-HVS5QLWG.js";
|
|
32
32
|
import {
|
|
33
33
|
VERSION,
|
|
34
34
|
resolveFeatures
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-JUXP5KRX.js";
|
|
36
36
|
import {
|
|
37
37
|
createLiveBridge,
|
|
38
38
|
createLiveStore
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-IPMB32AZ.js";
|
|
40
40
|
import "./chunk-URXSDJOU.js";
|
|
41
41
|
import {
|
|
42
|
+
collectFields,
|
|
42
43
|
normalizeQuery,
|
|
43
|
-
parsePatchLog
|
|
44
|
-
|
|
44
|
+
parsePatchLog,
|
|
45
|
+
readQueryDocument
|
|
46
|
+
} from "./chunk-KD3GK6TO.js";
|
|
45
47
|
import {
|
|
46
48
|
createScopedLogger
|
|
47
49
|
} from "./chunk-S3VT4UWM.js";
|
|
@@ -59,6 +61,105 @@ function previewAttrs(target, options) {
|
|
|
59
61
|
return attrs;
|
|
60
62
|
}
|
|
61
63
|
|
|
64
|
+
// src/core/live-preview/edit-links.ts
|
|
65
|
+
import {
|
|
66
|
+
vercelStegaCombine,
|
|
67
|
+
vercelStegaDecode,
|
|
68
|
+
vercelStegaSplit
|
|
69
|
+
} from "@vercel/stega";
|
|
70
|
+
var ENTRY_PARAM = "entry";
|
|
71
|
+
var TOP_LEVEL_ENTRY = /^[A-Za-z0-9_]+\.\d+$/;
|
|
72
|
+
function entryIdOf(element) {
|
|
73
|
+
if (!isRecord(element)) return void 0;
|
|
74
|
+
if (typeof element._id === "string") return element._id;
|
|
75
|
+
if (element.__typename !== "Assets" || !Array.isArray(element.items)) {
|
|
76
|
+
return void 0;
|
|
77
|
+
}
|
|
78
|
+
const first = element.items[0];
|
|
79
|
+
return isRecord(first) && typeof first._id === "string" ? first._id : void 0;
|
|
80
|
+
}
|
|
81
|
+
function isRecord(value) {
|
|
82
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
83
|
+
}
|
|
84
|
+
function annotate(value, ctx) {
|
|
85
|
+
if (!ctx.entryId) return value;
|
|
86
|
+
const { cleaned, encoded } = vercelStegaSplit(value);
|
|
87
|
+
if (!encoded) return value;
|
|
88
|
+
let payload;
|
|
89
|
+
try {
|
|
90
|
+
payload = vercelStegaDecode(encoded);
|
|
91
|
+
} catch {
|
|
92
|
+
return value;
|
|
93
|
+
}
|
|
94
|
+
if (typeof payload?.href !== "string") return value;
|
|
95
|
+
let url;
|
|
96
|
+
try {
|
|
97
|
+
url = new URL(payload.href);
|
|
98
|
+
} catch {
|
|
99
|
+
return value;
|
|
100
|
+
}
|
|
101
|
+
if (url.searchParams.has(ENTRY_PARAM)) return value;
|
|
102
|
+
url.searchParams.set(ENTRY_PARAM, ctx.entryId);
|
|
103
|
+
const itemId = decodeURIComponent(url.pathname.split("/").pop() ?? "");
|
|
104
|
+
if (!url.searchParams.has("field") && ctx.entryField && TOP_LEVEL_ENTRY.test(ctx.entryField) && itemId === ctx.entryOwnerId) {
|
|
105
|
+
url.searchParams.set("field", ctx.entryField);
|
|
106
|
+
}
|
|
107
|
+
return vercelStegaCombine(
|
|
108
|
+
cleaned,
|
|
109
|
+
{ ...payload, href: url.toString() },
|
|
110
|
+
false
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
function walk(value, selections, ctx) {
|
|
114
|
+
if (typeof value === "string") return annotate(value, ctx);
|
|
115
|
+
if (Array.isArray(value)) {
|
|
116
|
+
let changed2 = false;
|
|
117
|
+
const next2 = value.map((element, index) => {
|
|
118
|
+
const path = [...ctx.path, String(index)];
|
|
119
|
+
const entryId = ctx.inAssets ? void 0 : entryIdOf(element);
|
|
120
|
+
const entry = entryId ? {
|
|
121
|
+
entryId,
|
|
122
|
+
entryField: ctx.ownerId ? path.join(".") : void 0,
|
|
123
|
+
entryOwnerId: ctx.ownerId,
|
|
124
|
+
inAssets: isRecord(element) && element._id === void 0
|
|
125
|
+
} : {};
|
|
126
|
+
const out = walk(element, selections, { ...ctx, ...entry, path });
|
|
127
|
+
if (out !== element) changed2 = true;
|
|
128
|
+
return out;
|
|
129
|
+
});
|
|
130
|
+
return changed2 ? next2 : value;
|
|
131
|
+
}
|
|
132
|
+
if (!isRecord(value)) return value;
|
|
133
|
+
const id = typeof value._id === "string" ? value._id : void 0;
|
|
134
|
+
const typename = typeof value.__typename === "string" ? value.__typename : void 0;
|
|
135
|
+
const fields = ctx.doc && selections ? collectFields(selections, typename, ctx.doc) : null;
|
|
136
|
+
let changed = false;
|
|
137
|
+
const next = {};
|
|
138
|
+
for (const [key, child] of Object.entries(value)) {
|
|
139
|
+
const field = fields?.get(key);
|
|
140
|
+
const name = field?.name ?? key;
|
|
141
|
+
const out = walk(child, field?.selections ?? null, {
|
|
142
|
+
...ctx,
|
|
143
|
+
ownerId: id ?? ctx.ownerId,
|
|
144
|
+
path: id ? [name] : [...ctx.path, name]
|
|
145
|
+
});
|
|
146
|
+
if (out !== child) changed = true;
|
|
147
|
+
next[key] = out;
|
|
148
|
+
}
|
|
149
|
+
return changed ? next : value;
|
|
150
|
+
}
|
|
151
|
+
function annotateEditLinks(result, query, operationName) {
|
|
152
|
+
let doc = null;
|
|
153
|
+
if (query !== void 0) {
|
|
154
|
+
try {
|
|
155
|
+
doc = readQueryDocument(query, operationName);
|
|
156
|
+
} catch {
|
|
157
|
+
doc = null;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return walk(result, doc?.operation ?? null, { doc, path: [] });
|
|
161
|
+
}
|
|
162
|
+
|
|
62
163
|
// src/core/live-preview/morph.ts
|
|
63
164
|
function morphElement(current, next) {
|
|
64
165
|
syncAttributes(current, next);
|
|
@@ -376,6 +477,7 @@ export {
|
|
|
376
477
|
PreprError,
|
|
377
478
|
PreprToolbarElement,
|
|
378
479
|
VERSION,
|
|
480
|
+
annotateEditLinks,
|
|
379
481
|
createPreprPreview,
|
|
380
482
|
createToolbarStore,
|
|
381
483
|
definePreprToolbar,
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createLiveBridge,
|
|
3
3
|
createLiveStore
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-IPMB32AZ.js";
|
|
5
5
|
import "./chunk-URXSDJOU.js";
|
|
6
6
|
import {
|
|
7
7
|
applyPatchLog,
|
|
8
8
|
normalizeQuery,
|
|
9
9
|
parsePatchLog
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-KD3GK6TO.js";
|
|
11
11
|
import "./chunk-S3VT4UWM.js";
|
|
12
12
|
export {
|
|
13
13
|
applyPatchLog,
|
|
@@ -537,6 +537,7 @@ function decodeStega(str) {
|
|
|
537
537
|
|
|
538
538
|
// src/core/stega/dom.ts
|
|
539
539
|
var IGNORED_ANCESTORS = "script, style, noscript";
|
|
540
|
+
var AUTO_ENTRY_ATTR = "data-prepr-entry-auto";
|
|
540
541
|
function isIgnoredTextNode(node) {
|
|
541
542
|
if (node.parentElement?.closest(IGNORED_ANCESTORS)) return true;
|
|
542
543
|
return !node.textContent?.trim();
|
|
@@ -570,7 +571,9 @@ function parseEditHref(href) {
|
|
|
570
571
|
return {
|
|
571
572
|
id: url.pathname.split("/").pop() || void 0,
|
|
572
573
|
field: url.searchParams.get("field") || void 0,
|
|
573
|
-
locale: url.searchParams.get("locale") || void 0
|
|
574
|
+
locale: url.searchParams.get("locale") || void 0,
|
|
575
|
+
// Added by the toolkit's `annotateEditLinks`, not by Prepr.
|
|
576
|
+
entry: url.searchParams.get("entry") || void 0
|
|
574
577
|
};
|
|
575
578
|
} catch {
|
|
576
579
|
return {};
|
|
@@ -587,11 +590,16 @@ function tagEncodedElement(element, decoded) {
|
|
|
587
590
|
element.setAttribute("data-prepr-encoded", "");
|
|
588
591
|
element.setAttribute("data-prepr-href", decoded.href);
|
|
589
592
|
element.setAttribute("data-prepr-origin", decoded.origin);
|
|
590
|
-
const { id, field, locale } = parseEditHref(decoded.href);
|
|
593
|
+
const { id, field, locale, entry } = parseEditHref(decoded.href);
|
|
591
594
|
setOrRemove(element, "data-prepr-id", id);
|
|
592
595
|
const fieldHint = element.getAttribute("data-prepr-edit-target")?.trim() || void 0;
|
|
593
596
|
setOrRemove(element, "data-prepr-field", field ?? fieldHint);
|
|
594
597
|
setOrRemove(element, "data-prepr-locale", locale);
|
|
598
|
+
const siteEntry = element.hasAttribute("data-prepr-entry-id") && !element.hasAttribute(AUTO_ENTRY_ATTR);
|
|
599
|
+
if (!siteEntry) {
|
|
600
|
+
setOrRemove(element, "data-prepr-entry-id", entry);
|
|
601
|
+
setOrRemove(element, AUTO_ENTRY_ATTR, entry && "true");
|
|
602
|
+
}
|
|
595
603
|
}
|
|
596
604
|
function readEditPayload(element) {
|
|
597
605
|
return {
|
|
@@ -3517,7 +3525,7 @@ function createPreprPreview(opts = {}) {
|
|
|
3517
3525
|
var import_react = require("react");
|
|
3518
3526
|
|
|
3519
3527
|
// src/version.ts
|
|
3520
|
-
var VERSION = "0.5.0-rc.
|
|
3528
|
+
var VERSION = "0.5.0-rc.7";
|
|
3521
3529
|
|
|
3522
3530
|
// src/core/pixel.ts
|
|
3523
3531
|
var PIXEL_SCRIPT_URL = "https://cdn.tracking.prepr.io/js/prepr.min.js";
|