@arbidocs/coedit 0.5.20 → 0.5.22

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.
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var Y3 = require('yjs');
3
+ var Y = require('yjs');
4
4
  var awareness = require('y-protocols/awareness');
5
5
  var provider = require('@hocuspocus/provider');
6
6
  var store = require('@docx-editor.dev/core/store');
@@ -25,7 +25,7 @@ function _interopNamespace(e) {
25
25
  return Object.freeze(n);
26
26
  }
27
27
 
28
- var Y3__namespace = /*#__PURE__*/_interopNamespace(Y3);
28
+ var Y__namespace = /*#__PURE__*/_interopNamespace(Y);
29
29
 
30
30
  // src/hocuspocus.ts
31
31
 
@@ -338,6 +338,92 @@ function writeUnits(text, units) {
338
338
  function isRichParagraph(map) {
339
339
  return map.has("inline");
340
340
  }
341
+ var PACKED = "xml";
342
+ function isPackedElement(map) {
343
+ return map.has(PACKED);
344
+ }
345
+ function isCompact(map) {
346
+ return isRichParagraph(map) || isPackedElement(map);
347
+ }
348
+ var TEXT_BEARING = /* @__PURE__ */ new Set(["p", "t", "delText", "instrText", "delInstrText"]);
349
+ function packable(xml) {
350
+ if (xml.ns === WML && TEXT_BEARING.has(xml.local)) return false;
351
+ return xml.children.every((c) => typeof c === "string" || packable(c));
352
+ }
353
+ function createPacked(xml, scope) {
354
+ const map = new Y__namespace.Map();
355
+ map.set(PACKED, serializeXml(xml, scope));
356
+ return map;
357
+ }
358
+ function repack(map, xml) {
359
+ const next = serializeXml(xml, scopeOf(map));
360
+ if (map.get(PACKED) !== next) map.set(PACKED, next);
361
+ }
362
+ function scopeOf(node) {
363
+ const chain = [];
364
+ let parent = node.parent;
365
+ while (parent instanceof Y__namespace.Array) {
366
+ const owner = parent.parent;
367
+ if (!(owner instanceof Y__namespace.Map)) break;
368
+ chain.push(owner);
369
+ parent = owner.parent;
370
+ }
371
+ const scope = /* @__PURE__ */ new Map();
372
+ for (const el of chain.reverse()) {
373
+ for (const b of el.get("bindings").toArray()) scope.set(b.prefix, b.ns);
374
+ }
375
+ return scope;
376
+ }
377
+ function scopeWithin(el) {
378
+ const scope = scopeOf(el);
379
+ if (!isPackedElement(el)) {
380
+ for (const b of el.get("bindings").toArray()) scope.set(b.prefix, b.ns);
381
+ }
382
+ return scope;
383
+ }
384
+ var unpackLimits = { maxBytes: 64 * 1024 * 1024, maxElements: 2e6 };
385
+ function unpack(text, scope) {
386
+ const read = store.readXml(text, unpackLimits);
387
+ if (!read.ok) throw new Error(`collab: a packed element is not readable XML (${read.reason})`);
388
+ const convert = (node, outer) => {
389
+ const bindings = [];
390
+ const named = [];
391
+ for (const [name, value] of Object.entries(node.attributes)) {
392
+ if (name === "xmlns") bindings.push({ prefix: "", ns: value });
393
+ else if (name.startsWith("xmlns:")) bindings.push({ prefix: name.slice(6), ns: value });
394
+ else named.push([name, value]);
395
+ }
396
+ const inner = new Map(outer);
397
+ for (const b of bindings) inner.set(b.prefix, b.ns);
398
+ const resolve = (prefix) => {
399
+ if (prefix === "xml") return store.XML_NAMESPACE_URI;
400
+ const ns = inner.get(prefix);
401
+ if (ns === void 0)
402
+ throw new Error(`collab: prefix ${prefix} is not bound in a packed element`);
403
+ return ns;
404
+ };
405
+ const colon = node.name.indexOf(":");
406
+ const xml = {
407
+ ns: colon < 0 ? inner.get("") ?? "" : resolve(node.name.slice(0, colon)),
408
+ local: colon < 0 ? node.name : node.name.slice(colon + 1),
409
+ attrs: named.map(([name, value]) => {
410
+ const at = name.indexOf(":");
411
+ if (at < 0) return { ns: "", local: name, value };
412
+ const prefix = name.slice(0, at);
413
+ return { ns: resolve(prefix), local: name.slice(at + 1), prefix, value };
414
+ }),
415
+ bindings,
416
+ children: node.children.map(
417
+ (child) => child.type === "text" ? child.value : convert(child, inner)
418
+ )
419
+ };
420
+ if (colon >= 0) xml.prefix = node.name.slice(0, colon);
421
+ return xml;
422
+ };
423
+ const root = read.nodes.find((n) => n.type === "element");
424
+ if (!root || root.type !== "element") throw new Error("collab: a packed element is empty");
425
+ return convert(root, scope);
426
+ }
341
427
  function isParagraphEl(el) {
342
428
  return el.ns === WML && el.local === "p";
343
429
  }
@@ -345,47 +431,53 @@ function fieldsOf(map, xml) {
345
431
  map.set("ns", xml.ns);
346
432
  map.set("local", xml.local);
347
433
  if (xml.prefix !== void 0) map.set("prefix", xml.prefix);
348
- const attrs = new Y3__namespace.Array();
434
+ const attrs = new Y__namespace.Array();
349
435
  attrs.push(xml.attrs.map((a) => ({ ...a })));
350
436
  map.set("attrs", attrs);
351
- const bindings = new Y3__namespace.Array();
437
+ const bindings = new Y__namespace.Array();
352
438
  bindings.push(xml.bindings.map((b) => ({ ...b })));
353
439
  map.set("bindings", bindings);
354
440
  }
355
441
  function newText(value) {
356
- const text = new Y3__namespace.Text();
442
+ const text = new Y__namespace.Text();
357
443
  text.insert(0, value);
358
444
  return text;
359
445
  }
360
- function createRichParagraph(xml, encoded) {
361
- const map = new Y3__namespace.Map();
446
+ function createRichParagraph(xml, encoded, scope = /* @__PURE__ */ new Map()) {
447
+ const map = new Y__namespace.Map();
362
448
  fieldsOf(map, xml);
363
- const children = new Y3__namespace.Array();
364
- children.push(encoded.head.map((el) => xmlToLive(el)));
449
+ const inner = withBindings(scope, xml.bindings);
450
+ const children = new Y__namespace.Array();
451
+ children.push(encoded.head.map((el) => xmlToLive(el, inner)));
365
452
  map.set("children", children);
366
- const inline = new Y3__namespace.Text();
453
+ const inline = new Y__namespace.Text();
367
454
  writeUnits(inline, encoded.units);
368
455
  map.set("inline", inline);
369
456
  return map;
370
457
  }
371
- function xmlToLive(xml) {
458
+ function withBindings(scope, bindings) {
459
+ const inner = new Map(scope);
460
+ for (const b of bindings) inner.set(b.prefix, b.ns);
461
+ return inner;
462
+ }
463
+ function xmlToLive(xml, scope = /* @__PURE__ */ new Map(), root = false) {
372
464
  if (isParagraphEl(xml)) {
373
465
  const encoded = encodeParagraph(xml.children);
374
- if (encoded) return createRichParagraph(xml, encoded);
466
+ if (encoded) return createRichParagraph(xml, encoded, scope);
375
467
  }
376
- return xmlToGenericLive(xml);
377
- }
378
- function xmlToGenericLive(xml) {
379
- const map = new Y3__namespace.Map();
468
+ if (!root && packable(xml)) return createPacked(xml, scope);
469
+ const map = new Y__namespace.Map();
380
470
  fieldsOf(map, xml);
381
- const children = new Y3__namespace.Array();
382
- children.push(xml.children.map((c) => typeof c === "string" ? newText(c) : xmlToLive(c)));
471
+ const inner = withBindings(scope, xml.bindings);
472
+ const children = new Y__namespace.Array();
473
+ children.push(xml.children.map((c) => typeof c === "string" ? newText(c) : xmlToLive(c, inner)));
383
474
  map.set("children", children);
384
475
  return map;
385
476
  }
386
477
  function liveToXml(map) {
478
+ if (isPackedElement(map)) return unpack(map.get(PACKED), scopeOf(map));
387
479
  const prefix = map.get("prefix");
388
- const stored = map.get("children").toArray().map((child) => child instanceof Y3__namespace.Text ? child.toString() : liveToXml(child));
480
+ const stored = map.get("children").toArray().map((child) => child instanceof Y__namespace.Text ? child.toString() : liveToXml(child));
389
481
  const children = isRichParagraph(map) ? [...stored, ...decodeInline(readUnits(map.get("inline")))] : stored;
390
482
  const xml = {
391
483
  ns: map.get("ns"),
@@ -400,14 +492,13 @@ function liveToXml(map) {
400
492
  var escapeText = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
401
493
  var escapeAttr = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/\t/g, "&#9;").replace(/\n/g, "&#10;").replace(/\r/g, "&#13;");
402
494
  var qualified = (prefix, local) => prefix ? `${prefix}:${local}` : local;
403
- function serializeXml(el, scope) {
404
- const inScope = new Map(scope);
405
- for (const b of el.bindings) inScope.set(b.prefix, b.ns);
406
- let out = `<${qualified(el.prefix, el.local)}`;
407
- for (const b of el.bindings) {
495
+ function startTag(prefix, local, bindings, attrs, scope) {
496
+ const inScope = withBindings(scope, bindings);
497
+ let out = `<${qualified(prefix, local)}`;
498
+ for (const b of bindings) {
408
499
  out += b.prefix === "" ? ` xmlns="${escapeAttr(b.ns)}"` : ` xmlns:${b.prefix}="${escapeAttr(b.ns)}"`;
409
500
  }
410
- for (const a of el.attrs) {
501
+ for (const a of attrs) {
411
502
  let p = a.prefix;
412
503
  if (a.ns !== "" && !p) {
413
504
  for (const [candidate, uri] of inScope) {
@@ -419,48 +510,41 @@ function serializeXml(el, scope) {
419
510
  }
420
511
  out += ` ${qualified(p, a.local)}="${escapeAttr(a.value)}"`;
421
512
  }
513
+ return [out, inScope];
514
+ }
515
+ function serializeXml(el, scope) {
516
+ const [out, inScope] = startTag(el.prefix, el.local, el.bindings, el.attrs, scope);
422
517
  if (el.children.length === 0) return `${out}/>`;
423
- out += ">";
518
+ let body = "";
424
519
  for (const child of el.children) {
425
- out += typeof child === "string" ? escapeText(child) : serializeXml(child, inScope);
520
+ body += typeof child === "string" ? escapeText(child) : serializeXml(child, inScope);
426
521
  }
427
- return `${out}</${qualified(el.prefix, el.local)}>`;
522
+ return `${out}>${body}</${qualified(el.prefix, el.local)}>`;
428
523
  }
429
524
  function serializeLive(el, scope) {
430
- if (isRichParagraph(el)) return serializeXml(liveToXml(el), scope);
525
+ if (isPackedElement(el)) return el.get(PACKED);
431
526
  const prefix = el.get("prefix");
432
527
  const local = el.get("local");
433
528
  const bindings = el.get("bindings").toArray();
434
529
  const attrs = el.get("attrs").toArray();
435
530
  const children = el.get("children").toArray();
436
- const inScope = new Map(scope);
437
- for (const b of bindings) inScope.set(b.prefix, b.ns);
438
- let out = `<${qualified(prefix, local)}`;
439
- for (const b of bindings) {
440
- out += b.prefix === "" ? ` xmlns="${escapeAttr(b.ns)}"` : ` xmlns:${b.prefix}="${escapeAttr(b.ns)}"`;
441
- }
442
- for (const a of attrs) {
443
- let p = a.prefix;
444
- if (a.ns !== "" && !p) {
445
- for (const [candidate, uri] of inScope) {
446
- if (candidate !== "" && uri === a.ns) {
447
- p = candidate;
448
- break;
449
- }
450
- }
451
- }
452
- out += ` ${qualified(p, a.local)}="${escapeAttr(a.value)}"`;
453
- }
454
- if (children.length === 0) return `${out}/>`;
455
- out += ">";
531
+ const [out, inScope] = startTag(prefix, local, bindings, attrs, scope);
532
+ const inline = isRichParagraph(el) ? decodeInline(readUnits(el.get("inline"))) : [];
533
+ if (children.length === 0 && inline.length === 0) return `${out}/>`;
534
+ let body = "";
456
535
  for (const child of children) {
457
- out += child instanceof Y3__namespace.Text ? escapeText(child.toString()) : serializeLive(child, inScope);
536
+ body += child instanceof Y__namespace.Text ? escapeText(child.toString()) : serializeLive(child, inScope);
458
537
  }
459
- return `${out}</${qualified(prefix, local)}>`;
538
+ for (const child of inline) body += serializeXml(child, inScope);
539
+ return `${out}>${body}</${qualified(prefix, local)}>`;
460
540
  }
461
541
 
462
542
  // src/encoding.ts
463
- var COLLAB_FORMAT = "arbi-docx/1";
543
+ var COLLAB_FORMAT = "arbi-docx/2";
544
+ var READABLE_FORMATS = /* @__PURE__ */ new Set(["arbi-docx/1", COLLAB_FORMAT]);
545
+ function isReadableFormat(format) {
546
+ return format !== void 0 && READABLE_FORMATS.has(format);
547
+ }
464
548
  function isBootstrapped(doc) {
465
549
  return doc.getMap("meta").get("format") !== void 0;
466
550
  }
@@ -757,7 +841,7 @@ var NodeRegistry = class {
757
841
  require(id) {
758
842
  let entry = this.entries.get(id) ?? this.resolveInsideParagraph(id);
759
843
  if (!entry) throw new RegistryError(`journal names unknown node ${id}`);
760
- if ("live" in entry && entry.live instanceof Y3__namespace.Map && isRichParagraph(entry.live)) {
844
+ if ("live" in entry && entry.live instanceof Y__namespace.Map && isCompact(entry.live)) {
761
845
  this.openParagraph(entry.live);
762
846
  entry = this.entries.get(id);
763
847
  }
@@ -775,7 +859,7 @@ var NodeRegistry = class {
775
859
  for (let length = path.length - 1; length >= 1; length--) {
776
860
  const ancestor = this.entries.get(id.slice(0, hash + 1) + path.slice(0, length).join("."));
777
861
  if (!ancestor) continue;
778
- if ("live" in ancestor && ancestor.live instanceof Y3__namespace.Map && isRichParagraph(ancestor.live)) {
862
+ if ("live" in ancestor && ancestor.live instanceof Y__namespace.Map && isCompact(ancestor.live)) {
779
863
  this.openParagraph(ancestor.live);
780
864
  return this.entries.get(id);
781
865
  }
@@ -807,13 +891,13 @@ var NodeRegistry = class {
807
891
  /**
808
892
  * Walk a mirror root and register every node under its positional id, `${part}#0` for the root and
809
893
  * `${parent}.${index}` below it. This is the id scheme core assigns when it reads a part. A rich
810
- * paragraph is registered as one node; its inner nodes appear when it is opened.
894
+ * paragraph or a packed element is registered as one node; its inner nodes appear when it is opened.
811
895
  */
812
896
  registerTree(partName, root) {
813
897
  const walk = (node, id) => {
814
898
  this.registerLive(id, node);
815
- if (node instanceof Y3__namespace.Text) return;
816
- if (isRichParagraph(node)) return;
899
+ if (node instanceof Y__namespace.Text) return;
900
+ if (isCompact(node)) return;
817
901
  childrenOf(node).forEach((child, index) => walk(child, `${id}.${index}`));
818
902
  };
819
903
  walk(root, `${partName}#0`);
@@ -870,7 +954,7 @@ var NodeRegistry = class {
870
954
  for (const child of children) this.own(child, owner);
871
955
  if (owner) this.dirty.add(owner);
872
956
  }
873
- /** Write every changed open paragraph back into the mirror. Call at the end of a journal. */
957
+ /** Write every changed open paragraph or packed element back into the mirror. Call at the end of a journal. */
874
958
  flushRich() {
875
959
  for (const live of [...this.dirty]) {
876
960
  this.dirty.delete(live);
@@ -881,6 +965,11 @@ var NodeRegistry = class {
881
965
  writeBack(record) {
882
966
  const { live, root } = record;
883
967
  const xml = plainToXml(root);
968
+ if (isPackedElement(live)) {
969
+ if (packable(xml)) repack(live, xml);
970
+ else this.degrade(record);
971
+ return;
972
+ }
884
973
  const encoded = encodeParagraph(xml.children);
885
974
  if (!encoded) {
886
975
  this.degrade(record);
@@ -897,21 +986,22 @@ var NodeRegistry = class {
897
986
  bindings.push(xml.bindings.map((b) => ({ ...b })));
898
987
  }
899
988
  const head = childrenOf(live);
900
- const stored = head.toArray().map((child) => liveToXml(child));
901
- if (JSON.stringify(stored) !== JSON.stringify(encoded.head)) {
989
+ const scope = scopeWithin(live);
990
+ const stored = head.toArray().map((child) => serializeLive(child, scope)).join("");
991
+ if (stored !== encoded.head.map((el) => serializeXml(el, scope)).join("")) {
902
992
  head.delete(0, head.length);
903
- head.push(encoded.head.map((el) => xmlToLive(el)));
993
+ head.push(encoded.head.map((el) => xmlToLive(el, scope)));
904
994
  }
905
995
  const inline = live.get("inline");
906
996
  applyUnits(inline, readUnits(inline), encoded.units);
907
997
  }
908
- /** The paragraph can no longer be held as rich text: store it as plain elements instead. */
998
+ /** The paragraph can no longer be held as rich text, or the element packed: store it as a tree. */
909
999
  degrade(record) {
910
1000
  const parent = record.live.parent;
911
- if (!(parent instanceof Y3__namespace.Array))
1001
+ if (!(parent instanceof Y__namespace.Array))
912
1002
  throw new RegistryError("a paragraph outside a parent cannot change form");
913
1003
  const index = parent.toArray().indexOf(record.live);
914
- const generic = this.toGenericLive(record.root);
1004
+ const generic = this.toGenericLive(record.root, scopeOf(record.live));
915
1005
  this.open.delete(record.live);
916
1006
  parent.delete(index, 1);
917
1007
  parent.insert(index, [generic]);
@@ -926,8 +1016,8 @@ var NodeRegistry = class {
926
1016
  snapshotLive(node) {
927
1017
  const id = this.liveIds.get(node);
928
1018
  if (id === void 0) throw new RegistryError("live node has no registered id");
929
- if (node instanceof Y3__namespace.Text) return { type: "text", id, value: node.toString() };
930
- if (isRichParagraph(node)) {
1019
+ if (node instanceof Y__namespace.Text) return { type: "text", id, value: node.toString() };
1020
+ if (isCompact(node)) {
931
1021
  return this.open.get(node)?.root ?? xmlToPlain(liveToXml(node), id);
932
1022
  }
933
1023
  const prefix = node.get("prefix");
@@ -955,8 +1045,8 @@ var NodeRegistry = class {
955
1045
  if (id !== void 0 && this.isCurrentLive(id, node)) {
956
1046
  this.entries.set(id, { plain });
957
1047
  }
958
- if (node instanceof Y3__namespace.Text || plain.type === "text") return;
959
- if (isRichParagraph(node)) {
1048
+ if (node instanceof Y__namespace.Text || plain.type === "text") return;
1049
+ if (isCompact(node)) {
960
1050
  this.open.delete(node);
961
1051
  this.dirty.delete(node);
962
1052
  return;
@@ -964,53 +1054,61 @@ var NodeRegistry = class {
964
1054
  const liveChildren = childrenOf(node).toArray();
965
1055
  liveChildren.forEach((child, index) => this.detachInto(child, plain.children[index]));
966
1056
  }
967
- /** Build Yjs types for a plain subtree and register every node as live. */
968
- toLive(plain) {
1057
+ /**
1058
+ * Build Yjs types for a plain subtree placed where `scope` is in force, and register every node as
1059
+ * live. A rich paragraph or packed element stays open on the plain tree, which is already current.
1060
+ * A part's `root` is never packed.
1061
+ */
1062
+ toLive(plain, scope = /* @__PURE__ */ new Map(), root = false) {
969
1063
  if (plain.type === "text") {
970
- const text = new Y3__namespace.Text();
1064
+ const text = new Y__namespace.Text();
971
1065
  text.insert(0, plain.value);
972
1066
  this.registerLive(plain.id, text);
973
1067
  return text;
974
1068
  }
1069
+ const xml = plainToXml(plain);
1070
+ let map;
975
1071
  if (isParagraphEl(plain)) {
976
- const xml = plainToXml(plain);
977
1072
  const encoded = encodeParagraph(xml.children);
978
- if (encoded) {
979
- const map = createRichParagraph(xml, encoded);
980
- this.liveIds.set(map, plain.id);
981
- this.registerPlain(plain);
982
- this.own(plain, map);
983
- this.open.set(map, { live: map, root: plain, id: plain.id });
984
- return map;
985
- }
1073
+ if (encoded) map = createRichParagraph(xml, encoded, scope);
1074
+ }
1075
+ if (!map && !root && packable(xml)) map = xmlToLive(xml, scope);
1076
+ if (map) {
1077
+ this.liveIds.set(map, plain.id);
1078
+ this.registerPlain(plain);
1079
+ this.own(plain, map);
1080
+ this.open.set(map, { live: map, root: plain, id: plain.id });
1081
+ return map;
986
1082
  }
987
- return this.toGenericLive(plain);
1083
+ return this.toGenericLive(plain, scope);
988
1084
  }
989
- toGenericLive(plain) {
1085
+ toGenericLive(plain, scope) {
990
1086
  const map = xmlToGenericShell(plain);
991
- const children = new Y3__namespace.Array();
992
- children.push(plain.children.map((child) => this.toLive(child)));
1087
+ const inner = withBindings(scope, plain.bindings);
1088
+ const children = new Y__namespace.Array();
1089
+ children.push(plain.children.map((child) => this.toLive(child, inner)));
993
1090
  map.set("children", children);
994
1091
  this.registerLive(plain.id, map);
995
1092
  return map;
996
1093
  }
997
1094
  /**
998
- * A live node that can be inserted into a parent. Anything not yet attached is built fresh; an
999
- * attached node is copied, because a Yjs type cannot have two parents.
1095
+ * A live node that can be inserted into a parent (`scope` is in force there), or a part's `root`.
1096
+ * Anything not yet attached is built fresh; an attached node is copied, because a Yjs type cannot
1097
+ * have two parents.
1000
1098
  */
1001
- attachable(id) {
1002
- return this.toLive(this.snapshot(id));
1099
+ attachable(id, scope = /* @__PURE__ */ new Map(), root = false) {
1100
+ return this.toLive(this.snapshot(id), scope, root);
1003
1101
  }
1004
1102
  };
1005
1103
  function xmlToGenericShell(plain) {
1006
- const map = new Y3__namespace.Map();
1104
+ const map = new Y__namespace.Map();
1007
1105
  map.set("ns", plain.ns);
1008
1106
  map.set("local", plain.local);
1009
1107
  if (plain.prefix !== void 0) map.set("prefix", plain.prefix);
1010
- const attrs = new Y3__namespace.Array();
1108
+ const attrs = new Y__namespace.Array();
1011
1109
  attrs.push(plain.attrs.map((a) => ({ ...a })));
1012
1110
  map.set("attrs", attrs);
1013
- const bindings = new Y3__namespace.Array();
1111
+ const bindings = new Y__namespace.Array();
1014
1112
  bindings.push(plain.bindings.map((b) => ({ ...b })));
1015
1113
  map.set("bindings", bindings);
1016
1114
  return map;
@@ -1075,7 +1173,7 @@ function setNamespaceBinding(registry, id, prefix, uri) {
1075
1173
  }
1076
1174
  }
1077
1175
  function asLiveElement(node, id) {
1078
- if (node instanceof Y3__namespace.Text) throw new JournalError(`${id} is a text node, not an element`);
1176
+ if (node instanceof Y__namespace.Text) throw new JournalError(`${id} is a text node, not an element`);
1079
1177
  return node;
1080
1178
  }
1081
1179
  function asPlainElement(node, id) {
@@ -1091,7 +1189,7 @@ function spliceText(registry, id, start, deleteCount, insert) {
1091
1189
  return;
1092
1190
  }
1093
1191
  const text = entry.live;
1094
- if (!(text instanceof Y3__namespace.Text)) throw new JournalError(`${id} is not a text node`);
1192
+ if (!(text instanceof Y__namespace.Text)) throw new JournalError(`${id} is not a text node`);
1095
1193
  if (start < 0 || start + deleteCount > text.length) {
1096
1194
  throw new JournalError(`text splice out of range on ${id}`);
1097
1195
  }
@@ -1104,27 +1202,29 @@ function detachRemoved(registry, parent, start, count) {
1104
1202
  function spliceChildren(registry, parentId, start, deleteCount, childIds) {
1105
1203
  const parentEntry = registry.require(parentId);
1106
1204
  if ("plain" in parentEntry) {
1107
- const parent = asPlainElement(parentEntry.plain, parentId);
1108
- if (start < 0 || start + deleteCount > parent.children.length) {
1205
+ const parent2 = asPlainElement(parentEntry.plain, parentId);
1206
+ if (start < 0 || start + deleteCount > parent2.children.length) {
1109
1207
  throw new JournalError(`child splice out of range on ${parentId}`);
1110
1208
  }
1111
1209
  const inserted2 = childIds.map((id) => registry.snapshot(id));
1112
- parent.children.splice(start, deleteCount, ...inserted2);
1113
- registry.adopt(parent, inserted2);
1210
+ parent2.children.splice(start, deleteCount, ...inserted2);
1211
+ registry.adopt(parent2, inserted2);
1114
1212
  return;
1115
1213
  }
1116
- const children = childrenOf(asLiveElement(parentEntry.live, parentId));
1214
+ const parent = asLiveElement(parentEntry.live, parentId);
1215
+ const children = childrenOf(parent);
1117
1216
  if (start < 0 || start + deleteCount > children.length) {
1118
1217
  throw new JournalError(`child splice out of range on ${parentId}`);
1119
1218
  }
1120
1219
  detachRemoved(registry, children, start, deleteCount);
1121
- const inserted = childIds.map((id) => registry.attachable(id));
1220
+ const scope = scopeWithin(parent);
1221
+ const inserted = childIds.map((id) => registry.attachable(id, scope));
1122
1222
  if (deleteCount > 0) children.delete(start, deleteCount);
1123
1223
  if (inserted.length > 0) children.insert(start, inserted);
1124
1224
  }
1125
1225
  function locate(registry, id, node) {
1126
1226
  const children = node.parent;
1127
- if (!(children instanceof Y3__namespace.Array)) throw new JournalError(`${id} is not attached`);
1227
+ if (!(children instanceof Y__namespace.Array)) throw new JournalError(`${id} is not attached`);
1128
1228
  const index = children.toArray().indexOf(node);
1129
1229
  if (index < 0) throw new JournalError(`${id} is not in its parent`);
1130
1230
  return { children, index };
@@ -1151,8 +1251,10 @@ function moveNode(registry, id, destinationId, destinationIndex) {
1151
1251
  registry.adopt(destination2, [copy]);
1152
1252
  return;
1153
1253
  }
1154
- const destination = childrenOf(asLiveElement(destinationEntry.live, destinationId));
1155
- destination.insert(destinationIndex, [registry.toLive(copy)]);
1254
+ const destination = asLiveElement(destinationEntry.live, destinationId);
1255
+ childrenOf(destination).insert(destinationIndex, [
1256
+ registry.toLive(copy, scopeWithin(destination))
1257
+ ]);
1156
1258
  }
1157
1259
  function renameNode(registry, id, qname) {
1158
1260
  const entry = registry.require(id);
@@ -1167,7 +1269,7 @@ function renameNode(registry, id, qname) {
1167
1269
  return true;
1168
1270
  }
1169
1271
  const live = entry.live;
1170
- if (live instanceof Y3__namespace.Text || isRichParagraph(live)) return false;
1272
+ if (live instanceof Y__namespace.Text || isCompact(live)) return false;
1171
1273
  if (live.get("ns") !== qname.namespaceUri) live.set("ns", qname.namespaceUri);
1172
1274
  if (live.get("local") !== qname.localName) live.set("local", qname.localName);
1173
1275
  if (qname.prefix === void 0) {
@@ -1197,7 +1299,7 @@ function putNode(registry, effect) {
1197
1299
  }
1198
1300
  function rootFor(registry, id) {
1199
1301
  const entry = registry.require(id);
1200
- const live = "live" in entry && entry.live.parent === null ? entry.live : registry.attachable(id);
1302
+ const live = "live" in entry && entry.live.parent === null ? entry.live : registry.attachable(id, /* @__PURE__ */ new Map(), true);
1201
1303
  return asLiveElement(live, id);
1202
1304
  }
1203
1305
  function applyEffect(doc, registry, effect, context) {
@@ -1241,7 +1343,7 @@ function applyEffect(doc, registry, effect, context) {
1241
1343
  const rels = doc.getMap("rels");
1242
1344
  let byId = rels.get(effect.owner);
1243
1345
  if (!byId) {
1244
- byId = new Y3__namespace.Map();
1346
+ byId = new Y__namespace.Map();
1245
1347
  rels.set(effect.owner, byId);
1246
1348
  }
1247
1349
  byId.set(effect.record.id, { ...effect.record });
@@ -1446,7 +1548,7 @@ var DocxCollaborationSession = class {
1446
1548
  this.doc = options.doc;
1447
1549
  this.awareness = options.awareness;
1448
1550
  this.offlineEditing = options.offlineEditing ?? false;
1449
- this.undoManager = new Y3__namespace.UndoManager(
1551
+ this.undoManager = new Y__namespace.UndoManager(
1450
1552
  [
1451
1553
  this.doc.getMap("parts"),
1452
1554
  this.doc.getMap("rels"),
@@ -1486,7 +1588,7 @@ var DocxCollaborationSession = class {
1486
1588
  this.setStatus("error", "not-initialized");
1487
1589
  return;
1488
1590
  }
1489
- if (readFormat(this.doc) !== COLLAB_FORMAT) {
1591
+ if (!isReadableFormat(readFormat(this.doc))) {
1490
1592
  this.setStatus("error", "collaboration-format-mismatch", readFormat(this.doc));
1491
1593
  return;
1492
1594
  }
@@ -1760,7 +1862,7 @@ function resolveAddress(port, address) {
1760
1862
  };
1761
1863
  }
1762
1864
  function vectorKey(doc) {
1763
- return Array.from(Y3__namespace.encodeStateVector(doc)).join(",");
1865
+ return Array.from(Y__namespace.encodeStateVector(doc)).join(",");
1764
1866
  }
1765
1867
  function randomToken() {
1766
1868
  if (typeof crypto.randomUUID === "function") return crypto.randomUUID();
@@ -1779,7 +1881,7 @@ var CollaborationJoinError = class extends Error {
1779
1881
  }
1780
1882
  };
1781
1883
  async function createHocuspocusCollaboration(options) {
1782
- const ydoc = new Y3__namespace.Doc();
1884
+ const ydoc = new Y__namespace.Doc();
1783
1885
  const awareness$1 = new awareness.Awareness(ydoc);
1784
1886
  const session = new DocxCollaborationSession({
1785
1887
  doc: ydoc,