@echovisionlab/geul-common 0.2.2 → 0.2.3

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/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@echovisionlab/geul-common",
3
3
  "description": "Shared TypeScript contracts and helpers for Geul editors, collaboration, localized content, media blocks, pages, posts, and runtime events.",
4
4
  "author": "state303 <state303@dsub.io>",
5
- "version": "0.2.2",
5
+ "version": "0.2.3",
6
6
  "private": false,
7
7
  "type": "module",
8
8
  "repository": {
@@ -413,6 +413,17 @@ function changedStyleAttributes(
413
413
  return result;
414
414
  }
415
415
 
416
+ function isSurrogatePairBoundary(value: string, boundary: number): boolean {
417
+ if (boundary <= 0 || boundary >= value.length) {
418
+ return false;
419
+ }
420
+ const before = value.charCodeAt(boundary - 1);
421
+ const after = value.charCodeAt(boundary);
422
+ return (
423
+ before >= 0xd800 && before <= 0xdbff && after >= 0xdc00 && after <= 0xdfff
424
+ );
425
+ }
426
+
416
427
  function minimalDiff(
417
428
  before: string,
418
429
  after: string,
@@ -429,6 +440,12 @@ function minimalDiff(
429
440
  ) {
430
441
  from += 1;
431
442
  }
443
+ if (
444
+ isSurrogatePairBoundary(before, from) ||
445
+ isSurrogatePairBoundary(after, from)
446
+ ) {
447
+ from -= 1;
448
+ }
432
449
  let oldTo = before.length;
433
450
  let newTo = after.length;
434
451
  while (
@@ -439,6 +456,13 @@ function minimalDiff(
439
456
  oldTo -= 1;
440
457
  newTo -= 1;
441
458
  }
459
+ if (
460
+ isSurrogatePairBoundary(before, oldTo) ||
461
+ isSurrogatePairBoundary(after, newTo)
462
+ ) {
463
+ oldTo += 1;
464
+ newTo += 1;
465
+ }
442
466
  return { from, oldTo, newTo };
443
467
  }
444
468
 
@@ -621,7 +645,9 @@ function reconcileRawGroup(
621
645
  return;
622
646
  }
623
647
  if (raw.kind === "link" && desired.kind === "link") {
624
- raw.link.set("href", desired.href);
648
+ if (raw.link.get("href") !== desired.href) {
649
+ raw.link.set("href", desired.href);
650
+ }
625
651
  const content = raw.content ?? new Y.Array<unknown>();
626
652
  if (!raw.content && desired.runs.some((run) => run.text.length > 0)) {
627
653
  raw.link.set("content", content);
@@ -167,9 +167,13 @@ function projectedTextField(
167
167
  return fail(`${reason}:embed`);
168
168
  }
169
169
  const item: ProjectedTextRun = { text: operation.insert };
170
- const style = jsonStyle(mergedTextStyle(legacyStyle, operation.attributes));
171
- if (style) {
172
- item.styles = style;
170
+ if (operation.attributes !== undefined || styleValue !== undefined) {
171
+ const style = jsonStyle(
172
+ mergedTextStyle(legacyStyle, operation.attributes),
173
+ );
174
+ if (style) {
175
+ item.styles = style;
176
+ }
173
177
  }
174
178
  appendProjectedText(result, item);
175
179
  }
@@ -347,13 +351,12 @@ export function fromYRichTextBlockPayload(
347
351
  "inline_content:payload_json",
348
352
  ) as JsonValue;
349
353
  }
350
- const payload = Object.fromEntries(value.entries());
351
354
  const projected = decodeOtherFields(
352
355
  value,
353
356
  "content",
354
357
  "inline_content:payload_json",
355
358
  );
356
- const rawContent = payload.content;
359
+ const rawContent = value.get("content");
357
360
  if (rawContent === undefined) {
358
361
  return projected as JsonValue;
359
362
  }