@arbidocs/coedit 0.5.21 → 0.5.23

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/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { COLLAB_FORMAT, MaterializeError } from './encoding.cjs';
2
2
  export { C as CollaborationSessionError, D as DocxCollaborationSession, a as DocxCollaborationSessionOptions } from './session-WGvWs6yO.cjs';
3
- export { C as COLLAB_PROTOCOL, D as DOCUMENT_COLLABORATION_VERSIONS } from './versions-DXiFQMA6.cjs';
3
+ export { C as COLLAB_PROTOCOL, D as DOCUMENT_COLLABORATION_VERSIONS } from './versions-XSYTVmOU.cjs';
4
4
  import { EditorModule } from '@docx-editor.dev/core';
5
5
  import { EditorCollaborationSession } from '@docx-editor.dev/core/collaboration';
6
6
  import '@docx-editor.dev/core/store';
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { COLLAB_FORMAT, MaterializeError } from './encoding.js';
2
2
  export { C as CollaborationSessionError, D as DocxCollaborationSession, a as DocxCollaborationSessionOptions } from './session-WGvWs6yO.js';
3
- export { C as COLLAB_PROTOCOL, D as DOCUMENT_COLLABORATION_VERSIONS } from './versions-DXiFQMA6.js';
3
+ export { C as COLLAB_PROTOCOL, D as DOCUMENT_COLLABORATION_VERSIONS } from './versions-XSYTVmOU.js';
4
4
  import { EditorModule } from '@docx-editor.dev/core';
5
5
  import { EditorCollaborationSession } from '@docx-editor.dev/core/collaboration';
6
6
  import '@docx-editor.dev/core/store';
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import * as Y3 from 'yjs';
2
- import { ORIGIN_IDS, readOoxmlPart, validateExternalTarget, relsPartNameFor, contentTypesPartBytes, withContentTypeOverride } from '@docx-editor.dev/core/store';
1
+ import * as Y from 'yjs';
2
+ import { ORIGIN_IDS, readOoxmlPart, validateExternalTarget, relsPartNameFor, contentTypesPartBytes, withContentTypeOverride, readXml, XML_NAMESPACE_URI } from '@docx-editor.dev/core/store';
3
3
  import { createCollaborationStatusTracker, safeParticipantColor } from '@docx-editor.dev/core/collaboration';
4
4
  import { historyGroupOfJournal, mapOffsetAcrossText } from '@docx-editor.dev/core/collaboration/replication';
5
5
 
