@preprio/toolkit 0.5.0-rc.3 → 0.5.0-rc.4

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.
@@ -148,11 +148,25 @@ function fieldKeyIn(record, apiId) {
148
148
  const name = graphqlFieldName(apiId);
149
149
  return Object.prototype.hasOwnProperty.call(record, name) ? name : void 0;
150
150
  }
151
- var UPPERCASE_BOUNDARY;
151
+ function plainTextFromHtml(html) {
152
+ return html.replace(TAG_PATTERN, "");
153
+ }
154
+ function isTextEntry(record) {
155
+ const typename = record.__typename;
156
+ if (typeof typename === "string") return typename === "Text";
157
+ return "html" in record || "text" in record && "format" in record;
158
+ }
159
+ var UPPERCASE_BOUNDARY, TEXT_BODY_FIELDS, TAG_PATTERN;
152
160
  var init_field_name = __esm({
153
161
  "src/core/live-preview/field-name.ts"() {
154
162
  "use strict";
155
163
  UPPERCASE_BOUNDARY = /(.)(?=[A-Z])/g;
164
+ TEXT_BODY_FIELDS = [
165
+ { name: "body", plain: false },
166
+ { name: "html", plain: false },
167
+ { name: "text", plain: true }
168
+ ];
169
+ TAG_PATTERN = /<[^>]+>/g;
156
170
  }
157
171
  });
158
172
 
@@ -212,13 +226,51 @@ function patchSnapshot(snapshot, index, itemId, field, value) {
212
226
  if (!paths?.length) return snapshot;
213
227
  let root = snapshot;
214
228
  let changed = false;
229
+ const markChanged = () => {
230
+ changed = true;
231
+ };
215
232
  for (const path of paths) {
216
- root = patchAtPath(root, path, field, value, () => {
217
- changed = true;
218
- });
233
+ for (const [target, targetValue] of expandTextBody(
234
+ root,
235
+ path,
236
+ field,
237
+ value
238
+ )) {
239
+ root = patchAtPath(root, path, target, targetValue, markChanged);
240
+ }
219
241
  }
220
242
  return changed ? root : snapshot;
221
243
  }
