@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/encoding.cjs +54 -56
- package/dist/encoding.cjs.map +1 -1
- package/dist/encoding.d.cts +50 -14
- package/dist/encoding.d.ts +50 -14
- package/dist/encoding.js +54 -57
- package/dist/encoding.js.map +1 -1
- package/dist/hocuspocus.cjs +211 -109
- package/dist/hocuspocus.cjs.map +1 -1
- package/dist/hocuspocus.js +211 -109
- package/dist/hocuspocus.js.map +1 -1
- package/dist/index.cjs +210 -108
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +210 -108
- package/dist/index.js.map +1 -1
- package/dist/server.cjs +214 -112
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +214 -112
- package/dist/server.js.map +1 -1
- package/dist/template.cjs +3 -2
- package/dist/template.cjs.map +1 -1
- package/dist/template.d.cts +5 -0
- package/dist/template.d.ts +5 -0
- package/dist/template.js +3 -2
- package/dist/template.js.map +1 -1
- package/dist/{versions-DXiFQMA6.d.cts → versions-XSYTVmOU.d.cts} +1 -1
- package/dist/{versions-DXiFQMA6.d.ts → versions-XSYTVmOU.d.ts} +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var Y = require('yjs');
|
|
4
4
|
var store = require('@docx-editor.dev/core/store');
|
|
5
5
|
var collaboration = require('@docx-editor.dev/core/collaboration');
|
|
6
6
|
var replication = require('@docx-editor.dev/core/collaboration/replication');
|
|
@@ -23,7 +23,7 @@ function _interopNamespace(e) {
|
|
|
23
23
|
return Object.freeze(n);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
var
|
|
26
|
+
var Y__namespace = /*#__PURE__*/_interopNamespace(Y);
|
|
27
27
|
|
|
28
28
|
// src/encoding.ts
|
|
29
29
|
|
|
@@ -336,6 +336,92 @@ function writeUnits(text, units) {
|
|
|
336
336
|
function isRichParagraph(map) {
|
|
337
337
|
return map.has("inline");
|
|
338
338
|
}
|
|
339
|
+
var PACKED = "xml";
|
|
340
|
+
function isPackedElement(map) {
|
|
341
|
+
return map.has(PACKED);
|
|
342
|
+
}
|
|
343
|
+
function isCompact(map) {
|
|
344
|
+
return isRichParagraph(map) || isPackedElement(map);
|
|
345
|
+
}
|
|
346
|
+
var TEXT_BEARING = /* @__PURE__ */ new Set(["p", "t", "delText", "instrText", "delInstrText"]);
|
|
347
|
+
function packable(xml) {
|
|
348
|
+
if (xml.ns === WML && TEXT_BEARING.has(xml.local)) return false;
|
|
349
|
+
return xml.children.every((c) => typeof c === "string" || packable(c));
|
|
350
|
+
}
|
|
351
|
+
function createPacked(xml, scope) {
|
|
352
|
+
const map = new Y__namespace.Map();
|
|
353
|
+
map.set(PACKED, serializeXml(xml, scope));
|
|
354
|
+
return map;
|
|
355
|
+
}
|
|
356
|
+
function repack(map, xml) {
|
|
357
|
+
const next = serializeXml(xml, scopeOf(map));
|
|
358
|
+
if (map.get(PACKED) !== next) map.set(PACKED, next);
|
|
359
|
+
}
|
|
360
|
+
function scopeOf(node) {
|
|
361
|
+
const chain = [];
|
|
362
|
+
let parent = node.parent;
|
|
363
|
+
while (parent instanceof Y__namespace.Array) {
|
|
364
|
+
const owner = parent.parent;
|
|
365
|
+
if (!(owner instanceof Y__namespace.Map)) break;
|
|
366
|
+
chain.push(owner);
|
|
367
|
+
parent = owner.parent;
|
|
368
|
+
}
|
|
369
|
+
const scope = /* @__PURE__ */ new Map();
|
|
370
|
+
for (const el of chain.reverse()) {
|
|
371
|
+
for (const b of el.get("bindings").toArray()) scope.set(b.prefix, b.ns);
|
|
372
|
+
}
|
|
373
|
+
return scope;
|
|
374
|
+
}
|
|
375
|
+
function scopeWithin(el) {
|
|
376
|
+
const scope = scopeOf(el);
|
|
377
|
+
if (!isPackedElement(el)) {
|
|
378
|
+
for (const b of el.get("bindings").toArray()) scope.set(b.prefix, b.ns);
|
|
379
|
+
}
|
|
380
|
+
return scope;
|
|
381
|
+
}
|
|
382
|
+
var unpackLimits = { maxBytes: 64 * 1024 * 1024, maxElements: 2e6 };
|
|
383
|
+
function unpack(text, scope) {
|
|
384
|
+
const read = store.readXml(text, unpackLimits);
|
|
385
|
+
if (!read.ok) throw new Error(`collab: a packed element is not readable XML (${read.reason})`);
|
|
386
|
+
const convert = (node, outer) => {
|
|
387
|
+
const bindings = [];
|
|
388
|
+
const named = [];
|
|
389
|
+
for (const [name, value] of Object.entries(node.attributes)) {
|
|
390
|
+
if (name === "xmlns") bindings.push({ prefix: "", ns: value });
|
|
391
|
+
else if (name.startsWith("xmlns:")) bindings.push({ prefix: name.slice(6), ns: value });
|
|
392
|
+
else named.push([name, value]);
|
|
393
|
+
}
|
|
394
|
+
const inner = new Map(outer);
|
|
395
|
+
for (const b of bindings) inner.set(b.prefix, b.ns);
|
|
396
|
+
const resolve = (prefix) => {
|
|
397
|
+
if (prefix === "xml") return store.XML_NAMESPACE_URI;
|
|
398
|
+
const ns = inner.get(prefix);
|
|
399
|
+
if (ns === void 0)
|
|
400
|
+
throw new Error(`collab: prefix ${prefix} is not bound in a packed element`);
|
|
401
|
+
return ns;
|
|
402
|
+
};
|
|
403
|
+
const colon = node.name.indexOf(":");
|
|
404
|
+
const xml = {
|
|
405
|
+
ns: colon < 0 ? inner.get("") ?? "" : resolve(node.name.slice(0, colon)),
|
|
406
|
+
local: colon < 0 ? node.name : node.name.slice(colon + 1),
|
|
407
|
+
attrs: named.map(([name, value]) => {
|
|
408
|
+
const at = name.indexOf(":");
|
|
409
|
+
if (at < 0) return { ns: "", local: name, value };
|
|
410
|
+
const prefix = name.slice(0, at);
|
|
411
|
+
return { ns: resolve(prefix), local: name.slice(at + 1), prefix, value };
|
|
412
|
+
}),
|
|
413
|
+
bindings,
|
|
414
|
+
children: node.children.map(
|
|
415
|
+
(child) => child.type === "text" ? child.value : convert(child, inner)
|
|
416
|
+
)
|
|
417
|
+
};
|
|
418
|
+
if (colon >= 0) xml.prefix = node.name.slice(0, colon);
|
|
419
|
+
return xml;
|
|
420
|
+
};
|
|
421
|
+
const root = read.nodes.find((n) => n.type === "element");
|
|
422
|
+
if (!root || root.type !== "element") throw new Error("collab: a packed element is empty");
|
|
423
|
+
return convert(root, scope);
|
|
424
|
+
}
|
|
339
425
|
function isParagraphEl(el) {
|
|
340
426
|
return el.ns === WML && el.local === "p";
|
|
341
427
|
}
|
|
@@ -343,47 +429,53 @@ function fieldsOf(map, xml) {
|
|
|
343
429
|
map.set("ns", xml.ns);
|
|
344
430
|
map.set("local", xml.local);
|
|
345
431
|
if (xml.prefix !== void 0) map.set("prefix", xml.prefix);
|
|
346
|
-
const attrs = new
|
|
432
|
+
const attrs = new Y__namespace.Array();
|
|
347
433
|
attrs.push(xml.attrs.map((a) => ({ ...a })));
|
|
348
434
|
map.set("attrs", attrs);
|
|
349
|
-
const bindings = new
|
|
435
|
+
const bindings = new Y__namespace.Array();
|
|
350
436
|
bindings.push(xml.bindings.map((b) => ({ ...b })));
|
|
351
437
|
map.set("bindings", bindings);
|
|
352
438
|
}
|
|
353
439
|
function newText(value) {
|
|
354
|
-
const text = new
|
|
440
|
+
const text = new Y__namespace.Text();
|
|
355
441
|
text.insert(0, value);
|
|
356
442
|
return text;
|
|
357
443
|
}
|
|
358
|
-
function createRichParagraph(xml, encoded) {
|
|
359
|
-
const map = new
|
|
444
|
+
function createRichParagraph(xml, encoded, scope = /* @__PURE__ */ new Map()) {
|
|
445
|
+
const map = new Y__namespace.Map();
|
|
360
446
|
fieldsOf(map, xml);
|
|
361
|
-
const
|
|
362
|
-
children
|
|
447
|
+
const inner = withBindings(scope, xml.bindings);
|
|
448
|
+
const children = new Y__namespace.Array();
|
|
449
|
+
children.push(encoded.head.map((el) => xmlToLive(el, inner)));
|
|
363
450
|
map.set("children", children);
|
|
364
|
-
const inline = new
|
|
451
|
+
const inline = new Y__namespace.Text();
|
|
365
452
|
writeUnits(inline, encoded.units);
|
|
366
453
|
map.set("inline", inline);
|
|
367
454
|
return map;
|
|
368
455
|
}
|
|
369
|
-
function
|
|
456
|
+
function withBindings(scope, bindings) {
|
|
457
|
+
const inner = new Map(scope);
|
|
458
|
+
for (const b of bindings) inner.set(b.prefix, b.ns);
|
|
459
|
+
return inner;
|
|
460
|
+
}
|
|
461
|
+
function xmlToLive(xml, scope = /* @__PURE__ */ new Map(), root = false) {
|
|
370
462
|
if (isParagraphEl(xml)) {
|
|
371
463
|
const encoded = encodeParagraph(xml.children);
|
|
372
|
-
if (encoded) return createRichParagraph(xml, encoded);
|
|
464
|
+
if (encoded) return createRichParagraph(xml, encoded, scope);
|
|
373
465
|
}
|
|
374
|
-
return
|
|
375
|
-
|
|
376
|
-
function xmlToGenericLive(xml) {
|
|
377
|
-
const map = new Y3__namespace.Map();
|
|
466
|
+
if (!root && packable(xml)) return createPacked(xml, scope);
|
|
467
|
+
const map = new Y__namespace.Map();
|
|
378
468
|
fieldsOf(map, xml);
|
|
379
|
-
const
|
|
380
|
-
children
|
|
469
|
+
const inner = withBindings(scope, xml.bindings);
|
|
470
|
+
const children = new Y__namespace.Array();
|
|
471
|
+
children.push(xml.children.map((c) => typeof c === "string" ? newText(c) : xmlToLive(c, inner)));
|
|
381
472
|
map.set("children", children);
|
|
382
473
|
return map;
|
|
383
474
|
}
|
|
384
475
|
function liveToXml(map) {
|
|
476
|
+
if (isPackedElement(map)) return unpack(map.get(PACKED), scopeOf(map));
|
|
385
477
|
const prefix = map.get("prefix");
|
|
386
|
-
const stored = map.get("children").toArray().map((child) => child instanceof
|
|
478
|
+
const stored = map.get("children").toArray().map((child) => child instanceof Y__namespace.Text ? child.toString() : liveToXml(child));
|
|
387
479
|
const children = isRichParagraph(map) ? [...stored, ...decodeInline(readUnits(map.get("inline")))] : stored;
|
|
388
480
|
const xml = {
|
|
389
481
|
ns: map.get("ns"),
|
|
@@ -398,14 +490,13 @@ function liveToXml(map) {
|
|
|
398
490
|
var escapeText = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
399
491
|
var escapeAttr = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/\t/g, "	").replace(/\n/g, " ").replace(/\r/g, " ");
|
|
400
492
|
var qualified = (prefix, local) => prefix ? `${prefix}:${local}` : local;
|
|
401
|
-
function
|
|
402
|
-
const inScope =
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
for (const b of el.bindings) {
|
|
493
|
+
function startTag(prefix, local, bindings, attrs, scope) {
|
|
494
|
+
const inScope = withBindings(scope, bindings);
|
|
495
|
+
let out = `<${qualified(prefix, local)}`;
|
|
496
|
+
for (const b of bindings) {
|
|
406
497
|
out += b.prefix === "" ? ` xmlns="${escapeAttr(b.ns)}"` : ` xmlns:${b.prefix}="${escapeAttr(b.ns)}"`;
|
|
407
498
|
}
|
|
408
|
-
for (const a of
|
|
499
|
+
for (const a of attrs) {
|
|
409
500
|
let p = a.prefix;
|
|
410
501
|
if (a.ns !== "" && !p) {
|
|
411
502
|
for (const [candidate, uri] of inScope) {
|
|
@@ -417,48 +508,41 @@ function serializeXml(el, scope) {
|
|
|
417
508
|
}
|
|
418
509
|
out += ` ${qualified(p, a.local)}="${escapeAttr(a.value)}"`;
|
|
419
510
|
}
|
|
511
|
+
return [out, inScope];
|
|
512
|
+
}
|
|
513
|
+
function serializeXml(el, scope) {
|
|
514
|
+
const [out, inScope] = startTag(el.prefix, el.local, el.bindings, el.attrs, scope);
|
|
420
515
|
if (el.children.length === 0) return `${out}/>`;
|
|
421
|
-
|
|
516
|
+
let body = "";
|
|
422
517
|
for (const child of el.children) {
|
|
423
|
-
|
|
518
|
+
body += typeof child === "string" ? escapeText(child) : serializeXml(child, inScope);
|
|
424
519
|
}
|
|
425
|
-
return `${out}</${qualified(el.prefix, el.local)}>`;
|
|
520
|
+
return `${out}>${body}</${qualified(el.prefix, el.local)}>`;
|
|
426
521
|
}
|
|
427
522
|
function serializeLive(el, scope) {
|
|
428
|
-
if (
|
|
523
|
+
if (isPackedElement(el)) return el.get(PACKED);
|
|
429
524
|
const prefix = el.get("prefix");
|
|
430
525
|
const local = el.get("local");
|
|
431
526
|
const bindings = el.get("bindings").toArray();
|
|
432
527
|
const attrs = el.get("attrs").toArray();
|
|
433
528
|
const children = el.get("children").toArray();
|
|
434
|
-
const inScope =
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
out += b.prefix === "" ? ` xmlns="${escapeAttr(b.ns)}"` : ` xmlns:${b.prefix}="${escapeAttr(b.ns)}"`;
|
|
439
|
-
}
|
|
440
|
-
for (const a of attrs) {
|
|
441
|
-
let p = a.prefix;
|
|
442
|
-
if (a.ns !== "" && !p) {
|
|
443
|
-
for (const [candidate, uri] of inScope) {
|
|
444
|
-
if (candidate !== "" && uri === a.ns) {
|
|
445
|
-
p = candidate;
|
|
446
|
-
break;
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
out += ` ${qualified(p, a.local)}="${escapeAttr(a.value)}"`;
|
|
451
|
-
}
|
|
452
|
-
if (children.length === 0) return `${out}/>`;
|
|
453
|
-
out += ">";
|
|
529
|
+
const [out, inScope] = startTag(prefix, local, bindings, attrs, scope);
|
|
530
|
+
const inline = isRichParagraph(el) ? decodeInline(readUnits(el.get("inline"))) : [];
|
|
531
|
+
if (children.length === 0 && inline.length === 0) return `${out}/>`;
|
|
532
|
+
let body = "";
|
|
454
533
|
for (const child of children) {
|
|
455
|
-
|
|
534
|
+
body += child instanceof Y__namespace.Text ? escapeText(child.toString()) : serializeLive(child, inScope);
|
|
456
535
|
}
|
|
457
|
-
|
|
536
|
+
for (const child of inline) body += serializeXml(child, inScope);
|
|
537
|
+
return `${out}>${body}</${qualified(prefix, local)}>`;
|
|
458
538
|
}
|
|
459
539
|
|
|
460
540
|
// src/encoding.ts
|
|
461
|
-
var COLLAB_FORMAT = "arbi-docx/
|
|
541
|
+
var COLLAB_FORMAT = "arbi-docx/2";
|
|
542
|
+
var READABLE_FORMATS = /* @__PURE__ */ new Set(["arbi-docx/1", COLLAB_FORMAT]);
|
|
543
|
+
function isReadableFormat(format) {
|
|
544
|
+
return format !== void 0 && READABLE_FORMATS.has(format);
|
|
545
|
+
}
|
|
462
546
|
function isBootstrapped(doc) {
|
|
463
547
|
return doc.getMap("meta").get("format") !== void 0;
|
|
464
548
|
}
|
|
@@ -752,7 +836,7 @@ var NodeRegistry = class {
|
|
|
752
836
|
require(id) {
|
|
753
837
|
let entry = this.entries.get(id) ?? this.resolveInsideParagraph(id);
|
|
754
838
|
if (!entry) throw new RegistryError(`journal names unknown node ${id}`);
|
|
755
|
-
if ("live" in entry && entry.live instanceof
|
|
839
|
+
if ("live" in entry && entry.live instanceof Y__namespace.Map && isCompact(entry.live)) {
|
|
756
840
|
this.openParagraph(entry.live);
|
|
757
841
|
entry = this.entries.get(id);
|
|
758
842
|
}
|
|
@@ -770,7 +854,7 @@ var NodeRegistry = class {
|
|
|
770
854
|
for (let length = path.length - 1; length >= 1; length--) {
|
|
771
855
|
const ancestor = this.entries.get(id.slice(0, hash + 1) + path.slice(0, length).join("."));
|
|
772
856
|
if (!ancestor) continue;
|
|
773
|
-
if ("live" in ancestor && ancestor.live instanceof
|
|
857
|
+
if ("live" in ancestor && ancestor.live instanceof Y__namespace.Map && isCompact(ancestor.live)) {
|
|
774
858
|
this.openParagraph(ancestor.live);
|
|
775
859
|
return this.entries.get(id);
|
|
776
860
|
}
|
|
@@ -802,13 +886,13 @@ var NodeRegistry = class {
|
|
|
802
886
|
/**
|
|
803
887
|
* Walk a mirror root and register every node under its positional id, `${part}#0` for the root and
|
|
804
888
|
* `${parent}.${index}` below it. This is the id scheme core assigns when it reads a part. A rich
|
|
805
|
-
* paragraph is registered as one node; its inner nodes appear when it is opened.
|
|
889
|
+
* paragraph or a packed element is registered as one node; its inner nodes appear when it is opened.
|
|
806
890
|
*/
|
|
807
891
|
registerTree(partName, root) {
|
|
808
892
|
const walk = (node, id) => {
|
|
809
893
|
this.registerLive(id, node);
|
|
810
|
-
if (node instanceof
|
|
811
|
-
if (
|
|
894
|
+
if (node instanceof Y__namespace.Text) return;
|
|
895
|
+
if (isCompact(node)) return;
|
|
812
896
|
childrenOf(node).forEach((child, index) => walk(child, `${id}.${index}`));
|
|
813
897
|
};
|
|
814
898
|
walk(root, `${partName}#0`);
|
|
@@ -865,7 +949,7 @@ var NodeRegistry = class {
|
|
|
865
949
|
for (const child of children) this.own(child, owner);
|
|
866
950
|
if (owner) this.dirty.add(owner);
|
|
867
951
|
}
|
|
868
|
-
/** Write every changed open paragraph back into the mirror. Call at the end of a journal. */
|
|
952
|
+
/** Write every changed open paragraph or packed element back into the mirror. Call at the end of a journal. */
|
|
869
953
|
flushRich() {
|
|
870
954
|
for (const live of [...this.dirty]) {
|
|
871
955
|
this.dirty.delete(live);
|
|
@@ -876,6 +960,11 @@ var NodeRegistry = class {
|
|
|
876
960
|
writeBack(record) {
|
|
877
961
|
const { live, root } = record;
|
|
878
962
|
const xml = plainToXml(root);
|
|
963
|
+
if (isPackedElement(live)) {
|
|
964
|
+
if (packable(xml)) repack(live, xml);
|
|
965
|
+
else this.degrade(record);
|
|
966
|
+
return;
|
|
967
|
+
}
|
|
879
968
|
const encoded = encodeParagraph(xml.children);
|
|
880
969
|
if (!encoded) {
|
|
881
970
|
this.degrade(record);
|
|
@@ -892,21 +981,22 @@ var NodeRegistry = class {
|
|
|
892
981
|
bindings.push(xml.bindings.map((b) => ({ ...b })));
|
|
893
982
|
}
|
|
894
983
|
const head = childrenOf(live);
|
|
895
|
-
const
|
|
896
|
-
|
|
984
|
+
const scope = scopeWithin(live);
|
|
985
|
+
const stored = head.toArray().map((child) => serializeLive(child, scope)).join("");
|
|
986
|
+
if (stored !== encoded.head.map((el) => serializeXml(el, scope)).join("")) {
|
|
897
987
|
head.delete(0, head.length);
|
|
898
|
-
head.push(encoded.head.map((el) => xmlToLive(el)));
|
|
988
|
+
head.push(encoded.head.map((el) => xmlToLive(el, scope)));
|
|
899
989
|
}
|
|
900
990
|
const inline = live.get("inline");
|
|
901
991
|
applyUnits(inline, readUnits(inline), encoded.units);
|
|
902
992
|
}
|
|
903
|
-
/** The paragraph can no longer be held as rich text: store it as
|
|
993
|
+
/** The paragraph can no longer be held as rich text, or the element packed: store it as a tree. */
|
|
904
994
|
degrade(record) {
|
|
905
995
|
const parent = record.live.parent;
|
|
906
|
-
if (!(parent instanceof
|
|
996
|
+
if (!(parent instanceof Y__namespace.Array))
|
|
907
997
|
throw new RegistryError("a paragraph outside a parent cannot change form");
|
|
908
998
|
const index = parent.toArray().indexOf(record.live);
|
|
909
|
-
const generic = this.toGenericLive(record.root);
|
|
999
|
+
const generic = this.toGenericLive(record.root, scopeOf(record.live));
|
|
910
1000
|
this.open.delete(record.live);
|
|
911
1001
|
parent.delete(index, 1);
|
|
912
1002
|
parent.insert(index, [generic]);
|
|
@@ -921,8 +1011,8 @@ var NodeRegistry = class {
|
|
|
921
1011
|
snapshotLive(node) {
|
|
922
1012
|
const id = this.liveIds.get(node);
|
|
923
1013
|
if (id === void 0) throw new RegistryError("live node has no registered id");
|
|
924
|
-
if (node instanceof
|
|
925
|
-
if (
|
|
1014
|
+
if (node instanceof Y__namespace.Text) return { type: "text", id, value: node.toString() };
|
|
1015
|
+
if (isCompact(node)) {
|
|
926
1016
|
return this.open.get(node)?.root ?? xmlToPlain(liveToXml(node), id);
|
|
927
1017
|
}
|
|
928
1018
|
const prefix = node.get("prefix");
|
|
@@ -950,8 +1040,8 @@ var NodeRegistry = class {
|
|
|
950
1040
|
if (id !== void 0 && this.isCurrentLive(id, node)) {
|
|
951
1041
|
this.entries.set(id, { plain });
|
|
952
1042
|
}
|
|
953
|
-
if (node instanceof
|
|
954
|
-
if (
|
|
1043
|
+
if (node instanceof Y__namespace.Text || plain.type === "text") return;
|
|
1044
|
+
if (isCompact(node)) {
|
|
955
1045
|
this.open.delete(node);
|
|
956
1046
|
this.dirty.delete(node);
|
|
957
1047
|
return;
|
|
@@ -959,53 +1049,61 @@ var NodeRegistry = class {
|
|
|
959
1049
|
const liveChildren = childrenOf(node).toArray();
|
|
960
1050
|
liveChildren.forEach((child, index) => this.detachInto(child, plain.children[index]));
|
|
961
1051
|
}
|
|
962
|
-
/**
|
|
963
|
-
|
|
1052
|
+
/**
|
|
1053
|
+
* Build Yjs types for a plain subtree placed where `scope` is in force, and register every node as
|
|
1054
|
+
* live. A rich paragraph or packed element stays open on the plain tree, which is already current.
|
|
1055
|
+
* A part's `root` is never packed.
|
|
1056
|
+
*/
|
|
1057
|
+
toLive(plain, scope = /* @__PURE__ */ new Map(), root = false) {
|
|
964
1058
|
if (plain.type === "text") {
|
|
965
|
-
const text = new
|
|
1059
|
+
const text = new Y__namespace.Text();
|
|
966
1060
|
text.insert(0, plain.value);
|
|
967
1061
|
this.registerLive(plain.id, text);
|
|
968
1062
|
return text;
|
|
969
1063
|
}
|
|
1064
|
+
const xml = plainToXml(plain);
|
|
1065
|
+
let map;
|
|
970
1066
|
if (isParagraphEl(plain)) {
|
|
971
|
-
const xml = plainToXml(plain);
|
|
972
1067
|
const encoded = encodeParagraph(xml.children);
|
|
973
|
-
if (encoded)
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
}
|
|
1068
|
+
if (encoded) map = createRichParagraph(xml, encoded, scope);
|
|
1069
|
+
}
|
|
1070
|
+
if (!map && !root && packable(xml)) map = xmlToLive(xml, scope);
|
|
1071
|
+
if (map) {
|
|
1072
|
+
this.liveIds.set(map, plain.id);
|
|
1073
|
+
this.registerPlain(plain);
|
|
1074
|
+
this.own(plain, map);
|
|
1075
|
+
this.open.set(map, { live: map, root: plain, id: plain.id });
|
|
1076
|
+
return map;
|
|
981
1077
|
}
|
|
982
|
-
return this.toGenericLive(plain);
|
|
1078
|
+
return this.toGenericLive(plain, scope);
|
|
983
1079
|
}
|
|
984
|
-
toGenericLive(plain) {
|
|
1080
|
+
toGenericLive(plain, scope) {
|
|
985
1081
|
const map = xmlToGenericShell(plain);
|
|
986
|
-
const
|
|
987
|
-
children
|
|
1082
|
+
const inner = withBindings(scope, plain.bindings);
|
|
1083
|
+
const children = new Y__namespace.Array();
|
|
1084
|
+
children.push(plain.children.map((child) => this.toLive(child, inner)));
|
|
988
1085
|
map.set("children", children);
|
|
989
1086
|
this.registerLive(plain.id, map);
|
|
990
1087
|
return map;
|
|
991
1088
|
}
|
|
992
1089
|
/**
|
|
993
|
-
* A live node that can be inserted into a parent
|
|
994
|
-
* attached node is copied, because a Yjs type cannot
|
|
1090
|
+
* A live node that can be inserted into a parent (`scope` is in force there), or a part's `root`.
|
|
1091
|
+
* Anything not yet attached is built fresh; an attached node is copied, because a Yjs type cannot
|
|
1092
|
+
* have two parents.
|
|
995
1093
|
*/
|
|
996
|
-
attachable(id) {
|
|
997
|
-
return this.toLive(this.snapshot(id));
|
|
1094
|
+
attachable(id, scope = /* @__PURE__ */ new Map(), root = false) {
|
|
1095
|
+
return this.toLive(this.snapshot(id), scope, root);
|
|
998
1096
|
}
|
|
999
1097
|
};
|
|
1000
1098
|
function xmlToGenericShell(plain) {
|
|
1001
|
-
const map = new
|
|
1099
|
+
const map = new Y__namespace.Map();
|
|
1002
1100
|
map.set("ns", plain.ns);
|
|
1003
1101
|
map.set("local", plain.local);
|
|
1004
1102
|
if (plain.prefix !== void 0) map.set("prefix", plain.prefix);
|
|
1005
|
-
const attrs = new
|
|
1103
|
+
const attrs = new Y__namespace.Array();
|
|
1006
1104
|
attrs.push(plain.attrs.map((a) => ({ ...a })));
|
|
1007
1105
|
map.set("attrs", attrs);
|
|
1008
|
-
const bindings = new
|
|
1106
|
+
const bindings = new Y__namespace.Array();
|
|
1009
1107
|
bindings.push(plain.bindings.map((b) => ({ ...b })));
|
|
1010
1108
|
map.set("bindings", bindings);
|
|
1011
1109
|
return map;
|
|
@@ -1070,7 +1168,7 @@ function setNamespaceBinding(registry, id, prefix, uri) {
|
|
|
1070
1168
|
}
|
|
1071
1169
|
}
|
|
1072
1170
|
function asLiveElement(node, id) {
|
|
1073
|
-
if (node instanceof
|
|
1171
|
+
if (node instanceof Y__namespace.Text) throw new JournalError(`${id} is a text node, not an element`);
|
|
1074
1172
|
return node;
|
|
1075
1173
|
}
|
|
1076
1174
|
function asPlainElement(node, id) {
|
|
@@ -1086,7 +1184,7 @@ function spliceText(registry, id, start, deleteCount, insert) {
|
|
|
1086
1184
|
return;
|
|
1087
1185
|
}
|
|
1088
1186
|
const text = entry.live;
|
|
1089
|
-
if (!(text instanceof
|
|
1187
|
+
if (!(text instanceof Y__namespace.Text)) throw new JournalError(`${id} is not a text node`);
|
|
1090
1188
|
if (start < 0 || start + deleteCount > text.length) {
|
|
1091
1189
|
throw new JournalError(`text splice out of range on ${id}`);
|
|
1092
1190
|
}
|
|
@@ -1099,27 +1197,29 @@ function detachRemoved(registry, parent, start, count) {
|
|
|
1099
1197
|
function spliceChildren(registry, parentId, start, deleteCount, childIds) {
|
|
1100
1198
|
const parentEntry = registry.require(parentId);
|
|
1101
1199
|
if ("plain" in parentEntry) {
|
|
1102
|
-
const
|
|
1103
|
-
if (start < 0 || start + deleteCount >
|
|
1200
|
+
const parent2 = asPlainElement(parentEntry.plain, parentId);
|
|
1201
|
+
if (start < 0 || start + deleteCount > parent2.children.length) {
|
|
1104
1202
|
throw new JournalError(`child splice out of range on ${parentId}`);
|
|
1105
1203
|
}
|
|
1106
1204
|
const inserted2 = childIds.map((id) => registry.snapshot(id));
|
|
1107
|
-
|
|
1108
|
-
registry.adopt(
|
|
1205
|
+
parent2.children.splice(start, deleteCount, ...inserted2);
|
|
1206
|
+
registry.adopt(parent2, inserted2);
|
|
1109
1207
|
return;
|
|
1110
1208
|
}
|
|
1111
|
-
const
|
|
1209
|
+
const parent = asLiveElement(parentEntry.live, parentId);
|
|
1210
|
+
const children = childrenOf(parent);
|
|
1112
1211
|
if (start < 0 || start + deleteCount > children.length) {
|
|
1113
1212
|
throw new JournalError(`child splice out of range on ${parentId}`);
|
|
1114
1213
|
}
|
|
1115
1214
|
detachRemoved(registry, children, start, deleteCount);
|
|
1116
|
-
const
|
|
1215
|
+
const scope = scopeWithin(parent);
|
|
1216
|
+
const inserted = childIds.map((id) => registry.attachable(id, scope));
|
|
1117
1217
|
if (deleteCount > 0) children.delete(start, deleteCount);
|
|
1118
1218
|
if (inserted.length > 0) children.insert(start, inserted);
|
|
1119
1219
|
}
|
|
1120
1220
|
function locate(registry, id, node) {
|
|
1121
1221
|
const children = node.parent;
|
|
1122
|
-
if (!(children instanceof
|
|
1222
|
+
if (!(children instanceof Y__namespace.Array)) throw new JournalError(`${id} is not attached`);
|
|
1123
1223
|
const index = children.toArray().indexOf(node);
|
|
1124
1224
|
if (index < 0) throw new JournalError(`${id} is not in its parent`);
|
|
1125
1225
|
return { children, index };
|
|
@@ -1146,8 +1246,10 @@ function moveNode(registry, id, destinationId, destinationIndex) {
|
|
|
1146
1246
|
registry.adopt(destination2, [copy]);
|
|
1147
1247
|
return;
|
|
1148
1248
|
}
|
|
1149
|
-
const destination =
|
|
1150
|
-
destination.insert(destinationIndex, [
|
|
1249
|
+
const destination = asLiveElement(destinationEntry.live, destinationId);
|
|
1250
|
+
childrenOf(destination).insert(destinationIndex, [
|
|
1251
|
+
registry.toLive(copy, scopeWithin(destination))
|
|
1252
|
+
]);
|
|
1151
1253
|
}
|
|
1152
1254
|
function renameNode(registry, id, qname) {
|
|
1153
1255
|
const entry = registry.require(id);
|
|
@@ -1162,7 +1264,7 @@ function renameNode(registry, id, qname) {
|
|
|
1162
1264
|
return true;
|
|
1163
1265
|
}
|
|
1164
1266
|
const live = entry.live;
|
|
1165
|
-
if (live instanceof
|
|
1267
|
+
if (live instanceof Y__namespace.Text || isCompact(live)) return false;
|
|
1166
1268
|
if (live.get("ns") !== qname.namespaceUri) live.set("ns", qname.namespaceUri);
|
|
1167
1269
|
if (live.get("local") !== qname.localName) live.set("local", qname.localName);
|
|
1168
1270
|
if (qname.prefix === void 0) {
|
|
@@ -1192,7 +1294,7 @@ function putNode(registry, effect) {
|
|
|
1192
1294
|
}
|
|
1193
1295
|
function rootFor(registry, id) {
|
|
1194
1296
|
const entry = registry.require(id);
|
|
1195
|
-
const live = "live" in entry && entry.live.parent === null ? entry.live : registry.attachable(id);
|
|
1297
|
+
const live = "live" in entry && entry.live.parent === null ? entry.live : registry.attachable(id, /* @__PURE__ */ new Map(), true);
|
|
1196
1298
|
return asLiveElement(live, id);
|
|
1197
1299
|
}
|
|
1198
1300
|
function applyEffect(doc, registry, effect, context) {
|
|
@@ -1236,7 +1338,7 @@ function applyEffect(doc, registry, effect, context) {
|
|
|
1236
1338
|
const rels = doc.getMap("rels");
|
|
1237
1339
|
let byId = rels.get(effect.owner);
|
|
1238
1340
|
if (!byId) {
|
|
1239
|
-
byId = new
|
|
1341
|
+
byId = new Y__namespace.Map();
|
|
1240
1342
|
rels.set(effect.owner, byId);
|
|
1241
1343
|
}
|
|
1242
1344
|
byId.set(effect.record.id, { ...effect.record });
|
|
@@ -1441,7 +1543,7 @@ var DocxCollaborationSession = class {
|
|
|
1441
1543
|
this.doc = options.doc;
|
|
1442
1544
|
this.awareness = options.awareness;
|
|
1443
1545
|
this.offlineEditing = options.offlineEditing ?? false;
|
|
1444
|
-
this.undoManager = new
|
|
1546
|
+
this.undoManager = new Y__namespace.UndoManager(
|
|
1445
1547
|
[
|
|
1446
1548
|
this.doc.getMap("parts"),
|
|
1447
1549
|
this.doc.getMap("rels"),
|
|
@@ -1481,7 +1583,7 @@ var DocxCollaborationSession = class {
|
|
|
1481
1583
|
this.setStatus("error", "not-initialized");
|
|
1482
1584
|
return;
|
|
1483
1585
|
}
|
|
1484
|
-
if (readFormat(this.doc)
|
|
1586
|
+
if (!isReadableFormat(readFormat(this.doc))) {
|
|
1485
1587
|
this.setStatus("error", "collaboration-format-mismatch", readFormat(this.doc));
|
|
1486
1588
|
return;
|
|
1487
1589
|
}
|
|
@@ -1755,7 +1857,7 @@ function resolveAddress(port, address) {
|
|
|
1755
1857
|
};
|
|
1756
1858
|
}
|
|
1757
1859
|
function vectorKey(doc) {
|
|
1758
|
-
return Array.from(
|
|
1860
|
+
return Array.from(Y__namespace.encodeStateVector(doc)).join(",");
|
|
1759
1861
|
}
|
|
1760
1862
|
function randomToken() {
|
|
1761
1863
|
if (typeof crypto.randomUUID === "function") return crypto.randomUUID();
|