@arbidocs/coedit 0.5.21 → 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.
- 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/hocuspocus.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
446
|
+
function createRichParagraph(xml, encoded, scope = /* @__PURE__ */ new Map()) {
|
|
447
|
+
const map = new Y__namespace.Map();
|
|
362
448
|
fieldsOf(map, xml);
|
|
363
|
-
const
|
|
364
|
-
children
|
|
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
|
|
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
|
|
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
|
|
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
|
|
382
|
-
children
|
|
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
|
|
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, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
401
493
|
var escapeAttr = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/\t/g, "	").replace(/\n/g, " ").replace(/\r/g, " ");
|
|
402
494
|
var qualified = (prefix, local) => prefix ? `${prefix}:${local}` : local;
|
|
403
|
-
function
|
|
404
|
-
const inScope =
|
|
405
|
-
|
|
406
|
-
|
|
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
|
|
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
|
-
|
|
518
|
+
let body = "";
|
|
424
519
|
for (const child of el.children) {
|
|
425
|
-
|
|
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 (
|
|
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 =
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
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
|
-
|
|
536
|
+
body += child instanceof Y__namespace.Text ? escapeText(child.toString()) : serializeLive(child, inScope);
|
|
458
537
|
}
|
|
459
|
-
|
|
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/
|
|
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
|
|
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
|
|
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
|
|
816
|
-
if (
|
|
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
|
|
901
|
-
|
|
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
|
|
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
|
|
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
|
|
930
|
-
if (
|
|
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
|
|
959
|
-
if (
|
|
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
|
-
/**
|
|
968
|
-
|
|
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
|
|
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
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
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
|
|
992
|
-
children
|
|
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
|
|
999
|
-
* attached node is copied, because a Yjs type cannot
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
1108
|
-
if (start < 0 || start + deleteCount >
|
|
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
|
-
|
|
1113
|
-
registry.adopt(
|
|
1210
|
+
parent2.children.splice(start, deleteCount, ...inserted2);
|
|
1211
|
+
registry.adopt(parent2, inserted2);
|
|
1114
1212
|
return;
|
|
1115
1213
|
}
|
|
1116
|
-
const
|
|
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
|
|
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
|
|
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 =
|
|
1155
|
-
destination.insert(destinationIndex, [
|
|
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
|
|
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
|
|
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
|
|
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)
|
|
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(
|
|
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
|
|
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,
|