244
+ function expandTextBody(root, path, field, value) {
245
+ const segments = field.split(".");
246
+ if (segments[segments.length - 1] !== "body" || typeof value !== "string") {
247
+ return [[field, value]];
248
+ }
249
+ let node = root;
250
+ for (const step of path) {
251
+ node = node[step];
252
+ }
253
+ for (const segment of segments.slice(0, -1)) {
254
+ if (node === null || typeof node !== "object") return [[field, value]];
255
+ const record2 = node;
256
+ node = INDEX_SEGMENT.test(segment) ? record2[Number(segment)] : record2[fieldKeyIn(record2, segment) ?? segment];
257
+ }
258
+ if (node === null || typeof node !== "object" || Array.isArray(node)) {
259
+ return [[field, value]];
260
+ }
261
+ const record = node;
262
+ if (!isTextEntry(record)) return [[field, value]];
263
+ const prefix = segments.slice(0, -1);
264
+ const writes = [];
265
+ for (const { name, plain } of TEXT_BODY_FIELDS) {
266
+ if (!(name in record)) continue;
267
+ writes.push([
268
+ [...prefix, name].join("."),
269
+ plain ? plainTextFromHtml(value) : value
270
+ ]);
271
+ }
272
+ return writes.length ? writes : [[field, value]];
273
+ }
222
274
  function patchAtPath(root, path, field, value, markChanged) {
223
275
  const segments = field.split(".");
224
276
  if (segments.some((s) => FORBIDDEN_SEGMENTS.has(s))) return root;
@@ -290,7 +342,7 @@ function buildText(entry, template) {
290
342
  _id: entry._id,
291
343
  body,
292
344
  html: body,
293
- text: body.replace(TAG_PATTERN, ""),
345
+ text: plainTextFromHtml(body),
294
346
  format: entry.format ?? null
295
347
  };
296
348
  if (!template) return full;
@@ -368,7 +420,7 @@ function keepEditLink(current, value) {
368
420
  if (!encoded || (0, import_stega.vercelStegaSplit)(value).encoded) return value;
369
421
  return value + encoded;
370
422
  }
371
- var import_stega, INDEX_SEGMENT, FORBIDDEN_SEGMENTS, TAG_PATTERN;
423
+ var import_stega, INDEX_SEGMENT, FORBIDDEN_SEGMENTS;
372
424
  var init_patch = __esm({
373
425
  "src/core/live-preview/patch.ts"() {
374
426
  "use strict";
@@ -376,7 +428,6 @@ var init_patch = __esm({
376
428
  init_field_name();
377
429
  INDEX_SEGMENT = /^\d+$/;
378
430
  FORBIDDEN_SEGMENTS = /* @__PURE__ */ new Set(["__proto__", "prototype", "constructor"]);
379
- TAG_PATTERN = /<[^>]+>/g;
380
431
  }
381
432
  });
382
433
 
@@ -1192,11 +1243,13 @@ function applyPatch(root, index, patch, doc, result) {
1192
1243
  const segments = patch.field.split(".");
1193
1244
  if (segments.some((s) => !s || FORBIDDEN_SEGMENTS2.has(s))) return root;
1194
1245
  const targets = [];
1246
+ const plain = /* @__PURE__ */ new Set();
1195
1247
  for (const ownerPath of ownerPaths) {
1196
1248
  if (doc) {
1197
1249
  const resolved = resolveTargets(root, doc, ownerPath, segments);
1198
1250
  root = resolved.root;
1199
1251
  targets.push(...resolved.targets);
1252
+ resolved.plain.forEach((target) => plain.add(target));
1200
1253
  } else {
1201
1254
  targets.push([...ownerPath, ...segments.map(toPathSegment)]);
1202
1255
  }
@@ -1210,7 +1263,8 @@ function applyPatch(root, index, patch, doc, result) {
1210
1263
  }
1211
1264
  if (patch.type === "field") {
1212
1265
  for (const target of targets) {
1213
- let value = keepEditLink(readAtPath(root, target), patch.value);
1266
+ const pushed = plain.has(target) && typeof patch.value === "string" ? plainTextFromHtml(patch.value) : patch.value;
1267
+ let value = keepEditLink(readAtPath(root, target), pushed);
1214
1268
  if (patch.edit && typeof value === "string" && !(0, import_stega2.vercelStegaSplit)(value).encoded) {
1215
1269
  value = editLinksFor(result, patch.edit.item)?.encode(
1216
1270
  value,
@@ -1274,9 +1328,10 @@ function resolveTargets(root, doc, ownerPath, segments) {
1274
1328
  owner = owner[step];
1275
1329
  }
1276
1330
  const selections = selectionsAt(root, doc, ownerPath);
1277
- if (!selections) return { root, targets: [] };
1331
+ if (!selections) return { root, targets: [], plain: /* @__PURE__ */ new Set() };
1278
1332
  let current = root;
1279
1333
  const out = [];
1334
+ const plain = /* @__PURE__ */ new Set();
1280
1335
  const walk = (node, sel, i, path) => {
1281
1336
  if (i === segments.length) {
1282
1337
  out.push(path);
@@ -1297,12 +1352,15 @@ function resolveTargets(root, doc, ownerPath, segments) {
1297
1352
  if (node === null || typeof node !== "object") return;
1298
1353
  const record = node;
1299
1354
  const wanted = graphqlFieldName(segment);
1355
+ const textBody = i === segments.length - 1 && segment === "body" && isTextEntry(record) ? TEXT_BODY_FIELDS : null;
1300
1356
  let matched = false;
1301
1357
  for (const field of collectFields(sel, typenameOf(node), doc).values()) {
1302
- if (field.name !== segment && field.name !== wanted) continue;
1358
+ const alias = textBody?.find((f) => f.name === field.name);
1359
+ if (field.name !== segment && field.name !== wanted && !alias) continue;
1303
1360
  if (!Object.prototype.hasOwnProperty.call(record, field.key)) continue;
1304
1361
  matched = true;
1305
1362
  const fieldPath = [...path, field.key];
1363
+ if (alias?.plain) plain.add(fieldPath);
1306
1364
  let value = record[field.key];
1307
1365
  const next = segments[i + 1];
1308
1366
  if (value === null && field.selections.length && next !== void 0 && next !== "items" && !INDEX_SEGMENT2.test(next)) {
@@ -1325,7 +1383,7 @@ function resolveTargets(root, doc, ownerPath, segments) {
1325
1383
  if (!matched && segment === "items") walk(node, sel, i + 1, path);
1326
1384
  };
1327
1385
  walk(owner, selections, 0, ownerPath);
1328
- return { root: current, targets: out };
1386
+ return { root: current, targets: out, plain };
1329
1387
  }
1330
1388
  function resolveTypename(doc, selections, typename, typeName) {
1331
1389
  const known = typeConditions(selections, doc);
package/dist/nuxt/live.js CHANGED
@@ -26,7 +26,7 @@ function isFramed() {
26
26
  return typeof window !== "undefined" && window.self !== window.top;
27
27
  }
28
28
  function startLive() {
29
- starting ?? (starting = import("./live-preview-PTEC3GPC.js").then(
29
+ starting ?? (starting = import("./live-preview-O2ZTJNW4.js").then(
30
30
  ({ applyPatchLog, createLiveBridge, createLiveStore }) => {
31
31
  applyLog = applyPatchLog;
32
32
  const started = createLiveStore();
@@ -3513,7 +3513,7 @@ function createPreprPreview(opts = {}) {
3513
3513
  }
3514
3514
 
3515
3515
  // src/version.ts
3516
- var VERSION = "0.5.0-rc.3";
3516
+ var VERSION = "0.5.0-rc.4";
3517
3517
 
3518
3518
  // src/core/pixel.ts
3519
3519
  var PIXEL_SCRIPT_URL = "https://cdn.tracking.prepr.io/js/prepr.min.js";
@@ -3489,7 +3489,7 @@ function createPreprPreview(opts = {}) {
3489
3489
  }
3490
3490
 
3491
3491
  // src/version.ts
3492
- var VERSION = "0.5.0-rc.3";
3492
+ var VERSION = "0.5.0-rc.4";
3493
3493
 
3494
3494
  // src/core/pixel.ts
3495
3495
  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.3";
38
+ var VERSION = "0.5.0-rc.4";
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.3";
2
+ var VERSION = "0.5.0-rc.4";
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.3",
3
+ "version": "0.5.0-rc.4",
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)",