@@ -314,6 +314,92 @@ function writeUnits(text, units) {
314
314
  function isRichParagraph(map) {
315
315
  return map.has("inline");
316
316
  }
317
+ var PACKED = "xml";
318
+ function isPackedElement(map) {
319
+ return map.has(PACKED);
320
+ }
321
+ function isCompact(map) {
322
+ return isRichParagraph(map) || isPackedElement(map);
323
+ }
324
+ var TEXT_BEARING = /* @__PURE__ */ new Set(["p", "t", "delText", "instrText", "delInstrText"]);
325
+ function packable(xml) {
326
+ if (xml.ns === WML && TEXT_BEARING.has(xml.local)) return false;
327
+ return xml.children.every((c) => typeof c === "string" || packable(c));
328
+ }
329
+ function createPacked(xml, scope) {
330
+ const map = new Y.Map();
331
+ map.set(PACKED, serializeXml(xml, scope));
332
+ return map;
333
+ }
334
+ function repack(map, xml) {
335
+ const next = serializeXml(xml, scopeOf(map));
336
+ if (map.get(PACKED) !== next) map.set(PACKED, next);
337
+ }
338
+ function scopeOf(node) {
339
+ const chain = [];
340
+ let parent = node.parent;
341
+ while (parent instanceof Y.Array) {
342
+ const owner = parent.parent;
343
+ if (!(owner instanceof Y.Map)) break;
344
+ chain.push(owner);
345
+ parent = owner.parent;
346
+ }
347
+ const scope = /* @__PURE__ */ new Map();
348
+ for (const el of chain.reverse()) {
349
+ for (const b of el.get("bindings").toArray()) scope.set(b.prefix, b.ns);
350
+ }
351
+ return scope;
352
+ }
353
+ function scopeWithin(el) {
354
+ const scope = scopeOf(el);
355
+ if (!isPackedElement(el)) {
356
+ for (const b of el.get("bindings").toArray()) scope.set(b.prefix, b.ns);
357
+ }
358
+ return scope;
359
+ }
360
+ var unpackLimits = { maxBytes: 64 * 1024 * 1024, maxElements: 2e6 };
361
+ function unpack(text, scope) {
362
+ const read = readXml(text, unpackLimits);
363
+ if (!read.ok) throw new Error(`collab: a packed element is not readable XML (${read.reason})`);
364
+ const convert = (node, outer) => {
365
+ const bindings = [];
366
+ const named = [];
367
+ for (const [name, value] of Object.entries(node.attributes)) {
368
+ if (name === "xmlns") bindings.push({ prefix: "", ns: value });
369
+ else if (name.startsWith("xmlns:")) bindings.push({ prefix: name.slice(6), ns: value });
370
+ else named.push([name, value]);
371
+ }
372
+ const inner = new Map(outer);
373
+ for (const b of bindings) inner.set(b.prefix, b.ns);
374
+ const resolve = (prefix) => {
375
+ if (prefix === "xml") return XML_NAMESPACE_URI;
376
+ const ns = inner.get(prefix);
377
+ if (ns === void 0)
378
+ throw new Error(`collab: prefix ${prefix} is not bound in a packed element`);
379
+ return ns;
380
+ };
381
+ const colon = node.name.indexOf(":");
382
+ const xml = {
383
+ ns: colon < 0 ? inner.get("") ?? "" : resolve(node.name.slice(0, colon)),
384
+ local: colon < 0 ? node.name : node.name.slice(colon + 1),
385
+ attrs: named.map(([name, value]) => {
386
+ const at = name.indexOf(":");
387
+ if (at < 0) return { ns: "", local: name, value };
388
+ const prefix = name.slice(0, at);
389
+ return { ns: resolve(prefix), local: name.slice(at + 1), prefix, value };
390
+ }),
391
+ bindings,
392
+ children: node.children.map(
393
+ (child) => child.type === "text" ? child.value : convert(child, inner)
394
+ )
395
+ };
396
+ if (colon >= 0) xml.prefix = node.name.slice(0, colon);
397
+ return xml;
398
+ };
399
+ const root = read.nodes.find((n) => n.type === "element");
400
+ if (!root || root.type !== "element") throw new Error("collab: a packed element is empty");
401
+ return convert(root, scope);
402
+ }
317
403
  function isParagraphEl(el) {
318
404
  return el.ns === WML && el.local === "p";
319
405
  }
@@ -321,47 +407,53 @@ function fieldsOf(map, xml) {
321
407
  map.set("ns", xml.ns);
322
408
  map.set("local", xml.local);
323
409
  if (xml.prefix !== void 0) map.set("prefix", xml.prefix);
324
- const attrs = new Y3.Array();
410
+ const attrs = new Y.Array();
325
411
  attrs.push(xml.attrs.map((a) => ({ ...a })));
326
412
  map.set("attrs", attrs);
327
- const bindings = new Y3.Array();
413
+ const bindings = new Y.Array();
328
414
  bindings.push(xml.bindings.map((b) => ({ ...b })));
329
415
  map.set("bindings", bindings);
330
416
  }
331
417
  function newText(value) {
332
- const text = new Y3.Text();
418
+ const text = new Y.Text();
333
419
  text.insert(0, value);
334
420
  return text;
335
421
  }
336
- function createRichParagraph(xml, encoded) {
337
- const map = new Y3.Map();
422
+ function createRichParagraph(xml, encoded, scope = /* @__PURE__ */ new Map()) {
423
+ const map = new Y.Map();
338
424
  fieldsOf(map, xml);
339
- const children = new Y3.Array();
340
- children.push(encoded.head.map((el) => xmlToLive(el)));
425
+ const inner = withBindings(scope, xml.bindings);
426
+ const children = new Y.Array();
427
+ children.push(encoded.head.map((el) => xmlToLive(el, inner)));
341
428
  map.set("children", children);
342
- const inline = new Y3.Text();
429
+ const inline = new Y.Text();
343
430
  writeUnits(inline, encoded.units);
344
431
  map.set("inline", inline);
345
432
  return map;
346
433
  }
347
- function xmlToLive(xml) {
434
+ function withBindings(scope, bindings) {
435
+ const inner = new Map(scope);
436
+ for (const b of bindings) inner.set(b.prefix, b.ns);
437
+ return inner;
438
+ }
439
+ function xmlToLive(xml, scope = /* @__PURE__ */ new Map(), root = false) {
348
440
  if (isParagraphEl(xml)) {
349
441
  const encoded = encodeParagraph(xml.children);
350
- if (encoded) return createRichParagraph(xml, encoded);
442
+ if (encoded) return createRichParagraph(xml, encoded, scope);
351
443
  }
352
- return xmlToGenericLive(xml);
353
- }
354
- function xmlToGenericLive(xml) {
355
- const map = new Y3.Map();
444
+ if (!root && packable(xml)) return createPacked(xml, scope);
445
+ const map = new Y.Map();
356
446
  fieldsOf(map, xml);
357
- const children = new Y3.Array();
358
- children.push(xml.children.map((c) => typeof c === "string" ? newText(c) : xmlToLive(c)));
447
+ const inner = withBindings(scope, xml.bindings);
448
+ const children = new Y.Array();
449
+ children.push(xml.children.map((c) => typeof c === "string" ? newText(c) : xmlToLive(c, inner)));
359
450
  map.set("children", children);
360
451
  return map;
361
452
  }
362
453
  function liveToXml(map) {
454
+ if (isPackedElement(map)) return unpack(map.get(PACKED), scopeOf(map));
363
455
  const prefix = map.get("prefix");
364
- const stored = map.get("children").toArray().map((child) => child instanceof Y3.Text ? child.toString() : liveToXml(child));
456
+ const stored = map.get("children").toArray().map((child) => child instanceof Y.Text ? child.toString() : liveToXml(child));
365
457
  const children = isRichParagraph(map) ? [...stored, ...decodeInline(readUnits(map.get("inline")))] : stored;
366
458
  const xml = {
367
459
  ns: map.get("ns"),
@@ -376,14 +468,13 @@ function liveToXml(map) {
376
468
  var escapeText = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
377
469
  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;");
378
470
  var qualified = (prefix, local) => prefix ? `${prefix}:${local}` : local;
379
- function serializeXml(el, scope) {
380
- const inScope = new Map(scope);
381
- for (const b of el.bindings) inScope.set(b.prefix, b.ns);
382
- let out = `<${qualified(el.prefix, el.local)}`;
383
- for (const b of el.bindings) {
471
+ function startTag(prefix, local, bindings, attrs, scope) {
472
+ const inScope = withBindings(scope, bindings);
473
+ let out = `<${qualified(prefix, local)}`;
474
+ for (const b of bindings) {
384
475
  out += b.prefix === "" ? ` xmlns="${escapeAttr(b.ns)}"` : ` xmlns:${b.prefix}="${escapeAttr(b.ns)}"`;
385
476
  }
386
- for (const a of el.attrs) {
477
+ for (const a of attrs) {
387
478
  let p = a.prefix;
388
479
  if (a.ns !== "" && !p) {
389
480
  for (const [candidate, uri] of inScope) {
@@ -395,48 +486,41 @@ function serializeXml(el, scope) {
395
486
  }
396
487
  out += ` ${qualified(p, a.local)}="${escapeAttr(a.value)}"`;
397
488
  }
489
+ return [out, inScope];
490
+ }
491
+ function serializeXml(el, scope) {
492
+ const [out, inScope] = startTag(el.prefix, el.local, el.bindings, el.attrs, scope);
398
493
  if (el.children.length === 0) return `${out}/>`;
399
- out += ">";
494
+ let body = "";
400
495
  for (const child of el.children) {
401
- out += typeof child === "string" ? escapeText(child) : serializeXml(child, inScope);
496
+ body += typeof child === "string" ? escapeText(child) : serializeXml(child, inScope);
402
497
  }
403
- return `${out}</${qualified(el.prefix, el.local)}>`;
498
+ return `${out}>${body}</${qualified(el.prefix, el.local)}>`;
404
499
  }
405
500
  function serializeLive(el, scope) {
406
- if (isRichParagraph(el)) return serializeXml(liveToXml(el), scope);
501
+ if (isPackedElement(el)) return el.get(PACKED);
407
502
  const prefix = el.get("prefix");
408
503
  const local = el.get("local");
409
504
  const bindings = el.get("bindings").toArray();
410
505
  const attrs = el.get("attrs").toArray();
411
506
  const children = el.get("children").toArray();
412
- const inScope = new Map(scope);
413
- for (const b of bindings) inScope.set(b.prefix, b.ns);
414
- let out = `<${qualified(prefix, local)}`;
415
- for (const b of bindings) {
416
- out += b.prefix === "" ? ` xmlns="${escapeAttr(b.ns)}"` : ` xmlns:${b.prefix}="${escapeAttr(b.ns)}"`;
417
- }
418
- for (const a of attrs) {
419
- let p = a.prefix;
420
- if (a.ns !== "" && !p) {
421
- for (const [candidate, uri] of inScope) {
422
- if (candidate !== "" && uri === a.ns) {
423
- p = candidate;
424
- break;
425
- }
426
- }
427
- }
428
- out += ` ${qualified(p, a.local)}="${escapeAttr(a.value)}"`;
429
- }
430
- if (children.length === 0) return `${out}/>`;
431
- out += ">";
507
+ const [out, inScope] = startTag(prefix, local, bindings, attrs, scope);
508
+ const inline = isRichParagraph(el) ? decodeInline(readUnits(el.get("inline"))) : [];
509
+ if (children.length === 0 && inline.length === 0) return `${out}/>`;
510
+ let body = "";
432
511
  for (const child of children) {
433
- out += child instanceof Y3.Text ? escapeText(child.toString()) : serializeLive(child, inScope);
512
+ body += child instanceof Y.Text ? escapeText(child.toString()) : serializeLive(child, inScope);
434
513
  }
435
- return `${out}</${qualified(prefix, local)}>`;
514
+ for (const child of inline) body += serializeXml(child, inScope);
515
+ return `${out}>${body}</${qualified(prefix, local)}>`;
436
516
  }
437
517
 
438
518
  // src/encoding.ts
439
- var COLLAB_FORMAT = "arbi-docx/1";
519
+ var COLLAB_FORMAT = "arbi-docx/2";
520
+ var READABLE_FORMATS = /* @__PURE__ */ new Set(["arbi-docx/1", COLLAB_FORMAT]);
521
+ function isReadableFormat(format) {
522
+ return format !== void 0 && READABLE_FORMATS.has(format);
523
+ }
440
524
  function isBootstrapped(doc) {
441
525
  return doc.getMap("meta").get("format") !== void 0;
442
526
  }
@@ -730,7 +814,7 @@ var NodeRegistry = class {
730
814
  require(id) {
731
815
  let entry = this.entries.get(id) ?? this.resolveInsideParagraph(id);
732
816
  if (!entry) throw new RegistryError(`journal names unknown node ${id}`);
733
- if ("live" in entry && entry.live instanceof Y3.Map && isRichParagraph(entry.live)) {
817
+ if ("live" in entry && entry.live instanceof Y.Map && isCompact(entry.live)) {
734
818
  this.openParagraph(entry.live);
735
819
  entry = this.entries.get(id);
736
820
  }
@@ -748,7 +832,7 @@ var NodeRegistry = class {
748
832
  for (let length = path.length - 1; length >= 1; length--) {
749
833
  const ancestor = this.entries.get(id.slice(0, hash + 1) + path.slice(0, length).join("."));
750
834
  if (!ancestor) continue;
751
- if ("live" in ancestor && ancestor.live instanceof Y3.Map && isRichParagraph(ancestor.live)) {
835
+ if ("live" in ancestor && ancestor.live instanceof Y.Map && isCompact(ancestor.live)) {
752
836
  this.openParagraph(ancestor.live);
753
837
  return this.entries.get(id);
754
838
  }
@@ -780,13 +864,13 @@ var NodeRegistry = class {
780
864
  /**
781
865
  * Walk a mirror root and register every node under its positional id, `${part}#0` for the root and
782
866
  * `${parent}.${index}` below it. This is the id scheme core assigns when it reads a part. A rich
783
- * paragraph is registered as one node; its inner nodes appear when it is opened.
867
+ * paragraph or a packed element is registered as one node; its inner nodes appear when it is opened.
784
868
  */
785
869
  registerTree(partName, root) {
786
870
  const walk = (node, id) => {
787
871
  this.registerLive(id, node);
788
- if (node instanceof Y3.Text) return;
789
- if (isRichParagraph(node)) return;
872
+ if (node instanceof Y.Text) return;
873
+ if (isCompact(node)) return;
790
874
  childrenOf(node).forEach((child, index) => walk(child, `${id}.${index}`));
791
875
  };
792
876
  walk(root, `${partName}#0`);
@@ -843,7 +927,7 @@ var NodeRegistry = class {
843
927
  for (const child of children) this.own(child, owner);
844
928
  if (owner) this.dirty.add(owner);
845
929
  }
846
- /** Write every changed open paragraph back into the mirror. Call at the end of a journal. */
930
+ /** Write every changed open paragraph or packed element back into the mirror. Call at the end of a journal. */
847
931
  flushRich() {
848
932
  for (const live of [...this.dirty]) {
849
933
  this.dirty.delete(live);
@@ -854,6 +938,11 @@ var NodeRegistry = class {
854
938
  writeBack(record) {
855
939
  const { live, root } = record;
856
940
  const xml = plainToXml(root);
941
+ if (isPackedElement(live)) {
942
+ if (packable(xml)) repack(live, xml);
943
+ else this.degrade(record);
944
+ return;
945
+ }
857
946
  const encoded = encodeParagraph(xml.children);
858
947
  if (!encoded) {
859
948
  this.degrade(record);
@@ -870,21 +959,22 @@ var NodeRegistry = class {
870
959
  bindings.push(xml.bindings.map((b) => ({ ...b })));
871
960
  }
872
961
  const head = childrenOf(live);
873
- const stored = head.toArray().map((child) => liveToXml(child));
874
- if (JSON.stringify(stored) !== JSON.stringify(encoded.head)) {
962
+ const scope = scopeWithin(live);
963
+ const stored = head.toArray().map((child) => serializeLive(child, scope)).join("");
964
+ if (stored !== encoded.head.map((el) => serializeXml(el, scope)).join("")) {
875
965
  head.delete(0, head.length);
876
- head.push(encoded.head.map((el) => xmlToLive(el)));
966
+ head.push(encoded.head.map((el) => xmlToLive(el, scope)));
877
967
  }
878
968
  const inline = live.get("inline");
879
969
  applyUnits(inline, readUnits(inline), encoded.units);
880
970
  }
881
- /** The paragraph can no longer be held as rich text: store it as plain elements instead. */
971
+ /** The paragraph can no longer be held as rich text, or the element packed: store it as a tree. */
882
972
  degrade(record) {
883
973
  const parent = record.live.parent;
884
- if (!(parent instanceof Y3.Array))
974
+ if (!(parent instanceof Y.Array))
885
975
  throw new RegistryError("a paragraph outside a parent cannot change form");
886
976
  const index = parent.toArray().indexOf(record.live);
887
- const generic = this.toGenericLive(record.root);
977
+ const generic = this.toGenericLive(record.root, scopeOf(record.live));
888
978
  this.open.delete(record.live);
889
979
  parent.delete(index, 1);
890
980
  parent.insert(index, [generic]);
@@ -899,8 +989,8 @@ var NodeRegistry = class {
899
989
  snapshotLive(node) {
900
990
  const id = this.liveIds.get(node);
901
991
  if (id === void 0) throw new RegistryError("live node has no registered id");
902
- if (node instanceof Y3.Text) return { type: "text", id, value: node.toString() };
903
- if (isRichParagraph(node)) {
992
+ if (node instanceof Y.Text) return { type: "text", id, value: node.toString() };
993
+ if (isCompact(node)) {
904
994
  return this.open.get(node)?.root ?? xmlToPlain(liveToXml(node), id);
905
995
  }
906
996
  const prefix = node.get("prefix");
@@ -928,8 +1018,8 @@ var NodeRegistry = class {
928
1018
  if (id !== void 0 && this.isCurrentLive(id, node)) {
929
1019
  this.entries.set(id, { plain });
930
1020
  }
931
- if (node instanceof Y3.Text || plain.type === "text") return;
932
- if (isRichParagraph(node)) {
1021
+ if (node instanceof Y.Text || plain.type === "text") return;
1022
+ if (isCompact(node)) {
933
1023
  this.open.delete(node);
934
1024
  this.dirty.delete(node);
935
1025
  return;
@@ -937,53 +1027,61 @@ var NodeRegistry = class {
937
1027
  const liveChildren = childrenOf(node).toArray();
938
1028
  liveChildren.forEach((child, index) => this.detachInto(child, plain.children[index]));
939
1029
  }
940
- /** Build Yjs types for a plain subtree and register every node as live. */
941
- toLive(plain) {
1030
+ /**
1031
+ * Build Yjs types for a plain subtree placed where `scope` is in force, and register every node as
1032
+ * live. A rich paragraph or packed element stays open on the plain tree, which is already current.
1033
+ * A part's `root` is never packed.
1034
+ */
1035
+ toLive(plain, scope = /* @__PURE__ */ new Map(), root = false) {
942
1036
  if (plain.type === "text") {
943
- const text = new Y3.Text();
1037
+ const text = new Y.Text();
944
1038
  text.insert(0, plain.value);
945
1039
  this.registerLive(plain.id, text);
946
1040
  return text;
947
1041
  }
1042
+ const xml = plainToXml(plain);
1043
+ let map;
948
1044
  if (isParagraphEl(plain)) {
949
- const xml = plainToXml(plain);
950
1045
  const encoded = encodeParagraph(xml.children);
951
- if (encoded) {
952
- const map = createRichParagraph(xml, encoded);
953
- this.liveIds.set(map, plain.id);
954
- this.registerPlain(plain);
955
- this.own(plain, map);
956
- this.open.set(map, { live: map, root: plain, id: plain.id });
957
- return map;
958
- }
1046
+ if (encoded) map = createRichParagraph(xml, encoded, scope);
1047
+ }
1048
+ if (!map && !root && packable(xml)) map = xmlToLive(xml, scope);
1049
+ if (map) {
1050
+ this.liveIds.set(map, plain.id);
1051
+ this.registerPlain(plain);
1052
+ this.own(plain, map);
1053
+ this.open.set(map, { live: map, root: plain, id: plain.id });
1054
+ return map;
959
1055
  }
960
- return this.toGenericLive(plain);
1056
+ return this.toGenericLive(plain, scope);
961
1057
  }
962
- toGenericLive(plain) {
1058
+ toGenericLive(plain, scope) {
963
1059
  const map = xmlToGenericShell(plain);
964
- const children = new Y3.Array();
965
- children.push(plain.children.map((child) => this.toLive(child)));
1060
+ const inner = withBindings(scope, plain.bindings);
1061
+ const children = new Y.Array();
1062
+ children.push(plain.children.map((child) => this.toLive(child, inner)));
966
1063
  map.set("children", children);
967
1064
  this.registerLive(plain.id, map);
968
1065
  return map;
969
1066
  }
970
1067
  /**
971
- * A live node that can be inserted into a parent. Anything not yet attached is built fresh; an
972
- * attached node is copied, because a Yjs type cannot have two parents.
1068
+ * A live node that can be inserted into a parent (`scope` is in force there), or a part's `root`.
1069
+ * Anything not yet attached is built fresh; an attached node is copied, because a Yjs type cannot
1070
+ * have two parents.
973
1071
  */
974
- attachable(id) {
975
- return this.toLive(this.snapshot(id));
1072
+ attachable(id, scope = /* @__PURE__ */ new Map(), root = false) {
1073
+ return this.toLive(this.snapshot(id), scope, root);
976
1074
  }
977
1075
  };
978
1076
  function xmlToGenericShell(plain) {
979
- const map = new Y3.Map();
1077
+ const map = new Y.Map();
980
1078
  map.set("ns", plain.ns);
981
1079
  map.set("local", plain.local);
982
1080
  if (plain.prefix !== void 0) map.set("prefix", plain.prefix);
983
- const attrs = new Y3.Array();
1081
+ const attrs = new Y.Array();
984
1082
  attrs.push(plain.attrs.map((a) => ({ ...a })));
985
1083
  map.set("attrs", attrs);
986
- const bindings = new Y3.Array();
1084
+ const bindings = new Y.Array();
987
1085
  bindings.push(plain.bindings.map((b) => ({ ...b })));
988
1086
  map.set("bindings", bindings);
989
1087
  return map;
@@ -1048,7 +1146,7 @@ function setNamespaceBinding(registry, id, prefix, uri) {
1048
1146
  }
1049
1147
  }
1050
1148
  function asLiveElement(node, id) {
1051
- if (node instanceof Y3.Text) throw new JournalError(`${id} is a text node, not an element`);
1149
+ if (node instanceof Y.Text) throw new JournalError(`${id} is a text node, not an element`);
1052
1150
  return node;
1053
1151
  }
1054
1152
  function asPlainElement(node, id) {
@@ -1064,7 +1162,7 @@ function spliceText(registry, id, start, deleteCount, insert) {
1064
1162
  return;
1065
1163
  }
1066
1164
  const text = entry.live;
1067
- if (!(text instanceof Y3.Text)) throw new JournalError(`${id} is not a text node`);
1165
+ if (!(text instanceof Y.Text)) throw new JournalError(`${id} is not a text node`);
1068
1166
  if (start < 0 || start + deleteCount > text.length) {
1069
1167
  throw new JournalError(`text splice out of range on ${id}`);
1070
1168
  }
@@ -1077,27 +1175,29 @@ function detachRemoved(registry, parent, start, count) {
1077
1175
  function spliceChildren(registry, parentId, start, deleteCount, childIds) {
1078
1176
  const parentEntry = registry.require(parentId);
1079
1177
  if ("plain" in parentEntry) {
1080
- const parent = asPlainElement(parentEntry.plain, parentId);
1081
- if (start < 0 || start + deleteCount > parent.children.length) {
1178
+ const parent2 = asPlainElement(parentEntry.plain, parentId);
1179
+ if (start < 0 || start + deleteCount > parent2.children.length) {
1082
1180
  throw new JournalError(`child splice out of range on ${parentId}`);
1083
1181
  }
1084
1182
  const inserted2 = childIds.map((id) => registry.snapshot(id));
1085
- parent.children.splice(start, deleteCount, ...inserted2);
1086
- registry.adopt(parent, inserted2);
1183
+ parent2.children.splice(start, deleteCount, ...inserted2);
1184
+ registry.adopt(parent2, inserted2);
1087
1185
  return;
1088
1186
  }
1089
- const children = childrenOf(asLiveElement(parentEntry.live, parentId));
1187
+ const parent = asLiveElement(parentEntry.live, parentId);
1188
+ const children = childrenOf(parent);
1090
1189
  if (start < 0 || start + deleteCount > children.length) {
1091
1190
  throw new JournalError(`child splice out of range on ${parentId}`);
1092
1191
  }
1093
1192
  detachRemoved(registry, children, start, deleteCount);
1094
- const inserted = childIds.map((id) => registry.attachable(id));
1193
+ const scope = scopeWithin(parent);
1194
+ const inserted = childIds.map((id) => registry.attachable(id, scope));
1095
1195
  if (deleteCount > 0) children.delete(start, deleteCount);
1096
1196
  if (inserted.length > 0) children.insert(start, inserted);
1097
1197
  }
1098
1198
  function locate(registry, id, node) {
1099
1199
  const children = node.parent;
1100
- if (!(children instanceof Y3.Array)) throw new JournalError(`${id} is not attached`);
1200
+ if (!(children instanceof Y.Array)) throw new JournalError(`${id} is not attached`);
1101
1201
  const index = children.toArray().indexOf(node);
1102
1202
  if (index < 0) throw new JournalError(`${id} is not in its parent`);
1103
1203
  return { children, index };
@@ -1124,8 +1224,10 @@ function moveNode(registry, id, destinationId, destinationIndex) {
1124
1224
  registry.adopt(destination2, [copy]);
1125
1225
  return;
1126
1226
  }
1127
- const destination = childrenOf(asLiveElement(destinationEntry.live, destinationId));
1128
- destination.insert(destinationIndex, [registry.toLive(copy)]);
1227
+ const destination = asLiveElement(destinationEntry.live, destinationId);
1228
+ childrenOf(destination).insert(destinationIndex, [
1229
+ registry.toLive(copy, scopeWithin(destination))
1230
+ ]);
1129
1231
  }
1130
1232
  function renameNode(registry, id, qname) {
1131
1233
  const entry = registry.require(id);
@@ -1140,7 +1242,7 @@ function renameNode(registry, id, qname) {
1140
1242
  return true;
1141
1243
  }
1142
1244
  const live = entry.live;
1143
- if (live instanceof Y3.Text || isRichParagraph(live)) return false;
1245
+ if (live instanceof Y.Text || isCompact(live)) return false;
1144
1246
  if (live.get("ns") !== qname.namespaceUri) live.set("ns", qname.namespaceUri);
1145
1247
  if (live.get("local") !== qname.localName) live.set("local", qname.localName);
1146
1248
  if (qname.prefix === void 0) {
@@ -1170,7 +1272,7 @@ function putNode(registry, effect) {
1170
1272
  }
1171
1273
  function rootFor(registry, id) {
1172
1274
  const entry = registry.require(id);
1173
- const live = "live" in entry && entry.live.parent === null ? entry.live : registry.attachable(id);
1275
+ const live = "live" in entry && entry.live.parent === null ? entry.live : registry.attachable(id, /* @__PURE__ */ new Map(), true);
1174
1276
  return asLiveElement(live, id);
1175
1277
  }
1176
1278
  function applyEffect(doc, registry, effect, context) {
@@ -1214,7 +1316,7 @@ function applyEffect(doc, registry, effect, context) {
1214
1316
  const rels = doc.getMap("rels");
1215
1317
  let byId = rels.get(effect.owner);
1216
1318
  if (!byId) {
1217
- byId = new Y3.Map();
1319
+ byId = new Y.Map();
1218
1320
  rels.set(effect.owner, byId);
1219
1321
  }
1220
1322
  byId.set(effect.record.id, { ...effect.record });
@@ -1419,7 +1521,7 @@ var DocxCollaborationSession = class {
1419
1521
  this.doc = options.doc;
1420
1522
  this.awareness = options.awareness;
1421
1523
  this.offlineEditing = options.offlineEditing ?? false;
1422
- this.undoManager = new Y3.UndoManager(
1524
+ this.undoManager = new Y.UndoManager(
1423
1525
  [
1424
1526
  this.doc.getMap("parts"),
1425
1527
  this.doc.getMap("rels"),
@@ -1459,7 +1561,7 @@ var DocxCollaborationSession = class {
1459
1561
  this.setStatus("error", "not-initialized");
1460
1562
  return;
1461
1563
  }
1462
- if (readFormat(this.doc) !== COLLAB_FORMAT) {
1564
+ if (!isReadableFormat(readFormat(this.doc))) {
1463
1565
  this.setStatus("error", "collaboration-format-mismatch", readFormat(this.doc));
1464
1566
  return;
1465
1567
  }
@@ -1733,7 +1835,7 @@ function resolveAddress(port, address) {
1733
1835
  };
1734
1836
  }
1735
1837
  function vectorKey(doc) {
1736
- return Array.from(Y3.encodeStateVector(doc)).join(",");
1838
+ return Array.from(Y.encodeStateVector(doc)).join(",");
1737
1839
  }
1738
1840
  function randomToken() {
1739
1841
  if (typeof crypto.randomUUID === "function") return crypto.randomUUID();