ooxml-core 1.22.0 → 1.23.0
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/README.md +7 -2
- package/dist/automation/index.cjs +6 -4
- package/dist/automation/index.mjs +6 -4
- package/dist/collab/embedding.d.ts +7 -0
- package/dist/collab/embedding.d.ts.map +1 -1
- package/dist/collab/index.cjs +189 -0
- package/dist/collab/index.d.ts +2 -0
- package/dist/collab/index.d.ts.map +1 -1
- package/dist/collab/index.mjs +186 -1
- package/dist/collab/write-back-lifecycle.d.ts +33 -0
- package/dist/collab/write-back-lifecycle.d.ts.map +1 -0
- package/dist/collab/write-back.d.ts +75 -0
- package/dist/collab/write-back.d.ts.map +1 -0
- package/dist/visio/collab/baseline.d.ts +36 -0
- package/dist/visio/collab/baseline.d.ts.map +1 -0
- package/dist/visio/collab/bind.d.ts +20 -2
- package/dist/visio/collab/bind.d.ts.map +1 -1
- package/dist/visio/collab/compose-lists.d.ts +27 -0
- package/dist/visio/collab/compose-lists.d.ts.map +1 -0
- package/dist/visio/collab/compose.d.ts +6 -2
- package/dist/visio/collab/compose.d.ts.map +1 -1
- package/dist/visio/collab/fixups.d.ts +5 -0
- package/dist/visio/collab/fixups.d.ts.map +1 -0
- package/dist/visio/collab/index.cjs +1499 -362
- package/dist/visio/collab/index.d.ts +3 -2
- package/dist/visio/collab/index.d.ts.map +1 -1
- package/dist/visio/collab/index.mjs +1492 -363
- package/dist/visio/collab/keys.d.ts +30 -1
- package/dist/visio/collab/keys.d.ts.map +1 -1
- package/dist/visio/collab/package.d.ts +22 -1
- package/dist/visio/collab/package.d.ts.map +1 -1
- package/dist/visio/collab/pieces.d.ts +34 -0
- package/dist/visio/collab/pieces.d.ts.map +1 -0
- package/dist/visio/collab/read-ids.d.ts +29 -0
- package/dist/visio/collab/read-ids.d.ts.map +1 -0
- package/dist/visio/collab/read-parts.d.ts +34 -0
- package/dist/visio/collab/read-parts.d.ts.map +1 -0
- package/dist/visio/collab/read-shapes.d.ts +35 -0
- package/dist/visio/collab/read-shapes.d.ts.map +1 -0
- package/dist/visio/collab/read-util.d.ts +20 -0
- package/dist/visio/collab/read-util.d.ts.map +1 -0
- package/dist/visio/collab/read.d.ts +40 -19
- package/dist/visio/collab/read.d.ts.map +1 -1
- package/dist/visio/collab/schema.d.ts +55 -1
- package/dist/visio/collab/schema.d.ts.map +1 -1
- package/dist/visio/collab/snapshot-contents.d.ts +9 -0
- package/dist/visio/collab/snapshot-contents.d.ts.map +1 -0
- package/dist/visio/collab/snapshot-io.d.ts +26 -0
- package/dist/visio/collab/snapshot-io.d.ts.map +1 -0
- package/dist/visio/collab/snapshot-parts.d.ts +14 -0
- package/dist/visio/collab/snapshot-parts.d.ts.map +1 -0
- package/dist/visio/collab/snapshot.d.ts +31 -24
- package/dist/visio/collab/snapshot.d.ts.map +1 -1
- package/dist/visio/collab/write-parts.d.ts +8 -0
- package/dist/visio/collab/write-parts.d.ts.map +1 -0
- package/dist/visio/collab/write-shapes.d.ts +30 -0
- package/dist/visio/collab/write-shapes.d.ts.map +1 -0
- package/dist/visio/collab/write.d.ts +4 -16
- package/dist/visio/collab/write.d.ts.map +1 -1
- package/dist/visio/index.cjs +57 -4
- package/dist/visio/index.d.ts +1 -0
- package/dist/visio/index.d.ts.map +1 -1
- package/dist/visio/index.mjs +56 -5
- package/dist/visio/parse-incremental.d.ts +16 -0
- package/dist/visio/parse-incremental.d.ts.map +1 -0
- package/dist/visio/parser.d.ts +7 -0
- package/dist/visio/parser.d.ts.map +1 -1
- package/dist/visio/ui/collab-options.d.ts +10 -5
- package/dist/visio/ui/collab-options.d.ts.map +1 -1
- package/dist/visio/ui/index.cjs +6 -4
- package/dist/visio/ui/index.mjs +6 -4
- package/package.json +1 -1
|
@@ -28,6 +28,143 @@ var Y__namespace = /*#__PURE__*/_interopNamespace(Y);
|
|
|
28
28
|
var JSZip__default = /*#__PURE__*/_interopDefault(JSZip);
|
|
29
29
|
|
|
30
30
|
// visio/collab/bind.ts
|
|
31
|
+
|
|
32
|
+
// digest/sha256.ts
|
|
33
|
+
var K = new Uint32Array([
|
|
34
|
+
1116352408,
|
|
35
|
+
1899447441,
|
|
36
|
+
3049323471,
|
|
37
|
+
3921009573,
|
|
38
|
+
961987163,
|
|
39
|
+
1508970993,
|
|
40
|
+
2453635748,
|
|
41
|
+
2870763221,
|
|
42
|
+
3624381080,
|
|
43
|
+
310598401,
|
|
44
|
+
607225278,
|
|
45
|
+
1426881987,
|
|
46
|
+
1925078388,
|
|
47
|
+
2162078206,
|
|
48
|
+
2614888103,
|
|
49
|
+
3248222580,
|
|
50
|
+
3835390401,
|
|
51
|
+
4022224774,
|
|
52
|
+
264347078,
|
|
53
|
+
604807628,
|
|
54
|
+
770255983,
|
|
55
|
+
1249150122,
|
|
56
|
+
1555081692,
|
|
57
|
+
1996064986,
|
|
58
|
+
2554220882,
|
|
59
|
+
2821834349,
|
|
60
|
+
2952996808,
|
|
61
|
+
3210313671,
|
|
62
|
+
3336571891,
|
|
63
|
+
3584528711,
|
|
64
|
+
113926993,
|
|
65
|
+
338241895,
|
|
66
|
+
666307205,
|
|
67
|
+
773529912,
|
|
68
|
+
1294757372,
|
|
69
|
+
1396182291,
|
|
70
|
+
1695183700,
|
|
71
|
+
1986661051,
|
|
72
|
+
2177026350,
|
|
73
|
+
2456956037,
|
|
74
|
+
2730485921,
|
|
75
|
+
2820302411,
|
|
76
|
+
3259730800,
|
|
77
|
+
3345764771,
|
|
78
|
+
3516065817,
|
|
79
|
+
3600352804,
|
|
80
|
+
4094571909,
|
|
81
|
+
275423344,
|
|
82
|
+
430227734,
|
|
83
|
+
506948616,
|
|
84
|
+
659060556,
|
|
85
|
+
883997877,
|
|
86
|
+
958139571,
|
|
87
|
+
1322822218,
|
|
88
|
+
1537002063,
|
|
89
|
+
1747873779,
|
|
90
|
+
1955562222,
|
|
91
|
+
2024104815,
|
|
92
|
+
2227730452,
|
|
93
|
+
2361852424,
|
|
94
|
+
2428436474,
|
|
95
|
+
2756734187,
|
|
96
|
+
3204031479,
|
|
97
|
+
3329325298
|
|
98
|
+
]);
|
|
99
|
+
var IV = [
|
|
100
|
+
1779033703,
|
|
101
|
+
3144134277,
|
|
102
|
+
1013904242,
|
|
103
|
+
2773480762,
|
|
104
|
+
1359893119,
|
|
105
|
+
2600822924,
|
|
106
|
+
528734635,
|
|
107
|
+
1541459225
|
|
108
|
+
];
|
|
109
|
+
var W = new Uint32Array(64);
|
|
110
|
+
var rotr = (x, n) => x >>> n | x << 32 - n;
|
|
111
|
+
function compress(h, view, offset) {
|
|
112
|
+
for (let i = 0; i < 16; i++) W[i] = view.getUint32(offset + i * 4);
|
|
113
|
+
for (let i = 16; i < 64; i++) {
|
|
114
|
+
const a2 = W[i - 15];
|
|
115
|
+
const b2 = W[i - 2];
|
|
116
|
+
const s0 = rotr(a2, 7) ^ rotr(a2, 18) ^ a2 >>> 3;
|
|
117
|
+
const s1 = rotr(b2, 17) ^ rotr(b2, 19) ^ b2 >>> 10;
|
|
118
|
+
W[i] = W[i - 16] + s0 + W[i - 7] + s1 >>> 0;
|
|
119
|
+
}
|
|
120
|
+
let a = h[0], b = h[1], c = h[2], d = h[3], e = h[4], f = h[5], g = h[6], k = h[7];
|
|
121
|
+
for (let i = 0; i < 64; i++) {
|
|
122
|
+
const S1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
|
|
123
|
+
const ch = e & f ^ ~e & g;
|
|
124
|
+
const t1 = k + S1 + ch + K[i] + W[i] >>> 0;
|
|
125
|
+
const S0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
|
|
126
|
+
const maj = a & b ^ a & c ^ b & c;
|
|
127
|
+
const t2 = S0 + maj >>> 0;
|
|
128
|
+
k = g;
|
|
129
|
+
g = f;
|
|
130
|
+
f = e;
|
|
131
|
+
e = d + t1 >>> 0;
|
|
132
|
+
d = c;
|
|
133
|
+
c = b;
|
|
134
|
+
b = a;
|
|
135
|
+
a = t1 + t2 >>> 0;
|
|
136
|
+
}
|
|
137
|
+
h[0] = h[0] + a >>> 0;
|
|
138
|
+
h[1] = h[1] + b >>> 0;
|
|
139
|
+
h[2] = h[2] + c >>> 0;
|
|
140
|
+
h[3] = h[3] + d >>> 0;
|
|
141
|
+
h[4] = h[4] + e >>> 0;
|
|
142
|
+
h[5] = h[5] + f >>> 0;
|
|
143
|
+
h[6] = h[6] + g >>> 0;
|
|
144
|
+
h[7] = h[7] + k >>> 0;
|
|
145
|
+
}
|
|
146
|
+
function pad64(data) {
|
|
147
|
+
const padded = new Uint8Array(Math.ceil((data.length + 9) / 64) * 64);
|
|
148
|
+
padded.set(data);
|
|
149
|
+
padded[data.length] = 128;
|
|
150
|
+
const bits = data.length * 8;
|
|
151
|
+
const view = new DataView(padded.buffer);
|
|
152
|
+
view.setUint32(padded.length - 8, Math.floor(bits / 4294967296));
|
|
153
|
+
view.setUint32(padded.length - 4, bits >>> 0);
|
|
154
|
+
return view;
|
|
155
|
+
}
|
|
156
|
+
function wordsOut(h) {
|
|
157
|
+
const out = new Uint8Array(h.length * 4);
|
|
158
|
+
const view = new DataView(out.buffer);
|
|
159
|
+
for (let i = 0; i < h.length; i++) view.setUint32(i * 4, h[i]);
|
|
160
|
+
return out;
|
|
161
|
+
}
|
|
162
|
+
function sha256(data) {
|
|
163
|
+
const h = new Uint32Array(IV);
|
|
164
|
+
const view = pad64(data);
|
|
165
|
+
for (let offset = 0; offset < view.byteLength; offset += 64) compress(h, view, offset);
|
|
166
|
+
return wordsOut(h);
|
|
167
|
+
}
|
|
31
168
|
var DEFAULT_XML_LIMITS = {
|
|
32
169
|
maxDepth: 512,
|
|
33
170
|
maxNodes: 5e6
|
|
@@ -278,11 +415,51 @@ function stripPageOverrides(xml) {
|
|
|
278
415
|
(tag) => attrOf(tag, "ContentType") === PAGE_CONTENT_TYPE ? "" : tag
|
|
279
416
|
);
|
|
280
417
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
418
|
+
var withPageOverrides = (xml, pagePaths) => withOverrides(stripPageOverrides(xml), PAGE_CONTENT_TYPE, pagePaths);
|
|
419
|
+
var MASTER_TYPE = "http://schemas.microsoft.com/visio/2010/relationships/master";
|
|
420
|
+
var MASTER_CONTENT_TYPE = "application/vnd.ms-visio.master+xml";
|
|
421
|
+
function withOverrides(xml, contentType, paths) {
|
|
422
|
+
const add = paths.map((path) => `<Override PartName="/${path}" ContentType="${contentType}"/>`).join("");
|
|
423
|
+
const close = xml.lastIndexOf("</");
|
|
424
|
+
return close < 0 ? xml : xml.slice(0, close) + add + xml.slice(close);
|
|
425
|
+
}
|
|
426
|
+
function stripOverrides(xml, types, parts = /* @__PURE__ */ new Set()) {
|
|
427
|
+
return xml.replace(/<(?:\w+:)?Override\b[^>]*>/g, (tag) => {
|
|
428
|
+
const type = attrOf(tag, "ContentType");
|
|
429
|
+
const name = attrOf(tag, "PartName");
|
|
430
|
+
return type !== void 0 && types.includes(type) || name !== void 0 && parts.has(name.replace(/^\//, "")) ? "" : tag;
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
function declaredType(xml, path) {
|
|
434
|
+
for (const tag of xml.matchAll(/<(?:\w+:)?Override\b[^>]*>/g)) {
|
|
435
|
+
const name = attrOf(tag[0], "PartName");
|
|
436
|
+
const type = attrOf(tag[0], "ContentType");
|
|
437
|
+
if (name === `/${path}` && type !== void 0) return { type, byDefault: false };
|
|
438
|
+
}
|
|
439
|
+
const ext = /\.([^./]+)$/.exec(path)?.[1]?.toLowerCase();
|
|
440
|
+
if (ext === void 0) return void 0;
|
|
441
|
+
for (const tag of xml.matchAll(/<(?:\w+:)?Default\b[^>]*>/g)) {
|
|
442
|
+
const e = attrOf(tag[0], "Extension");
|
|
443
|
+
const type = attrOf(tag[0], "ContentType");
|
|
444
|
+
if (e?.toLowerCase() === ext && type !== void 0) return { type, byDefault: true };
|
|
445
|
+
}
|
|
446
|
+
return void 0;
|
|
447
|
+
}
|
|
448
|
+
function ensureType(xml, path, declared) {
|
|
449
|
+
if (declaredType(xml, path)) return xml;
|
|
450
|
+
const close = xml.lastIndexOf("</");
|
|
451
|
+
if (close < 0) return xml;
|
|
452
|
+
const ext = /\.([^./]+)$/.exec(path)?.[1];
|
|
453
|
+
const tag = declared.byDefault && ext ? `<Default Extension="${ext}" ContentType="${declared.type}"/>` : `<Override PartName="/${path}" ContentType="${declared.type}"/>`;
|
|
454
|
+
return xml.slice(0, close) + tag + xml.slice(close);
|
|
455
|
+
}
|
|
456
|
+
var isMediaPart = (path) => /(^|\/)media\/[^/]+$/i.test(path);
|
|
457
|
+
function relativeTarget(dir, path) {
|
|
458
|
+
const from = dir ? dir.split("/") : [];
|
|
459
|
+
const to = path.split("/");
|
|
460
|
+
let i = 0;
|
|
461
|
+
while (i < from.length && i < to.length - 1 && from[i] === to[i]) i++;
|
|
462
|
+
return [...from.slice(i).map(() => ".."), ...to.slice(i)].join("/");
|
|
286
463
|
}
|
|
287
464
|
function toBase64(bytes) {
|
|
288
465
|
let out = "";
|
|
@@ -316,15 +493,154 @@ function canon(xml) {
|
|
|
316
493
|
canonCache.set(xml, result);
|
|
317
494
|
return result;
|
|
318
495
|
}
|
|
496
|
+
function contentHash(bytes) {
|
|
497
|
+
let out = "";
|
|
498
|
+
for (const byte of sha256(bytes)) out += byte.toString(16).padStart(2, "0");
|
|
499
|
+
return out;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// visio/collab/pieces.ts
|
|
503
|
+
var seg = (value) => value.replace(/[%/]/g, (c) => c === "%" ? "%25" : "%2F");
|
|
504
|
+
var tagName = (open) => /^<([^\s/>]+)/.exec(open)?.[1] ?? "Shape";
|
|
505
|
+
var openTagOf = (text, span) => {
|
|
506
|
+
const tag = text.slice(span.start, span.openEnd);
|
|
507
|
+
return span.selfClosing ? tag.replace(/\s*\/>$/, ">") : tag;
|
|
508
|
+
};
|
|
509
|
+
var closeTagOf = (open) => `</${tagName(open)}>`;
|
|
510
|
+
function splitShape(xml) {
|
|
511
|
+
const box = scanContainer(xml, "Shape");
|
|
512
|
+
if (!box) return void 0;
|
|
513
|
+
const used = /* @__PURE__ */ new Set();
|
|
514
|
+
const unique = (path) => {
|
|
515
|
+
let out = path;
|
|
516
|
+
for (let n = 2; used.has(out); n++) out = `${path}~${n}`;
|
|
517
|
+
used.add(out);
|
|
518
|
+
return out;
|
|
519
|
+
};
|
|
520
|
+
const pieces = [];
|
|
521
|
+
const nested = [];
|
|
522
|
+
const others = /* @__PURE__ */ new Map();
|
|
523
|
+
const other = (parent, name, text) => {
|
|
524
|
+
const k = others.get(parent + name) ?? 0;
|
|
525
|
+
others.set(parent + name, k + 1);
|
|
526
|
+
pieces.push({
|
|
527
|
+
path: unique(`${parent ? `${parent}/` : ""}x/${name}#${k}`),
|
|
528
|
+
parent,
|
|
529
|
+
kind: "leaf",
|
|
530
|
+
text
|
|
531
|
+
});
|
|
532
|
+
};
|
|
533
|
+
const cell = (parent, text) => {
|
|
534
|
+
const n = attrOf(text.slice(0, text.search(/>/) + 1), "N");
|
|
535
|
+
if (n === void 0) return other(parent, "Cell", text);
|
|
536
|
+
pieces.push({
|
|
537
|
+
path: unique(`${parent ? `${parent}/` : ""}c/${seg(n)}`),
|
|
538
|
+
parent,
|
|
539
|
+
kind: "leaf",
|
|
540
|
+
text
|
|
541
|
+
});
|
|
542
|
+
};
|
|
543
|
+
for (const child of box.children) {
|
|
544
|
+
const text = xml.slice(child.start, child.end);
|
|
545
|
+
if (child.name === "Cell") cell("", text);
|
|
546
|
+
else if (child.name === "Shapes") {
|
|
547
|
+
const list = scanContainer(text, "Shapes");
|
|
548
|
+
for (const s of list?.children ?? [])
|
|
549
|
+
if (s.name === "Shape") nested.push(text.slice(s.start, s.end));
|
|
550
|
+
} else if (child.name === "Section") {
|
|
551
|
+
const head = openTagOf(xml, child);
|
|
552
|
+
const n = attrOf(head, "N");
|
|
553
|
+
const ix = attrOf(head, "IX");
|
|
554
|
+
if (n === void 0 && ix === void 0) {
|
|
555
|
+
other("", "Section", text);
|
|
556
|
+
continue;
|
|
557
|
+
}
|
|
558
|
+
const sec = unique(`s/${seg(n ?? "")}${ix !== void 0 ? `:${seg(ix)}` : ""}`);
|
|
559
|
+
pieces.push({ path: sec, parent: "", kind: "open", text: head });
|
|
560
|
+
const inner = scanContainer(text, "Section");
|
|
561
|
+
let rowIndex = 0;
|
|
562
|
+
for (const part of inner?.children ?? []) {
|
|
563
|
+
const sub = text.slice(part.start, part.end);
|
|
564
|
+
if (part.name === "Cell") cell(sec, sub);
|
|
565
|
+
else if (part.name === "Row") {
|
|
566
|
+
const rowHead = openTagOf(text, part);
|
|
567
|
+
const id = attrOf(rowHead, "IX") ?? attrOf(rowHead, "N") ?? `#${rowIndex}`;
|
|
568
|
+
rowIndex++;
|
|
569
|
+
const row = unique(`${sec}/r/${seg(id)}`);
|
|
570
|
+
pieces.push({ path: row, parent: sec, kind: "open", text: rowHead });
|
|
571
|
+
for (const rc of scanContainer(sub, "Row")?.children ?? [])
|
|
572
|
+
if (rc.name === "Cell") cell(row, sub.slice(rc.start, rc.end));
|
|
573
|
+
else other(row, rc.name, sub.slice(rc.start, rc.end));
|
|
574
|
+
} else other(sec, part.name, sub);
|
|
575
|
+
}
|
|
576
|
+
} else other("", child.name, text);
|
|
577
|
+
}
|
|
578
|
+
return { open: openTagOf(xml, box), pieces, nested };
|
|
579
|
+
}
|
|
580
|
+
function buildShape(open, entries, tail) {
|
|
581
|
+
const byParent = /* @__PURE__ */ new Map();
|
|
582
|
+
for (const [path, entry] of entries) {
|
|
583
|
+
const parent = parentOf(path);
|
|
584
|
+
const list = byParent.get(parent) ?? [];
|
|
585
|
+
list.push({ path, entry });
|
|
586
|
+
byParent.set(parent, list);
|
|
587
|
+
}
|
|
588
|
+
const render = (parent) => (byParent.get(parent) ?? []).sort((a, b) => a.entry.pos - b.entry.pos || (a.path < b.path ? -1 : a.path > b.path ? 1 : 0)).map(
|
|
589
|
+
({ path, entry }) => entry.open !== void 0 ? entry.open + render(path) + closeTagOf(entry.open) : entry.xml ?? ""
|
|
590
|
+
).join("");
|
|
591
|
+
return open + render("") + tail + closeTagOf(open);
|
|
592
|
+
}
|
|
593
|
+
function parentOf(path) {
|
|
594
|
+
const parts = path.split("/");
|
|
595
|
+
return parts.length <= 2 ? "" : parts.slice(0, -2).join("/");
|
|
596
|
+
}
|
|
597
|
+
var SIMPLE = /^<([^\s/>]+)((?:\s+[^\s=/>]+\s*=\s*(?:"[^"]*"|'[^']*'))*)\s*(?:\/>|>([^<]*)<\/\1>)$/;
|
|
598
|
+
var ATTR = /\s([^\s=/>]+)\s*=\s*(?:"([^"]*)"|'([^']*)')/g;
|
|
599
|
+
function pieceContent(kind, text) {
|
|
600
|
+
const simple = SIMPLE.exec(kind === "open" ? `${text}</${tagName(text)}>` : text);
|
|
601
|
+
if (!simple) return kind === "open" ? canon(`${text}</${tagName(text)}>`) : canon(text);
|
|
602
|
+
const attrs = [...(simple[2] ?? "").matchAll(ATTR)].map((m) => [m[1], m[2] ?? m[3] ?? ""]).sort((a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0);
|
|
603
|
+
return JSON.stringify([simple[1], attrs, simple[3] ?? ""]);
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
// visio/collab/baseline.ts
|
|
607
|
+
var masterScope = (key) => `m~${key}`;
|
|
608
|
+
var pageId = (key) => `p:${key}`;
|
|
609
|
+
var bodyId = (key) => `b:${key}`;
|
|
610
|
+
var shapeId = (page, key) => `s:${page}/${key}`;
|
|
611
|
+
var cellId = (page, shape, path) => `f:${page}/${shape}/${path}`;
|
|
612
|
+
var connectId = (key) => `c:${key}`;
|
|
613
|
+
var masterId = (key) => `m:${key}`;
|
|
614
|
+
var mediaId = (key) => `i:${key}`;
|
|
615
|
+
var pageContent = (e) => JSON.stringify([e.id, e.back ?? null, canon(e.xml)]);
|
|
616
|
+
var bodyContent = (e) => JSON.stringify([canon(e.shell), e.rels ?? null]);
|
|
617
|
+
var shellContent = (e) => JSON.stringify([e.parent ?? null, pieceContent("open", e.open)]);
|
|
618
|
+
var entryContent = (e) => e.xml !== void 0 ? pieceContent("leaf", e.xml) : pieceContent("open", e.open ?? "");
|
|
619
|
+
var masterContent = (e) => JSON.stringify([e.id, canon(e.xml), e.rels ?? null, e.print]);
|
|
319
620
|
|
|
320
621
|
// visio/collab/schema.ts
|
|
321
|
-
var SCHEMA_VERSION =
|
|
622
|
+
var SCHEMA_VERSION = 3;
|
|
623
|
+
var SchemaVersionError = class extends Error {
|
|
624
|
+
constructor(found) {
|
|
625
|
+
super(
|
|
626
|
+
`The shared drawing uses schema version ${String(found)}; this build reads version ${SCHEMA_VERSION}.`
|
|
627
|
+
);
|
|
628
|
+
this.found = found;
|
|
629
|
+
this.name = "SchemaVersionError";
|
|
630
|
+
}
|
|
631
|
+
found;
|
|
632
|
+
};
|
|
322
633
|
var META = "visio:meta";
|
|
323
634
|
var PAGES = "visio:pages";
|
|
324
635
|
var BODIES = "visio:bodies";
|
|
325
636
|
var SHAPES = "visio:shapes";
|
|
637
|
+
var CELLS = "visio:cells";
|
|
326
638
|
var CONNECTS = "visio:connects";
|
|
327
639
|
var DEAD = "visio:dead";
|
|
640
|
+
var MASTERS = "visio:masters";
|
|
641
|
+
var RENUM = "visio:renum";
|
|
642
|
+
var MEDIA = "visio:media";
|
|
643
|
+
var BLOBS = "visio:blobs";
|
|
328
644
|
var PARTS = "visio:parts";
|
|
329
645
|
var REL_MARK = "<!--@rel-->";
|
|
330
646
|
var SHAPES_MARK = "<!--@shapes-->";
|
|
@@ -335,8 +651,13 @@ function sharedDrawing(doc) {
|
|
|
335
651
|
pages: doc.getMap(PAGES),
|
|
336
652
|
bodies: doc.getMap(BODIES),
|
|
337
653
|
shapes: doc.getMap(SHAPES),
|
|
654
|
+
cells: doc.getMap(CELLS),
|
|
338
655
|
connects: doc.getMap(CONNECTS),
|
|
339
656
|
dead: doc.getMap(DEAD),
|
|
657
|
+
masters: doc.getMap(MASTERS),
|
|
658
|
+
renum: doc.getMap(RENUM),
|
|
659
|
+
media: doc.getMap(MEDIA),
|
|
660
|
+
blobs: doc.getMap(BLOBS),
|
|
340
661
|
parts: doc.getMap(PARTS)
|
|
341
662
|
};
|
|
342
663
|
}
|
|
@@ -345,17 +666,27 @@ var sharedTypes = (shared) => [
|
|
|
345
666
|
shared.pages,
|
|
346
667
|
shared.bodies,
|
|
347
668
|
shared.shapes,
|
|
669
|
+
shared.cells,
|
|
348
670
|
shared.connects,
|
|
349
671
|
shared.dead,
|
|
672
|
+
shared.masters,
|
|
673
|
+
shared.renum,
|
|
674
|
+
shared.media,
|
|
675
|
+
shared.blobs,
|
|
350
676
|
shared.parts
|
|
351
677
|
];
|
|
352
678
|
var isSharedDrawingEmpty = (shared) => shared.pages.size === 0 && shared.meta.get("v") === void 0;
|
|
679
|
+
function assertSchemaVersion(shared) {
|
|
680
|
+
const v = shared.meta.get("v");
|
|
681
|
+
if (v !== void 0 && v !== SCHEMA_VERSION) throw new SchemaVersionError(v);
|
|
682
|
+
}
|
|
353
683
|
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
354
684
|
function sameRecord(a, b) {
|
|
355
685
|
if (!isRecord(a) || !isRecord(b)) return a === b;
|
|
356
686
|
const ka = Object.keys(a).filter((k) => a[k] !== void 0);
|
|
357
687
|
const kb = Object.keys(b).filter((k) => b[k] !== void 0);
|
|
358
|
-
|
|
688
|
+
const same = (x, y) => x === y || Array.isArray(x) && Array.isArray(y) && JSON.stringify(x) === JSON.stringify(y);
|
|
689
|
+
return ka.length === kb.length && ka.every((k) => same(a[k], b[k]));
|
|
359
690
|
}
|
|
360
691
|
function setIfChanged(map, key, value) {
|
|
361
692
|
if (sameRecord(map.get(key), value)) return false;
|
|
@@ -364,27 +695,53 @@ function setIfChanged(map, key, value) {
|
|
|
364
695
|
}
|
|
365
696
|
var str = (value) => typeof value === "string" ? value : void 0;
|
|
366
697
|
var num = (value) => typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
698
|
+
var opt = (key, value) => value === void 0 ? {} : { [key]: value };
|
|
367
699
|
function pageEntry(value) {
|
|
368
700
|
if (!isRecord(value)) return void 0;
|
|
369
701
|
const pos = num(value.pos);
|
|
370
702
|
const id = str(value.id);
|
|
371
703
|
const xml = str(value.xml);
|
|
372
704
|
if (pos === void 0 || id === void 0 || xml === void 0) return void 0;
|
|
373
|
-
|
|
374
|
-
return { pos, id, xml, ...back !== void 0 ? { back } : {} };
|
|
705
|
+
return { pos, id, xml, ...opt("back", str(value.back)) };
|
|
375
706
|
}
|
|
376
707
|
function bodyEntry(value) {
|
|
377
708
|
if (!isRecord(value)) return void 0;
|
|
378
709
|
const shell = str(value.shell);
|
|
379
710
|
if (shell === void 0) return void 0;
|
|
380
|
-
|
|
381
|
-
return { shell, ...rels !== void 0 ? { rels } : {} };
|
|
711
|
+
return { shell, ...opt("rels", str(value.rels)), ...opt("b", str(value.b)) };
|
|
382
712
|
}
|
|
383
713
|
function shapeEntry(value) {
|
|
714
|
+
if (!isRecord(value)) return void 0;
|
|
715
|
+
const pos = num(value.pos);
|
|
716
|
+
const open = str(value.open);
|
|
717
|
+
if (pos === void 0 || open === void 0) return void 0;
|
|
718
|
+
return { pos, open, ...opt("parent", str(value.parent)), ...opt("b", str(value.b)) };
|
|
719
|
+
}
|
|
720
|
+
function cellEntry(value) {
|
|
384
721
|
if (!isRecord(value)) return void 0;
|
|
385
722
|
const pos = num(value.pos);
|
|
386
723
|
const xml = str(value.xml);
|
|
387
|
-
|
|
724
|
+
const open = str(value.open);
|
|
725
|
+
if (pos === void 0 || xml === void 0 && open === void 0) return void 0;
|
|
726
|
+
return { pos, ...opt("xml", xml), ...opt("open", xml === void 0 ? open : void 0) };
|
|
727
|
+
}
|
|
728
|
+
function masterEntry(value) {
|
|
729
|
+
if (!isRecord(value)) return void 0;
|
|
730
|
+
const pos = num(value.pos);
|
|
731
|
+
const id = str(value.id);
|
|
732
|
+
const xml = str(value.xml);
|
|
733
|
+
const part = str(value.part);
|
|
734
|
+
if (pos === void 0 || id === void 0 || xml === void 0 || part === void 0)
|
|
735
|
+
return void 0;
|
|
736
|
+
return { pos, id, xml, part, ...opt("rels", str(value.rels)), ...opt("b", str(value.b)) };
|
|
737
|
+
}
|
|
738
|
+
function mediaEntry(value) {
|
|
739
|
+
if (!isRecord(value)) return void 0;
|
|
740
|
+
const path = str(value.path);
|
|
741
|
+
const hash = str(value.hash);
|
|
742
|
+
const ct = str(value.ct);
|
|
743
|
+
if (path === void 0 || hash === void 0 || ct === void 0) return void 0;
|
|
744
|
+
return { path, hash, ct, d: value.d === true, ...opt("b", str(value.b)) };
|
|
388
745
|
}
|
|
389
746
|
function connectEntry(value) {
|
|
390
747
|
if (!isRecord(value)) return void 0;
|
|
@@ -396,11 +753,15 @@ function connectEntry(value) {
|
|
|
396
753
|
}
|
|
397
754
|
return out;
|
|
398
755
|
}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
756
|
+
function renumEntry(value) {
|
|
757
|
+
if (!isRecord(value)) return void 0;
|
|
758
|
+
const pair = (v) => Array.isArray(v) && v.length === 2 && typeof v[0] === "string" && typeof v[1] === "string" ? [v[0], v[1]] : void 0;
|
|
759
|
+
const i = pair(value.i);
|
|
760
|
+
const m = pair(value.m);
|
|
761
|
+
return i || m ? { ...i ? { i } : {}, ...m ? { m } : {} } : void 0;
|
|
403
762
|
}
|
|
763
|
+
|
|
764
|
+
// visio/collab/snapshot-contents.ts
|
|
404
765
|
function splitList(text, name, mark, child) {
|
|
405
766
|
const box = scanContainer(text, name);
|
|
406
767
|
if (!box) return { text, items: [] };
|
|
@@ -416,6 +777,46 @@ function splitList(text, name, mark, child) {
|
|
|
416
777
|
}
|
|
417
778
|
return { text: text.slice(0, box.openEnd) + mark + text.slice(box.closeStart), items };
|
|
418
779
|
}
|
|
780
|
+
function flatten(xml, parent, page, keys, out) {
|
|
781
|
+
const split2 = splitShape(xml);
|
|
782
|
+
const id = split2 ? attrOf(split2.open, "ID") : void 0;
|
|
783
|
+
if (!split2 || id === void 0) return;
|
|
784
|
+
const key = keys.shapeKey(page, id);
|
|
785
|
+
out.push({
|
|
786
|
+
key,
|
|
787
|
+
id,
|
|
788
|
+
...parent !== void 0 ? { parent } : {},
|
|
789
|
+
open: split2.open,
|
|
790
|
+
pieces: split2.pieces
|
|
791
|
+
});
|
|
792
|
+
for (const nested of split2.nested) flatten(nested, key, page, keys, out);
|
|
793
|
+
}
|
|
794
|
+
function splitContents(content, scope, keys) {
|
|
795
|
+
const shapesSplit = splitList(content, "Shapes", SHAPES_MARK, "Shape");
|
|
796
|
+
const connectsSplit = splitList(shapesSplit.text, "Connects", CONNECTS_MARK, "Connect");
|
|
797
|
+
const shapes = [];
|
|
798
|
+
for (const text of shapesSplit.items) flatten(text, void 0, scope, keys, shapes);
|
|
799
|
+
const owner = new Map(shapes.map((s) => [s.id, s.key]));
|
|
800
|
+
const connects = [];
|
|
801
|
+
for (const text of connectsSplit.items) {
|
|
802
|
+
const a = (name) => attrOf(text, name) ?? "";
|
|
803
|
+
const entry = {
|
|
804
|
+
fk: owner.get(a("FromSheet")) ?? "",
|
|
805
|
+
fi: a("FromSheet"),
|
|
806
|
+
tk: owner.get(a("ToSheet")) ?? "",
|
|
807
|
+
ti: a("ToSheet"),
|
|
808
|
+
fc: a("FromCell"),
|
|
809
|
+
tc: a("ToCell"),
|
|
810
|
+
fp: a("FromPart"),
|
|
811
|
+
tp: a("ToPart")
|
|
812
|
+
};
|
|
813
|
+
connects.push({
|
|
814
|
+
key: `${scope}/${entry.fk}.${entry.fi}.${entry.fc}.${entry.fp}>${entry.tk}.${entry.ti}.${entry.tc}.${entry.tp}`,
|
|
815
|
+
entry
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
return { shell: connectsSplit.text, shapes, connects };
|
|
819
|
+
}
|
|
419
820
|
var readZip = (bytes) => JSZip__default.default.loadAsync(bytes);
|
|
420
821
|
var zipText = async (zip, path) => zip.file(path)?.async("string");
|
|
421
822
|
async function readLayout(zip) {
|
|
@@ -426,19 +827,25 @@ async function readLayout(zip) {
|
|
|
426
827
|
const documentPath = resolveTarget("", root.target);
|
|
427
828
|
const rels = parseRelationships(await zipText(zip, relsPathOf(documentPath)));
|
|
428
829
|
const pages = rels.find((r) => r.type.endsWith("/pages"));
|
|
429
|
-
|
|
830
|
+
const masters = rels.find((r) => r.type.endsWith("/masters"));
|
|
831
|
+
const dir = dirName(documentPath);
|
|
832
|
+
return pages ? {
|
|
833
|
+
documentPath,
|
|
834
|
+
pagesPath: resolveTarget(dir, pages.target),
|
|
835
|
+
...masters ? { mastersPath: resolveTarget(dir, masters.target) } : {}
|
|
836
|
+
} : void 0;
|
|
430
837
|
}
|
|
431
|
-
async function
|
|
432
|
-
const box = scanContainer(
|
|
838
|
+
async function readLocalItems(zip, listPath, xml, container, child) {
|
|
839
|
+
const box = scanContainer(xml, container);
|
|
433
840
|
if (!box) return void 0;
|
|
434
841
|
const rels = new Map(
|
|
435
|
-
parseRelationships(await zipText(zip, relsPathOf(
|
|
842
|
+
parseRelationships(await zipText(zip, relsPathOf(listPath))).map((r) => [r.id, r])
|
|
436
843
|
);
|
|
437
|
-
const
|
|
844
|
+
const items = [];
|
|
438
845
|
for (const span of box.children) {
|
|
439
|
-
if (span.name !==
|
|
440
|
-
const text =
|
|
441
|
-
const inner = scanContainer(text,
|
|
846
|
+
if (span.name !== child) continue;
|
|
847
|
+
const text = xml.slice(span.start, span.end);
|
|
848
|
+
const inner = scanContainer(text, child);
|
|
442
849
|
const relSpan = inner?.children.find((c) => c.name === "Rel");
|
|
443
850
|
if (!inner || !relSpan) return void 0;
|
|
444
851
|
const relTag = text.slice(relSpan.start, relSpan.openEnd);
|
|
@@ -446,239 +853,194 @@ async function readLocalPages(zip, layout, pagesXml) {
|
|
|
446
853
|
const target = rid ? rels.get(rid)?.target : void 0;
|
|
447
854
|
const id = attrOf(text.slice(0, inner.openEnd), "ID");
|
|
448
855
|
if (target === void 0 || id === void 0) return void 0;
|
|
449
|
-
|
|
856
|
+
items.push({
|
|
450
857
|
id,
|
|
451
858
|
text,
|
|
452
|
-
path: resolveTarget(dirName(
|
|
859
|
+
path: resolveTarget(dirName(listPath), target),
|
|
453
860
|
rel: { start: relSpan.start, end: relSpan.end }
|
|
454
861
|
});
|
|
455
862
|
}
|
|
456
|
-
return { box,
|
|
863
|
+
return { box, items };
|
|
864
|
+
}
|
|
865
|
+
var withMark = (item) => item.text.slice(0, item.rel.start) + REL_MARK + item.text.slice(item.rel.end);
|
|
866
|
+
|
|
867
|
+
// visio/collab/snapshot-parts.ts
|
|
868
|
+
async function snapshotMasters(zip, layout, keys, derived) {
|
|
869
|
+
const masters = [];
|
|
870
|
+
let mastersOpen;
|
|
871
|
+
let mastersClose;
|
|
872
|
+
if (layout.mastersPath) {
|
|
873
|
+
const listXml = await zipText(zip, layout.mastersPath) ?? "";
|
|
874
|
+
const list = await readLocalItems(zip, layout.mastersPath, listXml, "Masters", "Master");
|
|
875
|
+
if (list) {
|
|
876
|
+
derived.add(layout.mastersPath).add(relsPathOf(layout.mastersPath));
|
|
877
|
+
mastersOpen = listXml.slice(0, list.box.openEnd);
|
|
878
|
+
mastersClose = listXml.slice(list.box.closeStart);
|
|
879
|
+
for (const item of list.items) {
|
|
880
|
+
const content = await zipText(zip, item.path);
|
|
881
|
+
if (content === void 0) continue;
|
|
882
|
+
derived.add(item.path).add(relsPathOf(item.path));
|
|
883
|
+
const key = keys.masterKey(item.id);
|
|
884
|
+
keys.masterPaths.set(key, item.path);
|
|
885
|
+
const rels = await zipText(zip, relsPathOf(item.path));
|
|
886
|
+
const { shell, shapes, connects } = splitContents(content, masterScope(key), keys);
|
|
887
|
+
masters.push({
|
|
888
|
+
key,
|
|
889
|
+
id: item.id,
|
|
890
|
+
xml: withMark(item),
|
|
891
|
+
path: item.path,
|
|
892
|
+
part: encoder.encode(shell),
|
|
893
|
+
...rels !== void 0 ? { rels } : {},
|
|
894
|
+
shapes,
|
|
895
|
+
connects
|
|
896
|
+
});
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
return { masters, mastersOpen, mastersClose };
|
|
901
|
+
}
|
|
902
|
+
async function snapshotRest(zip, derived, limit) {
|
|
903
|
+
const parts = /* @__PURE__ */ new Map();
|
|
904
|
+
const media = [];
|
|
905
|
+
const typesXml = await zipText(zip, CONTENT_TYPES) ?? "";
|
|
906
|
+
const mediaPaths = /* @__PURE__ */ new Set();
|
|
907
|
+
let total = 0;
|
|
908
|
+
for (const path of Object.keys(zip.files)) {
|
|
909
|
+
const file = zip.files[path];
|
|
910
|
+
if (file.dir || derived.has(path) || isLocalOnlyPart(path)) continue;
|
|
911
|
+
const data = await file.async("uint8array");
|
|
912
|
+
total += data.length;
|
|
913
|
+
if (total > limit) throw new Error("The package parts exceed the shared size limit.");
|
|
914
|
+
const declared = isMediaPart(path) ? declaredType(typesXml, path) : void 0;
|
|
915
|
+
if (declared) {
|
|
916
|
+
mediaPaths.add(path);
|
|
917
|
+
media.push({
|
|
918
|
+
path,
|
|
919
|
+
hash: contentHash(data),
|
|
920
|
+
ct: declared.type,
|
|
921
|
+
d: declared.byDefault,
|
|
922
|
+
data
|
|
923
|
+
});
|
|
924
|
+
} else parts.set(path, data);
|
|
925
|
+
}
|
|
926
|
+
const types = parts.get(CONTENT_TYPES);
|
|
927
|
+
if (types)
|
|
928
|
+
parts.set(
|
|
929
|
+
CONTENT_TYPES,
|
|
930
|
+
encoder.encode(
|
|
931
|
+
stripOverrides(decoder.decode(types), [PAGE_CONTENT_TYPE, MASTER_CONTENT_TYPE], mediaPaths)
|
|
932
|
+
)
|
|
933
|
+
);
|
|
934
|
+
return { parts, media };
|
|
457
935
|
}
|
|
936
|
+
|
|
937
|
+
// visio/collab/snapshot.ts
|
|
938
|
+
var DEFAULT_MAX_PART_BYTES = 48 * 1024 * 1024;
|
|
458
939
|
async function snapshotDrawing(bytes, keys, options = {}) {
|
|
459
940
|
const zip = await readZip(bytes);
|
|
460
941
|
const layout = await readLayout(zip);
|
|
461
942
|
if (!layout) throw new Error("The package has no Visio pages part.");
|
|
462
943
|
const pagesXml = await zipText(zip, layout.pagesPath) ?? "";
|
|
463
|
-
const local = await
|
|
944
|
+
const local = await readLocalItems(zip, layout.pagesPath, pagesXml, "Pages", "Page");
|
|
464
945
|
if (!local) throw new Error("The pages part cannot be split into pages.");
|
|
465
946
|
const derived = /* @__PURE__ */ new Set([layout.pagesPath, relsPathOf(layout.pagesPath)]);
|
|
466
|
-
const idToKey = new Map(local.
|
|
947
|
+
const idToKey = new Map(local.items.map((p) => [p.id, keys.pageKey(p.id)]));
|
|
467
948
|
const pages = [];
|
|
468
|
-
for (const page of local.
|
|
949
|
+
for (const page of local.items) {
|
|
469
950
|
const key = idToKey.get(page.id);
|
|
470
951
|
derived.add(page.path).add(relsPathOf(page.path));
|
|
471
952
|
const head = page.text.slice(0, scanContainer(page.text, "Page").openEnd);
|
|
472
953
|
const backId = attrOf(head, "BackPage");
|
|
473
|
-
const xml = page.text.slice(0, page.rel.start) + REL_MARK + page.text.slice(page.rel.end);
|
|
474
954
|
const content = await zipText(zip, page.path) ?? "";
|
|
475
955
|
const rels = await zipText(zip, relsPathOf(page.path));
|
|
476
|
-
const
|
|
477
|
-
const connectsSplit = splitList(shapesSplit.text, "Connects", CONNECTS_MARK, "Connect");
|
|
478
|
-
const owner = /* @__PURE__ */ new Map();
|
|
479
|
-
const shapes = [];
|
|
480
|
-
for (const text of shapesSplit.items) {
|
|
481
|
-
const ids = shapeIds(text);
|
|
482
|
-
const id = ids[0];
|
|
483
|
-
if (id === void 0) continue;
|
|
484
|
-
const shapeKey = keys.shapeKey(key, id);
|
|
485
|
-
for (const nested of ids) owner.set(nested, shapeKey);
|
|
486
|
-
shapes.push({ key: shapeKey, id, xml: text });
|
|
487
|
-
}
|
|
488
|
-
const connects = [];
|
|
489
|
-
for (const text of connectsSplit.items) {
|
|
490
|
-
const a = (name) => attrOf(text, name) ?? "";
|
|
491
|
-
const entry = {
|
|
492
|
-
fk: owner.get(a("FromSheet")) ?? "",
|
|
493
|
-
fi: a("FromSheet"),
|
|
494
|
-
tk: owner.get(a("ToSheet")) ?? "",
|
|
495
|
-
ti: a("ToSheet"),
|
|
496
|
-
fc: a("FromCell"),
|
|
497
|
-
tc: a("ToCell"),
|
|
498
|
-
fp: a("FromPart"),
|
|
499
|
-
tp: a("ToPart")
|
|
500
|
-
};
|
|
501
|
-
connects.push({
|
|
502
|
-
key: `${key}/${entry.fk}.${entry.fi}.${entry.fc}.${entry.fp}>${entry.tk}.${entry.ti}.${entry.tc}.${entry.tp}`,
|
|
503
|
-
entry
|
|
504
|
-
});
|
|
505
|
-
}
|
|
956
|
+
const { shell, shapes, connects } = splitContents(content, key, keys);
|
|
506
957
|
keys.pagePaths.set(key, page.path);
|
|
507
958
|
pages.push({
|
|
508
959
|
key,
|
|
509
960
|
id: page.id,
|
|
510
961
|
...backId !== void 0 && idToKey.has(backId) ? { back: idToKey.get(backId) } : {},
|
|
511
|
-
xml,
|
|
512
|
-
shell
|
|
962
|
+
xml: withMark(page),
|
|
963
|
+
shell,
|
|
513
964
|
...rels !== void 0 ? { rels } : {},
|
|
514
965
|
path: page.path,
|
|
515
966
|
shapes,
|
|
516
967
|
connects
|
|
517
968
|
});
|
|
518
969
|
}
|
|
519
|
-
const
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
let data = await file.async("uint8array");
|
|
526
|
-
if (path === CONTENT_TYPES) data = encoder.encode(stripPageOverrides(decoder.decode(data)));
|
|
527
|
-
total += data.length;
|
|
528
|
-
if (total > limit) throw new Error("The package parts exceed the shared size limit.");
|
|
529
|
-
parts.set(path, data);
|
|
530
|
-
}
|
|
970
|
+
const { masters, mastersOpen, mastersClose } = await snapshotMasters(zip, layout, keys, derived);
|
|
971
|
+
const { parts, media } = await snapshotRest(
|
|
972
|
+
zip,
|
|
973
|
+
derived,
|
|
974
|
+
options.maxPartBytes ?? DEFAULT_MAX_PART_BYTES
|
|
975
|
+
);
|
|
531
976
|
return {
|
|
532
977
|
pagesPath: layout.pagesPath,
|
|
533
978
|
pagesOpen: pagesXml.slice(0, local.box.openEnd),
|
|
534
979
|
pagesClose: pagesXml.slice(local.box.closeStart),
|
|
535
980
|
pages,
|
|
981
|
+
...mastersOpen !== void 0 && mastersClose !== void 0 && layout.mastersPath ? { mastersPath: layout.mastersPath, mastersOpen, mastersClose } : {},
|
|
982
|
+
masters,
|
|
983
|
+
media,
|
|
536
984
|
parts
|
|
537
985
|
};
|
|
538
986
|
}
|
|
539
987
|
|
|
540
|
-
// visio/collab/
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
const
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
let i = 0;
|
|
553
|
-
while (i < order.length) {
|
|
554
|
-
const known = kept[i];
|
|
555
|
-
if (known !== void 0) {
|
|
556
|
-
result.set(order[i], known);
|
|
557
|
-
i++;
|
|
558
|
-
continue;
|
|
559
|
-
}
|
|
560
|
-
let end = i;
|
|
561
|
-
while (end < order.length && kept[end] === void 0) end++;
|
|
562
|
-
const lo = i > 0 ? kept[i - 1] : void 0;
|
|
563
|
-
const hi = end < order.length ? kept[end] : void 0;
|
|
564
|
-
const count = end - i;
|
|
565
|
-
for (let j = 0; j < count; j++) {
|
|
566
|
-
const key = order[i + j];
|
|
567
|
-
if (lo !== void 0 && hi !== void 0)
|
|
568
|
-
result.set(key, lo + (hi - lo) * (j + 1) / (count + 1));
|
|
569
|
-
else if (lo !== void 0) result.set(key, lo + j + 1);
|
|
570
|
-
else if (hi !== void 0) result.set(key, hi - count + j);
|
|
571
|
-
else result.set(key, j + 1);
|
|
572
|
-
}
|
|
573
|
-
i = end;
|
|
574
|
-
}
|
|
575
|
-
return result;
|
|
576
|
-
}
|
|
577
|
-
function byPosition(items) {
|
|
578
|
-
return items.sort((a, b) => a.pos - b.pos || (a.key < b.key ? -1 : a.key > b.key ? 1 : 0));
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
// visio/collab/write.ts
|
|
582
|
-
var pageId = (key) => `p:${key}`;
|
|
583
|
-
var bodyId = (key) => `b:${key}`;
|
|
584
|
-
var shapeId = (page, key) => `s:${page}/${key}`;
|
|
585
|
-
var connectId = (key) => `c:${key}`;
|
|
586
|
-
var pageContent = (e) => JSON.stringify([e.id, e.back ?? null, canon(e.xml)]);
|
|
587
|
-
var bodyContent = (e) => JSON.stringify([canon(e.shell), e.rels ?? null]);
|
|
588
|
-
function writeSharedDrawing(shared, snapshot, keys) {
|
|
589
|
-
let writes = 0;
|
|
590
|
-
const set = (map, key, value) => {
|
|
591
|
-
if (setIfChanged(map, key, value)) writes++;
|
|
592
|
-
};
|
|
593
|
-
set(shared.meta, "v", SCHEMA_VERSION);
|
|
594
|
-
set(shared.meta, "pagesPath", snapshot.pagesPath);
|
|
595
|
-
set(shared.meta, "pagesOpen", snapshot.pagesOpen);
|
|
596
|
-
set(shared.meta, "pagesClose", snapshot.pagesClose);
|
|
597
|
-
const now = /* @__PURE__ */ new Map();
|
|
598
|
-
const changed = (id, content, room) => {
|
|
599
|
-
const base = keys.known.get(id);
|
|
600
|
-
return base === void 0 ? room !== content : base !== content;
|
|
601
|
-
};
|
|
602
|
-
const pagePos = assignPositions(
|
|
603
|
-
snapshot.pages.map((p) => p.key),
|
|
604
|
-
(key) => pageEntry(shared.pages.get(key))?.pos
|
|
605
|
-
);
|
|
606
|
-
for (const page of snapshot.pages) {
|
|
607
|
-
const room = pageEntry(shared.pages.get(page.key));
|
|
608
|
-
const content = pageContent(page);
|
|
609
|
-
now.set(pageId(page.key), content);
|
|
610
|
-
const own = changed(pageId(page.key), content, room && pageContent(room));
|
|
611
|
-
const source = own || !room ? page : room;
|
|
612
|
-
set(shared.pages, page.key, {
|
|
613
|
-
pos: pagePos.get(page.key),
|
|
614
|
-
id: source.id,
|
|
615
|
-
...source.back !== void 0 ? { back: source.back } : {},
|
|
616
|
-
xml: source.xml
|
|
617
|
-
});
|
|
618
|
-
const roomBody = bodyEntry(shared.bodies.get(page.key));
|
|
619
|
-
const bodyText = bodyContent(page);
|
|
620
|
-
now.set(bodyId(page.key), bodyText);
|
|
621
|
-
const ownBody = changed(bodyId(page.key), bodyText, roomBody && bodyContent(roomBody));
|
|
622
|
-
const body = ownBody || !roomBody ? page : roomBody;
|
|
623
|
-
set(shared.bodies, page.key, {
|
|
624
|
-
shell: body.shell,
|
|
625
|
-
...body.rels !== void 0 ? { rels: body.rels } : {}
|
|
626
|
-
});
|
|
627
|
-
const shapePos = assignPositions(
|
|
628
|
-
page.shapes.map((s) => s.key),
|
|
629
|
-
(key) => shapeEntry(shared.shapes.get(`${page.key}/${key}`))?.pos
|
|
630
|
-
);
|
|
631
|
-
for (const shape of page.shapes) {
|
|
632
|
-
const id = shapeId(page.key, shape.key);
|
|
633
|
-
const roomShape = shapeEntry(shared.shapes.get(`${page.key}/${shape.key}`));
|
|
634
|
-
const text = canon(shape.xml);
|
|
635
|
-
now.set(id, text);
|
|
636
|
-
const xml = changed(id, text, roomShape && canon(roomShape.xml)) || !roomShape ? shape.xml : roomShape.xml;
|
|
637
|
-
set(shared.shapes, `${page.key}/${shape.key}`, { pos: shapePos.get(shape.key), xml });
|
|
638
|
-
}
|
|
639
|
-
for (const connect of page.connects) {
|
|
640
|
-
now.set(connectId(connect.key), "");
|
|
641
|
-
if (!keys.known.has(connectId(connect.key)) || !shared.connects.has(connect.key))
|
|
642
|
-
set(shared.connects, connect.key, connect.entry);
|
|
988
|
+
// visio/collab/compose-lists.ts
|
|
989
|
+
var relTarget = (dir, path) => dir && path.startsWith(`${dir}/`) ? path.slice(dir.length + 1) : `/${path}`;
|
|
990
|
+
async function placeList(options) {
|
|
991
|
+
const { files, taken, localZip, items } = options;
|
|
992
|
+
const dir = dirName(options.listPath);
|
|
993
|
+
taken.add(options.listPath).add(relsPathOf(options.listPath));
|
|
994
|
+
const paths = /* @__PURE__ */ new Map();
|
|
995
|
+
for (const item of items) {
|
|
996
|
+
const known = options.known.get(item.key);
|
|
997
|
+
if (known && !taken.has(known) && localZip?.file(known)) {
|
|
998
|
+
paths.set(item.key, known);
|
|
999
|
+
taken.add(known);
|
|
643
1000
|
}
|
|
644
1001
|
}
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
writes++;
|
|
655
|
-
} else if (id.startsWith("s:")) {
|
|
656
|
-
const slash = name.indexOf("/");
|
|
657
|
-
const page = name.slice(0, slash);
|
|
658
|
-
if (!now.has(pageId(page))) continue;
|
|
659
|
-
shared.dead.set(name, true);
|
|
660
|
-
shared.shapes.delete(name);
|
|
661
|
-
keys.forgetShape(page, name.slice(slash + 1));
|
|
662
|
-
writes++;
|
|
663
|
-
} else if (id.startsWith("c:") && shared.connects.has(name)) {
|
|
664
|
-
shared.connects.delete(name);
|
|
665
|
-
writes++;
|
|
666
|
-
}
|
|
1002
|
+
let counter = 0;
|
|
1003
|
+
for (const item of items) {
|
|
1004
|
+
if (paths.has(item.key)) continue;
|
|
1005
|
+
let path;
|
|
1006
|
+
do
|
|
1007
|
+
path = `${dir ? `${dir}/` : ""}${options.stem}${++counter}.xml`;
|
|
1008
|
+
while (taken.has(path) || localZip?.file(path));
|
|
1009
|
+
paths.set(item.key, path);
|
|
1010
|
+
taken.add(path);
|
|
667
1011
|
}
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
1012
|
+
const others = parseRelationships(
|
|
1013
|
+
localZip ? await zipText(localZip, relsPathOf(options.listPath)) : void 0
|
|
1014
|
+
).filter((r) => r.type !== options.relType);
|
|
1015
|
+
const usedIds = new Set(others.map((r) => r.id));
|
|
1016
|
+
let nextRel = 0;
|
|
1017
|
+
const rels = [];
|
|
1018
|
+
const elements = [];
|
|
1019
|
+
for (const item of items) {
|
|
1020
|
+
const path = paths.get(item.key);
|
|
1021
|
+
let id;
|
|
1022
|
+
do
|
|
1023
|
+
id = `rId${++nextRel}`;
|
|
1024
|
+
while (usedIds.has(id));
|
|
1025
|
+
usedIds.add(id);
|
|
1026
|
+
rels.push(
|
|
1027
|
+
`<Relationship Id="${id}" Type="${options.relType}" Target="${escapeAttr(relTarget(dir, path))}"/>`
|
|
1028
|
+
);
|
|
1029
|
+
const rel = `<Rel xmlns:r="${REL_NS}" r:id="${id}"/>`;
|
|
1030
|
+
elements.push(
|
|
1031
|
+
item.xml.includes(REL_MARK) ? item.xml.replace(REL_MARK, () => rel) : item.xml.slice(0, item.xml.lastIndexOf("</")) + rel + item.xml.slice(item.xml.lastIndexOf("</"))
|
|
1032
|
+
);
|
|
1033
|
+
files.set(path, item.part);
|
|
1034
|
+
if (item.rels !== void 0) files.set(relsPathOf(path), encoder.encode(item.rels));
|
|
674
1035
|
}
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
1036
|
+
files.set(options.listPath, encoder.encode(options.open + elements.join("") + options.close));
|
|
1037
|
+
files.set(
|
|
1038
|
+
relsPathOf(options.listPath),
|
|
1039
|
+
encoder.encode(
|
|
1040
|
+
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">' + others.map((r) => r.text).join("") + rels.join("") + "</Relationships>"
|
|
1041
|
+
)
|
|
1042
|
+
);
|
|
1043
|
+
return paths;
|
|
682
1044
|
}
|
|
683
1045
|
|
|
684
1046
|
// visio/collab/compose.ts
|
|
@@ -694,32 +1056,51 @@ function connectXml(item) {
|
|
|
694
1056
|
];
|
|
695
1057
|
return `<Connect ${attrs.filter(([, v]) => v !== "").map(([k, v]) => `${k}="${escapeAttr(v)}"`).join(" ")}/>`;
|
|
696
1058
|
}
|
|
697
|
-
function
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
return shell.replace(SHAPES_MARK, () => page.shapes.map((s) => s.xml).join("")).replace(CONNECTS_MARK, () => page.connects.map(connectXml).join(""));
|
|
706
|
-
}
|
|
707
|
-
function relTarget(pagesDir, path) {
|
|
708
|
-
return pagesDir && path.startsWith(`${pagesDir}/`) ? path.slice(pagesDir.length + 1) : `/${path}`;
|
|
1059
|
+
function contentsXml(shell, root, shapesXml, hasShapes, connects) {
|
|
1060
|
+
const outer = scanContainer(shell, root);
|
|
1061
|
+
if (hasShapes && !shell.includes(SHAPES_MARK) && outer && !outer.selfClosing)
|
|
1062
|
+
shell = shell.slice(0, outer.openEnd) + `<Shapes>${SHAPES_MARK}</Shapes>` + shell.slice(outer.openEnd);
|
|
1063
|
+
const outer2 = scanContainer(shell, root);
|
|
1064
|
+
if (connects.length && !shell.includes(CONNECTS_MARK) && outer2 && !outer2.selfClosing)
|
|
1065
|
+
shell = shell.slice(0, outer2.closeStart) + `<Connects>${CONNECTS_MARK}</Connects>` + shell.slice(outer2.closeStart);
|
|
1066
|
+
return shell.replace(SHAPES_MARK, () => shapesXml).replace(CONNECTS_MARK, () => connects.map(connectXml).join(""));
|
|
709
1067
|
}
|
|
1068
|
+
var pagePartXml = (page) => contentsXml(
|
|
1069
|
+
page.body.shell,
|
|
1070
|
+
"PageContents",
|
|
1071
|
+
page.shapesXml,
|
|
1072
|
+
page.shapes.length > 0,
|
|
1073
|
+
page.connects
|
|
1074
|
+
);
|
|
1075
|
+
var masterPartXml = (master) => contentsXml(
|
|
1076
|
+
decoder.decode(fromBase64(master.part)),
|
|
1077
|
+
"MasterContents",
|
|
1078
|
+
master.shapesXml,
|
|
1079
|
+
master.shapes.length > 0,
|
|
1080
|
+
master.connects
|
|
1081
|
+
);
|
|
710
1082
|
async function composeDrawing(drawing, local, keys, options = {}) {
|
|
711
1083
|
const localZip = local ? await readZip(local) : void 0;
|
|
712
1084
|
const files = /* @__PURE__ */ new Map();
|
|
713
1085
|
const prints = /* @__PURE__ */ new Map();
|
|
714
1086
|
let total = 0;
|
|
715
1087
|
const limit = options.maxPartBytes ?? 48 * 1024 * 1024;
|
|
716
|
-
|
|
717
|
-
|
|
1088
|
+
const cache = keys.cache.parts;
|
|
1089
|
+
const decode = (path, b64) => {
|
|
1090
|
+
const hit = cache.get(path);
|
|
1091
|
+
const data = hit && hit.b64 === b64 ? hit.data : fromBase64(b64);
|
|
1092
|
+
if (!hit || hit.b64 !== b64) cache.set(path, { b64, data });
|
|
718
1093
|
total += data.length;
|
|
719
1094
|
if (total > limit) throw new Error("The shared parts exceed the size limit.");
|
|
1095
|
+
return data;
|
|
1096
|
+
};
|
|
1097
|
+
for (const [path, b64] of drawing.parts) {
|
|
1098
|
+
const data = decode(path, b64);
|
|
720
1099
|
files.set(path, data);
|
|
721
1100
|
prints.set(path, fingerprint(data));
|
|
722
1101
|
}
|
|
1102
|
+
for (const path of [...cache.keys()])
|
|
1103
|
+
if (!drawing.parts.has(path) && !path.startsWith("media:")) cache.delete(path);
|
|
723
1104
|
if (localZip)
|
|
724
1105
|
for (const path of Object.keys(localZip.files)) {
|
|
725
1106
|
const file = localZip.files[path];
|
|
@@ -727,6 +1108,10 @@ async function composeDrawing(drawing, local, keys, options = {}) {
|
|
|
727
1108
|
files.set(path, await file.async("uint8array"));
|
|
728
1109
|
}
|
|
729
1110
|
let contentTypes = files.get(CONTENT_TYPES) !== void 0 ? decoder.decode(files.get(CONTENT_TYPES)) : (localZip && await zipText(localZip, CONTENT_TYPES)) ?? DEFAULT_CONTENT_TYPES;
|
|
1111
|
+
for (const item of drawing.media) {
|
|
1112
|
+
files.set(item.path, decode(`media:${item.path}`, item.data));
|
|
1113
|
+
contentTypes = ensureType(contentTypes, item.path, item.declared);
|
|
1114
|
+
}
|
|
730
1115
|
for (const [path, data] of [...files]) {
|
|
731
1116
|
if (!path.endsWith(".rels") || typeof data === "string") continue;
|
|
732
1117
|
const source = path.replace(/(^|\/)_rels\/([^/]+)\.rels$/, "$1$2");
|
|
@@ -745,65 +1130,56 @@ async function composeDrawing(drawing, local, keys, options = {}) {
|
|
|
745
1130
|
});
|
|
746
1131
|
if (next !== text) files.set(path, encoder.encode(next));
|
|
747
1132
|
}
|
|
748
|
-
const
|
|
749
|
-
const
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
localZip
|
|
774
|
-
)
|
|
775
|
-
|
|
776
|
-
let
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
1133
|
+
const taken = new Set(files.keys());
|
|
1134
|
+
const pageCache = keys.cache.pageParts;
|
|
1135
|
+
const pageItems = drawing.pages.map((page) => {
|
|
1136
|
+
const hit = pageCache.get(page.key);
|
|
1137
|
+
const bytes2 = hit && hit.sig === page.signature ? hit.bytes : encoder.encode(pagePartXml(page));
|
|
1138
|
+
pageCache.set(page.key, { sig: page.signature, bytes: bytes2 });
|
|
1139
|
+
return {
|
|
1140
|
+
key: page.key,
|
|
1141
|
+
xml: page.xml,
|
|
1142
|
+
part: bytes2,
|
|
1143
|
+
...page.body.rels !== void 0 ? { rels: page.body.rels } : {}
|
|
1144
|
+
};
|
|
1145
|
+
});
|
|
1146
|
+
for (const key of [...pageCache.keys()])
|
|
1147
|
+
if (!drawing.pages.some((p) => p.key === key)) pageCache.delete(key);
|
|
1148
|
+
const pagePaths = await placeList({
|
|
1149
|
+
listPath: drawing.pagesPath,
|
|
1150
|
+
open: drawing.pagesOpen,
|
|
1151
|
+
close: drawing.pagesClose,
|
|
1152
|
+
relType: PAGE_TYPE,
|
|
1153
|
+
stem: "page",
|
|
1154
|
+
items: pageItems,
|
|
1155
|
+
known: keys.pagePaths,
|
|
1156
|
+
files,
|
|
1157
|
+
taken,
|
|
1158
|
+
localZip
|
|
1159
|
+
});
|
|
1160
|
+
contentTypes = withPageOverrides(contentTypes, [...pagePaths.values()]);
|
|
1161
|
+
let masterPaths = /* @__PURE__ */ new Map();
|
|
1162
|
+
if (drawing.mastersPath !== void 0) {
|
|
1163
|
+
masterPaths = await placeList({
|
|
1164
|
+
listPath: drawing.mastersPath,
|
|
1165
|
+
open: drawing.mastersOpen ?? "<Masters>",
|
|
1166
|
+
close: drawing.mastersClose ?? "</Masters>",
|
|
1167
|
+
relType: MASTER_TYPE,
|
|
1168
|
+
stem: "master",
|
|
1169
|
+
items: drawing.masters.map((m) => ({
|
|
1170
|
+
key: m.key,
|
|
1171
|
+
xml: m.xml,
|
|
1172
|
+
part: encoder.encode(masterPartXml(m)),
|
|
1173
|
+
...m.rels !== void 0 ? { rels: m.rels } : {}
|
|
1174
|
+
})),
|
|
1175
|
+
known: keys.masterPaths,
|
|
1176
|
+
files,
|
|
1177
|
+
taken,
|
|
1178
|
+
localZip
|
|
1179
|
+
});
|
|
1180
|
+
contentTypes = withOverrides(contentTypes, MASTER_CONTENT_TYPE, [...masterPaths.values()]);
|
|
795
1181
|
}
|
|
796
|
-
files.set(
|
|
797
|
-
drawing.pagesPath,
|
|
798
|
-
encoder.encode(drawing.pagesOpen + pageXml.join("") + drawing.pagesClose)
|
|
799
|
-
);
|
|
800
|
-
files.set(
|
|
801
|
-
relsPathOf(drawing.pagesPath),
|
|
802
|
-
encoder.encode(
|
|
803
|
-
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">' + others.map((r) => r.text).join("") + pageRels.join("") + "</Relationships>"
|
|
804
|
-
)
|
|
805
|
-
);
|
|
806
|
-
files.set(CONTENT_TYPES, encoder.encode(withPageOverrides(contentTypes, [...paths.values()])));
|
|
1182
|
+
files.set(CONTENT_TYPES, encoder.encode(contentTypes));
|
|
807
1183
|
const zip = new JSZip__default.default();
|
|
808
1184
|
const names = [...files.keys()].sort(
|
|
809
1185
|
(a, b) => a === CONTENT_TYPES ? -1 : b === CONTENT_TYPES ? 1 : 0
|
|
@@ -812,24 +1188,58 @@ async function composeDrawing(drawing, local, keys, options = {}) {
|
|
|
812
1188
|
const bytes = await zip.generateAsync({ type: "uint8array", compression: "STORE" });
|
|
813
1189
|
const commit = () => {
|
|
814
1190
|
const pageIds = /* @__PURE__ */ new Map();
|
|
815
|
-
const
|
|
1191
|
+
const shapeIds = /* @__PURE__ */ new Map();
|
|
1192
|
+
const masterIds = /* @__PURE__ */ new Map();
|
|
816
1193
|
const known = /* @__PURE__ */ new Map();
|
|
1194
|
+
const recordShapes = (scope, shapes, connects) => {
|
|
1195
|
+
shapeIds.set(scope, new Map(shapes.map((s) => [s.id, s.key])));
|
|
1196
|
+
for (const shape of shapes) {
|
|
1197
|
+
known.set(shapeId(scope, shape.key), shellContent(shape));
|
|
1198
|
+
for (const [path, entry] of shape.entries)
|
|
1199
|
+
known.set(cellId(scope, shape.key, path), entryContent(entry));
|
|
1200
|
+
}
|
|
1201
|
+
for (const connect of connects) known.set(connectId(connect.key), "");
|
|
1202
|
+
};
|
|
817
1203
|
keys.pagePaths.clear();
|
|
1204
|
+
keys.masterPaths.clear();
|
|
1205
|
+
keys.mediaKeys.clear();
|
|
818
1206
|
for (const page of drawing.pages) {
|
|
819
1207
|
pageIds.set(page.id, page.key);
|
|
820
|
-
keys.pagePaths.set(page.key,
|
|
1208
|
+
keys.pagePaths.set(page.key, pagePaths.get(page.key));
|
|
821
1209
|
known.set(pageId(page.key), pageContent(page));
|
|
822
1210
|
known.set(bodyId(page.key), bodyContent(page.body));
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
1211
|
+
recordShapes(page.key, page.shapes, page.connects);
|
|
1212
|
+
}
|
|
1213
|
+
for (const master of drawing.masters) {
|
|
1214
|
+
masterIds.set(master.id, master.key);
|
|
1215
|
+
recordShapes(masterScope(master.key), master.shapes, master.connects);
|
|
1216
|
+
const path = masterPaths.get(master.key);
|
|
1217
|
+
if (path) keys.masterPaths.set(master.key, path);
|
|
1218
|
+
known.set(
|
|
1219
|
+
masterId(master.key),
|
|
1220
|
+
masterContent({ ...master, print: fingerprint(fromBase64(master.part)) })
|
|
1221
|
+
);
|
|
826
1222
|
}
|
|
827
|
-
|
|
1223
|
+
for (const item of drawing.media) {
|
|
1224
|
+
known.set(mediaId(item.key), "");
|
|
1225
|
+
keys.mediaKeys.set(item.path, item.key);
|
|
1226
|
+
}
|
|
1227
|
+
keys.reset(pageIds, shapeIds, masterIds);
|
|
828
1228
|
keys.known = known;
|
|
829
1229
|
keys.partPrints.clear();
|
|
830
1230
|
for (const [path, print] of prints) keys.partPrints.set(path, print);
|
|
831
1231
|
};
|
|
832
|
-
return { bytes, commit };
|
|
1232
|
+
return { bytes, signature: drawing.signature, commit };
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
// visio/collab/fixups.ts
|
|
1236
|
+
function applyFixups(shared, fixups) {
|
|
1237
|
+
let changed = 0;
|
|
1238
|
+
for (const fixup of fixups) {
|
|
1239
|
+
const map = fixup.map === "renum" ? shared.renum : shared.cells;
|
|
1240
|
+
if (setIfChanged(map, fixup.key, fixup.value)) changed++;
|
|
1241
|
+
}
|
|
1242
|
+
return changed;
|
|
833
1243
|
}
|
|
834
1244
|
|
|
835
1245
|
// visio/collab/keys.ts
|
|
@@ -843,15 +1253,34 @@ var DrawingKeys = class {
|
|
|
843
1253
|
seeding = false;
|
|
844
1254
|
#pages = /* @__PURE__ */ new Map();
|
|
845
1255
|
#shapes = /* @__PURE__ */ new Map();
|
|
1256
|
+
#masters = /* @__PURE__ */ new Map();
|
|
846
1257
|
/** Content of each entry this peer last wrote or applied, to tell a local edit or deletion from a change it has not applied yet. */
|
|
847
1258
|
known = /* @__PURE__ */ new Map();
|
|
848
1259
|
/** Fingerprints of the parts this peer last wrote or applied. */
|
|
849
1260
|
partPrints = /* @__PURE__ */ new Map();
|
|
850
1261
|
/** The part path of each page key in the local package. */
|
|
851
1262
|
pagePaths = /* @__PURE__ */ new Map();
|
|
1263
|
+
/** The part path of each master key in the local package. */
|
|
1264
|
+
masterPaths = /* @__PURE__ */ new Map();
|
|
1265
|
+
/** The room key of each media path in the local package. */
|
|
1266
|
+
mediaKeys = /* @__PURE__ */ new Map();
|
|
1267
|
+
/** Serialised page parts and decoded shared parts of the last rebuild, to skip unchanged work. */
|
|
1268
|
+
cache = {
|
|
1269
|
+
pageParts: /* @__PURE__ */ new Map(),
|
|
1270
|
+
parts: /* @__PURE__ */ new Map()
|
|
1271
|
+
};
|
|
1272
|
+
/**
|
|
1273
|
+
* What was last applied to the editor: the drawing signature, the editor version it produced,
|
|
1274
|
+
* the signature of everything but page content and the content signature of each page.
|
|
1275
|
+
*/
|
|
1276
|
+
applied;
|
|
852
1277
|
mint() {
|
|
853
1278
|
return `${this.tag}.${(++this.#counter).toString(36)}`;
|
|
854
1279
|
}
|
|
1280
|
+
/** A fresh id for one write batch: entries written together share it. */
|
|
1281
|
+
batch() {
|
|
1282
|
+
return this.mint();
|
|
1283
|
+
}
|
|
855
1284
|
pageKey(id) {
|
|
856
1285
|
let key = this.#pages.get(id);
|
|
857
1286
|
if (key === void 0) {
|
|
@@ -870,6 +1299,14 @@ var DrawingKeys = class {
|
|
|
870
1299
|
}
|
|
871
1300
|
return key;
|
|
872
1301
|
}
|
|
1302
|
+
masterKey(id) {
|
|
1303
|
+
let key = this.#masters.get(id);
|
|
1304
|
+
if (key === void 0) {
|
|
1305
|
+
key = this.seeding ? `s${id}` : this.mint();
|
|
1306
|
+
this.#masters.set(id, key);
|
|
1307
|
+
}
|
|
1308
|
+
return key;
|
|
1309
|
+
}
|
|
873
1310
|
findPage(id) {
|
|
874
1311
|
return this.#pages.get(id);
|
|
875
1312
|
}
|
|
@@ -883,38 +1320,355 @@ var DrawingKeys = class {
|
|
|
883
1320
|
for (const [id, k] of map) if (k === key) map.delete(id);
|
|
884
1321
|
}
|
|
885
1322
|
}
|
|
1323
|
+
forgetMaster(key) {
|
|
1324
|
+
for (const [id, k] of this.#masters) if (k === key) this.#masters.delete(id);
|
|
1325
|
+
this.#shapes.delete(masterScope(key));
|
|
1326
|
+
this.masterPaths.delete(key);
|
|
1327
|
+
}
|
|
886
1328
|
/** Replaces the id-to-key tables with those of a freshly composed package. */
|
|
887
|
-
reset(pages, shapes) {
|
|
1329
|
+
reset(pages, shapes, masters = /* @__PURE__ */ new Map()) {
|
|
888
1330
|
this.#pages.clear();
|
|
889
1331
|
this.#shapes.clear();
|
|
1332
|
+
this.#masters.clear();
|
|
890
1333
|
for (const [id, key] of pages) this.#pages.set(id, key);
|
|
891
1334
|
for (const [page, map] of shapes) this.#shapes.set(page, new Map(map));
|
|
1335
|
+
for (const [id, key] of masters) this.#masters.set(id, key);
|
|
892
1336
|
}
|
|
893
1337
|
};
|
|
894
1338
|
|
|
895
|
-
// visio/collab/
|
|
1339
|
+
// visio/collab/order.ts
|
|
1340
|
+
function assignPositions(order, current) {
|
|
1341
|
+
const result = /* @__PURE__ */ new Map();
|
|
1342
|
+
const kept = [];
|
|
1343
|
+
let last = -Infinity;
|
|
1344
|
+
for (const key of order) {
|
|
1345
|
+
const pos = current(key);
|
|
1346
|
+
if (pos !== void 0 && pos > last) {
|
|
1347
|
+
kept.push(pos);
|
|
1348
|
+
last = pos;
|
|
1349
|
+
} else kept.push(void 0);
|
|
1350
|
+
}
|
|
1351
|
+
let i = 0;
|
|
1352
|
+
while (i < order.length) {
|
|
1353
|
+
const known = kept[i];
|
|
1354
|
+
if (known !== void 0) {
|
|
1355
|
+
result.set(order[i], known);
|
|
1356
|
+
i++;
|
|
1357
|
+
continue;
|
|
1358
|
+
}
|
|
1359
|
+
let end = i;
|
|
1360
|
+
while (end < order.length && kept[end] === void 0) end++;
|
|
1361
|
+
const lo = i > 0 ? kept[i - 1] : void 0;
|
|
1362
|
+
const hi = end < order.length ? kept[end] : void 0;
|
|
1363
|
+
const count = end - i;
|
|
1364
|
+
for (let j = 0; j < count; j++) {
|
|
1365
|
+
const key = order[i + j];
|
|
1366
|
+
if (lo !== void 0 && hi !== void 0)
|
|
1367
|
+
result.set(key, lo + (hi - lo) * (j + 1) / (count + 1));
|
|
1368
|
+
else if (lo !== void 0) result.set(key, lo + j + 1);
|
|
1369
|
+
else if (hi !== void 0) result.set(key, hi - count + j);
|
|
1370
|
+
else result.set(key, j + 1);
|
|
1371
|
+
}
|
|
1372
|
+
i = end;
|
|
1373
|
+
}
|
|
1374
|
+
return result;
|
|
1375
|
+
}
|
|
1376
|
+
function byPosition(items) {
|
|
1377
|
+
return items.sort((a, b) => a.pos - b.pos || (a.key < b.key ? -1 : a.key > b.key ? 1 : 0));
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
// visio/collab/read-ids.ts
|
|
896
1381
|
var compare = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
897
1382
|
var numeric = (id) => /^\d+$/.test(id) ? Number(id) : 0;
|
|
1383
|
+
function assignIds(items) {
|
|
1384
|
+
const effective = (item) => item.fixed ?? item.id;
|
|
1385
|
+
let max = Math.max(0, ...items.map((item) => numeric(effective(item))));
|
|
1386
|
+
const order = [...items].sort(
|
|
1387
|
+
(a, b) => Number(b.fixed !== void 0) - Number(a.fixed !== void 0) || compare(a.key, b.key)
|
|
1388
|
+
);
|
|
1389
|
+
const used = /* @__PURE__ */ new Set();
|
|
1390
|
+
const ids = /* @__PURE__ */ new Map();
|
|
1391
|
+
const fresh = /* @__PURE__ */ new Map();
|
|
1392
|
+
for (const item of order) {
|
|
1393
|
+
let id = effective(item);
|
|
1394
|
+
if (used.has(id)) {
|
|
1395
|
+
id = String(++max);
|
|
1396
|
+
fresh.set(item.key, { from: item.id, to: id });
|
|
1397
|
+
}
|
|
1398
|
+
used.add(id);
|
|
1399
|
+
ids.set(item.key, id);
|
|
1400
|
+
}
|
|
1401
|
+
return { ids, fresh };
|
|
1402
|
+
}
|
|
1403
|
+
var fixedId = (renum, key, id) => {
|
|
1404
|
+
const pair = renum.get(key)?.i;
|
|
1405
|
+
return pair && pair[0] === id ? pair[1] : void 0;
|
|
1406
|
+
};
|
|
1407
|
+
function readRenum(shared) {
|
|
1408
|
+
const out = /* @__PURE__ */ new Map();
|
|
1409
|
+
for (const [key, value] of shared.renum) {
|
|
1410
|
+
const entry = renumEntry(value);
|
|
1411
|
+
if (entry) out.set(key, entry);
|
|
1412
|
+
}
|
|
1413
|
+
return out;
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
// visio/collab/read-util.ts
|
|
1417
|
+
function hashTexts(texts) {
|
|
1418
|
+
let a = 2166136261;
|
|
1419
|
+
let b = 16777619 ^ 2654435769;
|
|
1420
|
+
for (const text of texts) {
|
|
1421
|
+
for (let i = 0; i < text.length; i++) {
|
|
1422
|
+
const c = text.charCodeAt(i);
|
|
1423
|
+
a = Math.imul(a ^ c, 16777619);
|
|
1424
|
+
b = Math.imul(b + c, 2246822507) ^ b >>> 13;
|
|
1425
|
+
}
|
|
1426
|
+
a = Math.imul(a ^ 255, 16777619);
|
|
1427
|
+
b = Math.imul(b ^ 255, 3266489909);
|
|
1428
|
+
}
|
|
1429
|
+
return `${(a >>> 0).toString(16)}${(b >>> 0).toString(16)}`;
|
|
1430
|
+
}
|
|
1431
|
+
var split = (key, depth) => {
|
|
1432
|
+
const out = [];
|
|
1433
|
+
let from = 0;
|
|
1434
|
+
for (let i = 0; i < depth; i++) {
|
|
1435
|
+
const slash = key.indexOf("/", from);
|
|
1436
|
+
if (slash < 0) return void 0;
|
|
1437
|
+
out.push(key.slice(from, slash));
|
|
1438
|
+
from = slash + 1;
|
|
1439
|
+
}
|
|
1440
|
+
out.push(key.slice(from));
|
|
1441
|
+
return out;
|
|
1442
|
+
};
|
|
1443
|
+
var connectSignature = (connects) => connects.flatMap((c) => [c.from, c.to, c.entry.fc, c.entry.tc, c.entry.fp, c.entry.tp]);
|
|
1444
|
+
function resolveConnects(list, shapes) {
|
|
1445
|
+
const byKey = new Map(shapes.map((s) => [s.key, s]));
|
|
1446
|
+
const out = [];
|
|
1447
|
+
for (const item of [...list ?? []].sort((a, b) => compare(a.key, b.key))) {
|
|
1448
|
+
const { entry } = item;
|
|
1449
|
+
const from = entry.fk ? byKey.get(entry.fk) : void 0;
|
|
1450
|
+
const to = entry.tk ? byKey.get(entry.tk) : void 0;
|
|
1451
|
+
if (entry.fk && !from || entry.tk && !to) continue;
|
|
1452
|
+
out.push({ key: item.key, entry, from: from?.id ?? entry.fi, to: to?.id ?? entry.ti });
|
|
1453
|
+
}
|
|
1454
|
+
return out;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
// visio/collab/read-shapes.ts
|
|
898
1458
|
function setAttr(open, name, value) {
|
|
899
1459
|
return open.replace(
|
|
900
1460
|
new RegExp(String.raw`(\s${name}\s*=\s*)(?:"[^"]*"|'[^']*')`),
|
|
901
1461
|
(_m, head) => `${head}"${value}"`
|
|
902
1462
|
);
|
|
903
1463
|
}
|
|
904
|
-
function
|
|
905
|
-
if (!remap.size) return xml;
|
|
906
|
-
return xml.replace(
|
|
907
|
-
|
|
908
|
-
(tag) => tag.replace(/(\bID\s*=\s*)(["'])(\d+)\2/, (m, head, q, id) => {
|
|
1464
|
+
function renumberFormulas(xml, remap) {
|
|
1465
|
+
if (!remap.size || !xml.includes("Sheet.")) return xml;
|
|
1466
|
+
return xml.replace(/(\sF\s*=\s*)("[^"]*"|'[^']*')/g, (_m, head, value) => {
|
|
1467
|
+
const body = value.slice(1, -1).replace(/Sheet\.(\d+)(?!\d)/g, (m, id) => {
|
|
909
1468
|
const next = remap.get(id);
|
|
910
|
-
return next === void 0 ? m :
|
|
1469
|
+
return next === void 0 ? m : `Sheet.${next}`;
|
|
1470
|
+
});
|
|
1471
|
+
return `${head}${value[0]}${body}${value[0]}`;
|
|
1472
|
+
});
|
|
1473
|
+
}
|
|
1474
|
+
function resolveShapes(input) {
|
|
1475
|
+
const raw = /* @__PURE__ */ new Map();
|
|
1476
|
+
for (const [key, entry] of input.shapes) {
|
|
1477
|
+
const id = attrOf(entry.open, "ID");
|
|
1478
|
+
if (id !== void 0) raw.set(key, { entry, id });
|
|
1479
|
+
}
|
|
1480
|
+
const state = /* @__PURE__ */ new Map();
|
|
1481
|
+
const valid = (key, seen = /* @__PURE__ */ new Set()) => {
|
|
1482
|
+
const known = state.get(key);
|
|
1483
|
+
if (known !== void 0) return known;
|
|
1484
|
+
const item = raw.get(key);
|
|
1485
|
+
const parent = item?.entry.parent;
|
|
1486
|
+
let ok = !!item;
|
|
1487
|
+
if (ok && parent !== void 0) ok = !seen.has(key) && valid(parent, seen.add(key));
|
|
1488
|
+
state.set(key, ok);
|
|
1489
|
+
return ok;
|
|
1490
|
+
};
|
|
1491
|
+
const live = [...raw.keys()].filter((k) => valid(k)).sort(compare);
|
|
1492
|
+
const { ids: finalId, fresh: renumbered } = assignIds(
|
|
1493
|
+
live.map((key) => {
|
|
1494
|
+
const { id } = raw.get(key);
|
|
1495
|
+
return { key, id, fixed: fixedId(input.renum, key, id) };
|
|
911
1496
|
})
|
|
912
|
-
)
|
|
913
|
-
|
|
914
|
-
|
|
1497
|
+
);
|
|
1498
|
+
const batchRemap = /* @__PURE__ */ new Map();
|
|
1499
|
+
for (const [key, change] of renumbered) {
|
|
1500
|
+
const b = raw.get(key).entry.b;
|
|
1501
|
+
if (b === void 0) continue;
|
|
1502
|
+
const map = batchRemap.get(b) ?? /* @__PURE__ */ new Map();
|
|
1503
|
+
map.set(change.from, change.to);
|
|
1504
|
+
batchRemap.set(b, map);
|
|
1505
|
+
}
|
|
1506
|
+
const remapFor = (key) => {
|
|
1507
|
+
const out = new Map(batchRemap.get(raw.get(key).entry.b ?? "") ?? []);
|
|
1508
|
+
const chain = [];
|
|
1509
|
+
for (let k = key; k !== void 0; k = raw.get(k)?.entry.parent)
|
|
1510
|
+
chain.unshift(k);
|
|
1511
|
+
for (const k of chain) {
|
|
1512
|
+
const change = renumbered.get(k);
|
|
1513
|
+
if (change) out.set(change.from, change.to);
|
|
1514
|
+
}
|
|
1515
|
+
return out;
|
|
1516
|
+
};
|
|
1517
|
+
const children = /* @__PURE__ */ new Map();
|
|
1518
|
+
for (const key of live) {
|
|
1519
|
+
const parent = raw.get(key).entry.parent ?? "";
|
|
1520
|
+
children.set(parent, [...children.get(parent) ?? [], key]);
|
|
1521
|
+
}
|
|
1522
|
+
const sortSiblings = (keys) => keys.sort((a, b) => raw.get(a).entry.pos - raw.get(b).entry.pos || compare(a, b));
|
|
1523
|
+
const shapes = [];
|
|
1524
|
+
const fixups = [];
|
|
1525
|
+
const render = (key) => {
|
|
1526
|
+
const { entry } = raw.get(key);
|
|
1527
|
+
const id = finalId.get(key);
|
|
1528
|
+
const remap = remapFor(key);
|
|
1529
|
+
let open = setAttr(entry.open, "ID", id);
|
|
1530
|
+
const record = { ...input.renum.get(key) };
|
|
1531
|
+
let dirty = false;
|
|
1532
|
+
const change = renumbered.get(key);
|
|
1533
|
+
if (change) {
|
|
1534
|
+
record.i = [change.from, change.to];
|
|
1535
|
+
dirty = true;
|
|
1536
|
+
}
|
|
1537
|
+
const master = attrOf(open, "Master");
|
|
1538
|
+
const persisted = record.m && record.m[0] === master ? record.m[1] : void 0;
|
|
1539
|
+
const batched = master !== void 0 ? input.masterRemap.get(entry.b ?? "")?.get(master) : void 0;
|
|
1540
|
+
const next = persisted ?? batched;
|
|
1541
|
+
if (next !== void 0) open = setAttr(open, "Master", next);
|
|
1542
|
+
if (persisted === void 0 && batched !== void 0) {
|
|
1543
|
+
record.m = [master, batched];
|
|
1544
|
+
dirty = true;
|
|
1545
|
+
}
|
|
1546
|
+
if (dirty) fixups.push({ map: "renum", key: `${input.scope}/${key}`, value: record });
|
|
1547
|
+
const entries = /* @__PURE__ */ new Map();
|
|
1548
|
+
for (const [path, piece] of input.cells.get(key) ?? []) {
|
|
1549
|
+
const leaf = piece.xml !== void 0 && /(^|\/)c\/[^/]*$/.test(path);
|
|
1550
|
+
const xml2 = leaf ? renumberFormulas(piece.xml, remap) : void 0;
|
|
1551
|
+
if (xml2 !== void 0 && xml2 !== piece.xml) {
|
|
1552
|
+
const value = { ...piece, xml: xml2 };
|
|
1553
|
+
entries.set(path, value);
|
|
1554
|
+
fixups.push({ map: "cells", key: `${input.scope}/${key}/${path}`, value });
|
|
1555
|
+
} else entries.set(path, piece);
|
|
1556
|
+
}
|
|
1557
|
+
shapes.push({
|
|
1558
|
+
key,
|
|
1559
|
+
id,
|
|
1560
|
+
...entry.parent !== void 0 ? { parent: entry.parent } : {},
|
|
1561
|
+
open,
|
|
1562
|
+
entries
|
|
1563
|
+
});
|
|
1564
|
+
const inner = sortSiblings(children.get(key) ?? []).map(render).join("");
|
|
1565
|
+
return buildShape(open, entries, inner ? `<Shapes>${inner}</Shapes>` : "");
|
|
1566
|
+
};
|
|
1567
|
+
const xml = sortSiblings(children.get("") ?? []).map(render).join("");
|
|
1568
|
+
return { shapes, xml, fixups };
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
// visio/collab/read-parts.ts
|
|
1572
|
+
var compare2 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
1573
|
+
function resolveMasters(shared, renum) {
|
|
1574
|
+
const alive = [];
|
|
1575
|
+
for (const [key, value] of shared.masters) {
|
|
1576
|
+
const entry = masterEntry(value);
|
|
1577
|
+
if (entry) alive.push({ key, entry });
|
|
1578
|
+
}
|
|
1579
|
+
const { ids, fresh } = assignIds(
|
|
1580
|
+
alive.map(({ key, entry }) => ({
|
|
1581
|
+
key,
|
|
1582
|
+
id: entry.id,
|
|
1583
|
+
fixed: fixedId(renum, masterScope(key), entry.id)
|
|
1584
|
+
}))
|
|
1585
|
+
);
|
|
1586
|
+
const remap = /* @__PURE__ */ new Map();
|
|
1587
|
+
const fixups = [];
|
|
1588
|
+
for (const [key, change] of [...fresh].sort((a, b) => compare2(a[0], b[0]))) {
|
|
1589
|
+
const b = alive.find((m) => m.key === key).entry.b;
|
|
1590
|
+
if (b !== void 0) {
|
|
1591
|
+
const map = remap.get(b) ?? /* @__PURE__ */ new Map();
|
|
1592
|
+
map.set(change.from, change.to);
|
|
1593
|
+
remap.set(b, map);
|
|
1594
|
+
}
|
|
1595
|
+
fixups.push({
|
|
1596
|
+
map: "renum",
|
|
1597
|
+
key: masterScope(key),
|
|
1598
|
+
value: { ...renum.get(masterScope(key)), i: [change.from, change.to] }
|
|
1599
|
+
});
|
|
1600
|
+
}
|
|
1601
|
+
alive.sort((a, b) => a.entry.pos - b.entry.pos || compare2(a.key, b.key));
|
|
1602
|
+
return {
|
|
1603
|
+
masters: alive.map(({ key, entry }) => {
|
|
1604
|
+
const id = ids.get(key);
|
|
1605
|
+
const open = /^<[^>]*>/.exec(entry.xml)?.[0];
|
|
1606
|
+
return {
|
|
1607
|
+
key,
|
|
1608
|
+
id,
|
|
1609
|
+
xml: open ? setAttr(open, "ID", id) + entry.xml.slice(open.length) : entry.xml,
|
|
1610
|
+
part: entry.part,
|
|
1611
|
+
...entry.rels !== void 0 ? { rels: entry.rels } : {}
|
|
1612
|
+
};
|
|
1613
|
+
}),
|
|
1614
|
+
remap,
|
|
1615
|
+
fixups
|
|
1616
|
+
};
|
|
1617
|
+
}
|
|
1618
|
+
function resolveMedia(shared) {
|
|
1619
|
+
const items = [...shared.media].flatMap(([key, value]) => {
|
|
1620
|
+
const entry = mediaEntry(value);
|
|
1621
|
+
const data = entry ? str(shared.blobs.get(entry.hash)) : void 0;
|
|
1622
|
+
return entry && data !== void 0 ? [{ key, entry, data }] : [];
|
|
1623
|
+
}).sort((a, b) => compare2(a.key, b.key));
|
|
1624
|
+
const taken = /* @__PURE__ */ new Set();
|
|
1625
|
+
const first = /* @__PURE__ */ new Map();
|
|
1626
|
+
for (const item of items) if (!first.has(item.entry.path)) first.set(item.entry.path, item.key);
|
|
1627
|
+
for (const path of first.keys()) taken.add(path);
|
|
1628
|
+
const renames = /* @__PURE__ */ new Map();
|
|
1629
|
+
const media = [];
|
|
1630
|
+
for (const { key, entry, data } of items) {
|
|
1631
|
+
let path = entry.path;
|
|
1632
|
+
if (first.get(entry.path) !== key) {
|
|
1633
|
+
const dot = path.lastIndexOf(".");
|
|
1634
|
+
const stem = dot > path.lastIndexOf("/") ? path.slice(0, dot) : path;
|
|
1635
|
+
const ext = dot > path.lastIndexOf("/") ? path.slice(dot) : "";
|
|
1636
|
+
path = `${stem}-${entry.hash.slice(0, 8)}${ext}`;
|
|
1637
|
+
for (let n = 2; taken.has(path); n++) path = `${stem}-${entry.hash.slice(0, 8)}-${n}${ext}`;
|
|
1638
|
+
taken.add(path);
|
|
1639
|
+
if (entry.b !== void 0) {
|
|
1640
|
+
const map = renames.get(entry.b) ?? /* @__PURE__ */ new Map();
|
|
1641
|
+
map.set(entry.path, path);
|
|
1642
|
+
renames.set(entry.b, map);
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
media.push({
|
|
1646
|
+
key,
|
|
1647
|
+
path,
|
|
1648
|
+
hash: entry.hash,
|
|
1649
|
+
declared: { type: entry.ct, byDefault: entry.d },
|
|
1650
|
+
data
|
|
1651
|
+
});
|
|
1652
|
+
}
|
|
1653
|
+
return { media, renames };
|
|
1654
|
+
}
|
|
1655
|
+
function renameTargets(rels, baseDir, renames) {
|
|
1656
|
+
return rels.replace(/<(?:\w+:)?Relationship\b[^>]*>/g, (tag) => {
|
|
1657
|
+
const target = attrOf(tag, "Target");
|
|
1658
|
+
if (target === void 0 || attrOf(tag, "TargetMode") === "External") return tag;
|
|
1659
|
+
const next = renames.get(resolveTarget(baseDir, target));
|
|
1660
|
+
if (next === void 0) return tag;
|
|
1661
|
+
const value = target.startsWith("/") ? `/${next}` : relativeTarget(baseDir, next);
|
|
1662
|
+
return tag.replace(
|
|
1663
|
+
/(\sTarget\s*=\s*)(?:"[^"]*"|'[^']*')/,
|
|
1664
|
+
(_m, head) => `${head}"${value}"`
|
|
1665
|
+
);
|
|
915
1666
|
});
|
|
916
1667
|
}
|
|
1668
|
+
|
|
1669
|
+
// visio/collab/read.ts
|
|
917
1670
|
function readSharedDrawing(shared) {
|
|
1671
|
+
assertSchemaVersion(shared);
|
|
918
1672
|
if (isSharedDrawingEmpty(shared)) return void 0;
|
|
919
1673
|
const pagesPath = str(shared.meta.get("pagesPath"));
|
|
920
1674
|
const pagesOpen = str(shared.meta.get("pagesOpen"));
|
|
@@ -926,25 +1680,50 @@ function readSharedDrawing(shared) {
|
|
|
926
1680
|
const body = bodyEntry(shared.bodies.get(key));
|
|
927
1681
|
return entry && body ? [{ key, pos: entry.pos, entry, body }] : [];
|
|
928
1682
|
});
|
|
929
|
-
const
|
|
930
|
-
const
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
1683
|
+
const renum = readRenum(shared);
|
|
1684
|
+
const fixups = [];
|
|
1685
|
+
const { ids: pageIds, fresh: freshPages } = assignIds(
|
|
1686
|
+
alive.map((p) => ({
|
|
1687
|
+
key: p.key,
|
|
1688
|
+
id: p.entry.id,
|
|
1689
|
+
fixed: fixedId(renum, p.key, p.entry.id)
|
|
1690
|
+
}))
|
|
1691
|
+
);
|
|
1692
|
+
for (const [key, change] of [...freshPages].sort((a, b) => compare(a[0], b[0])))
|
|
1693
|
+
fixups.push({
|
|
1694
|
+
map: "renum",
|
|
1695
|
+
key,
|
|
1696
|
+
value: { ...renum.get(key), i: [change.from, change.to] }
|
|
1697
|
+
});
|
|
938
1698
|
const shapesByPage = /* @__PURE__ */ new Map();
|
|
939
1699
|
for (const [full, value] of shared.shapes) {
|
|
940
|
-
const
|
|
941
|
-
if (
|
|
1700
|
+
const parts2 = split(full, 1);
|
|
1701
|
+
if (!parts2 || shared.dead.has(full)) continue;
|
|
942
1702
|
const entry = shapeEntry(value);
|
|
943
1703
|
if (!entry) continue;
|
|
944
|
-
const
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
1704
|
+
const map = shapesByPage.get(parts2[0]) ?? /* @__PURE__ */ new Map();
|
|
1705
|
+
map.set(parts2[1], entry);
|
|
1706
|
+
shapesByPage.set(parts2[0], map);
|
|
1707
|
+
}
|
|
1708
|
+
const cellsByPage = /* @__PURE__ */ new Map();
|
|
1709
|
+
for (const [full, value] of shared.cells) {
|
|
1710
|
+
const parts2 = split(full, 2);
|
|
1711
|
+
const entry = parts2 && cellEntry(value);
|
|
1712
|
+
if (!parts2 || !entry) continue;
|
|
1713
|
+
const [page, shape, path] = parts2;
|
|
1714
|
+
const shapes = cellsByPage.get(page) ?? /* @__PURE__ */ new Map();
|
|
1715
|
+
const cells = shapes.get(shape) ?? /* @__PURE__ */ new Map();
|
|
1716
|
+
cells.set(path, entry);
|
|
1717
|
+
shapes.set(shape, cells);
|
|
1718
|
+
cellsByPage.set(page, shapes);
|
|
1719
|
+
}
|
|
1720
|
+
const renumByScope = /* @__PURE__ */ new Map();
|
|
1721
|
+
for (const [full, entry] of renum) {
|
|
1722
|
+
const parts2 = split(full, 1);
|
|
1723
|
+
if (!parts2) continue;
|
|
1724
|
+
const map = renumByScope.get(parts2[0]) ?? /* @__PURE__ */ new Map();
|
|
1725
|
+
map.set(parts2[1], entry);
|
|
1726
|
+
renumByScope.set(parts2[0], map);
|
|
948
1727
|
}
|
|
949
1728
|
const connectsByPage = /* @__PURE__ */ new Map();
|
|
950
1729
|
for (const [full, value] of shared.connects) {
|
|
@@ -955,24 +1734,25 @@ function readSharedDrawing(shared) {
|
|
|
955
1734
|
list.push({ key: full, entry });
|
|
956
1735
|
connectsByPage.set(full.slice(0, slash), list);
|
|
957
1736
|
}
|
|
1737
|
+
const { masters, remap: masterRemap, fixups: masterFixups } = resolveMasters(shared, renum);
|
|
1738
|
+
fixups.push(...masterFixups);
|
|
1739
|
+
const { media, renames } = resolveMedia(shared);
|
|
1740
|
+
const mastersPath = str(shared.meta.get("mastersPath"));
|
|
1741
|
+
const mastersOpen = str(shared.meta.get("mastersOpen"));
|
|
1742
|
+
const mastersClose = str(shared.meta.get("mastersClose"));
|
|
1743
|
+
const pagesDir = dirName(pagesPath);
|
|
958
1744
|
const pages = [];
|
|
959
1745
|
for (const page of byPosition(alive)) {
|
|
960
1746
|
const finalId = pageIds.get(page.key);
|
|
961
|
-
const
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
key: item.key,
|
|
971
|
-
entry,
|
|
972
|
-
from: from?.remap.get(entry.fi) ?? entry.fi,
|
|
973
|
-
to: to?.remap.get(entry.ti) ?? entry.ti
|
|
974
|
-
});
|
|
975
|
-
}
|
|
1747
|
+
const resolved = resolveShapes({
|
|
1748
|
+
scope: page.key,
|
|
1749
|
+
shapes: shapesByPage.get(page.key) ?? /* @__PURE__ */ new Map(),
|
|
1750
|
+
cells: cellsByPage.get(page.key) ?? /* @__PURE__ */ new Map(),
|
|
1751
|
+
renum: renumByScope.get(page.key) ?? /* @__PURE__ */ new Map(),
|
|
1752
|
+
masterRemap
|
|
1753
|
+
});
|
|
1754
|
+
fixups.push(...resolved.fixups);
|
|
1755
|
+
const connects = resolveConnects(connectsByPage.get(page.key), resolved.shapes);
|
|
976
1756
|
let xml = page.entry.xml;
|
|
977
1757
|
const open = /^<[^>]*>/.exec(xml)?.[0];
|
|
978
1758
|
if (open) {
|
|
@@ -981,46 +1761,360 @@ function readSharedDrawing(shared) {
|
|
|
981
1761
|
if (back !== void 0) next = setAttr(next, "BackPage", back);
|
|
982
1762
|
xml = next + xml.slice(open.length);
|
|
983
1763
|
}
|
|
1764
|
+
const rename = page.body.b !== void 0 ? renames.get(page.body.b) : void 0;
|
|
1765
|
+
const body = rename && page.body.rels !== void 0 ? { ...page.body, rels: renameTargets(page.body.rels, pagesDir, rename) } : page.body;
|
|
1766
|
+
const contentSignature = hashTexts([
|
|
1767
|
+
body.shell,
|
|
1768
|
+
body.rels ?? "\0",
|
|
1769
|
+
resolved.xml,
|
|
1770
|
+
...connectSignature(connects)
|
|
1771
|
+
]);
|
|
984
1772
|
pages.push({
|
|
985
1773
|
key: page.key,
|
|
986
1774
|
id: finalId,
|
|
987
1775
|
...page.entry.back !== void 0 ? { back: page.entry.back } : {},
|
|
988
1776
|
xml,
|
|
989
|
-
body
|
|
990
|
-
shapes,
|
|
991
|
-
|
|
1777
|
+
body,
|
|
1778
|
+
shapes: resolved.shapes,
|
|
1779
|
+
shapesXml: resolved.xml,
|
|
1780
|
+
connects,
|
|
1781
|
+
signature: hashTexts([xml, contentSignature]),
|
|
1782
|
+
contentSignature
|
|
992
1783
|
});
|
|
993
1784
|
}
|
|
1785
|
+
const mastersDir = mastersPath !== void 0 ? dirName(mastersPath) : pagesDir;
|
|
1786
|
+
const finalMasters = masters.map((m) => {
|
|
1787
|
+
const batch = shared.masters.get(m.key)?.b;
|
|
1788
|
+
const rename = typeof batch === "string" ? renames.get(batch) : void 0;
|
|
1789
|
+
const scope = masterScope(m.key);
|
|
1790
|
+
const resolved = resolveShapes({
|
|
1791
|
+
scope,
|
|
1792
|
+
shapes: shapesByPage.get(scope) ?? /* @__PURE__ */ new Map(),
|
|
1793
|
+
cells: cellsByPage.get(scope) ?? /* @__PURE__ */ new Map(),
|
|
1794
|
+
renum: renumByScope.get(scope) ?? /* @__PURE__ */ new Map(),
|
|
1795
|
+
masterRemap: /* @__PURE__ */ new Map()
|
|
1796
|
+
});
|
|
1797
|
+
fixups.push(...resolved.fixups);
|
|
1798
|
+
return {
|
|
1799
|
+
...m,
|
|
1800
|
+
...rename && m.rels !== void 0 ? { rels: renameTargets(m.rels, mastersDir, rename) } : {},
|
|
1801
|
+
shapes: resolved.shapes,
|
|
1802
|
+
shapesXml: resolved.xml,
|
|
1803
|
+
connects: resolveConnects(connectsByPage.get(scope), resolved.shapes)
|
|
1804
|
+
};
|
|
1805
|
+
});
|
|
994
1806
|
const parts = /* @__PURE__ */ new Map();
|
|
995
1807
|
for (const [path, value] of shared.parts) if (typeof value === "string") parts.set(path, value);
|
|
996
|
-
|
|
1808
|
+
const baseSignature = hashTexts([
|
|
1809
|
+
pagesPath,
|
|
1810
|
+
pagesOpen,
|
|
1811
|
+
pagesClose,
|
|
1812
|
+
mastersPath ?? "",
|
|
1813
|
+
mastersOpen ?? "",
|
|
1814
|
+
mastersClose ?? "",
|
|
1815
|
+
...pages.map((p) => `${p.key}:${p.id}:${p.xml}`),
|
|
1816
|
+
...finalMasters.flatMap((m) => [
|
|
1817
|
+
m.key,
|
|
1818
|
+
m.id,
|
|
1819
|
+
m.xml,
|
|
1820
|
+
m.part,
|
|
1821
|
+
m.rels ?? "\0",
|
|
1822
|
+
m.shapesXml,
|
|
1823
|
+
...connectSignature(m.connects)
|
|
1824
|
+
]),
|
|
1825
|
+
...media.flatMap((m) => [m.path, m.hash, m.declared.type, String(m.declared.byDefault)]),
|
|
1826
|
+
...[...parts].flatMap(([path, data]) => [path, data])
|
|
1827
|
+
]);
|
|
1828
|
+
const signature = hashTexts([
|
|
1829
|
+
baseSignature,
|
|
1830
|
+
...pages.map((p) => `${p.key}:${p.contentSignature}`)
|
|
1831
|
+
]);
|
|
1832
|
+
return {
|
|
1833
|
+
pagesPath,
|
|
1834
|
+
pagesOpen,
|
|
1835
|
+
pagesClose,
|
|
1836
|
+
pages,
|
|
1837
|
+
...mastersPath !== void 0 && mastersOpen !== void 0 && mastersClose !== void 0 ? { mastersPath, mastersOpen, mastersClose } : {},
|
|
1838
|
+
masters: finalMasters,
|
|
1839
|
+
media,
|
|
1840
|
+
parts,
|
|
1841
|
+
signature,
|
|
1842
|
+
baseSignature,
|
|
1843
|
+
fixups
|
|
1844
|
+
};
|
|
997
1845
|
}
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
const
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1846
|
+
|
|
1847
|
+
// visio/collab/write-shapes.ts
|
|
1848
|
+
function syncEntry(ctx, map, mapKey, id, content, room, roomContent, local, stamp = false) {
|
|
1849
|
+
ctx.now.set(id, content);
|
|
1850
|
+
const base = ctx.keys.known.get(id);
|
|
1851
|
+
const own = base === void 0 ? !room || roomContent() !== content : base !== content;
|
|
1852
|
+
if (own || !room) {
|
|
1853
|
+
const value = local();
|
|
1854
|
+
ctx.write(map, mapKey, stamp ? { ...value, b: ctx.batch } : value);
|
|
1855
|
+
} else {
|
|
1856
|
+
const pos = local().pos;
|
|
1857
|
+
ctx.write(map, mapKey, pos === void 0 ? room : { ...room, pos });
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
function groupPositions(items, current) {
|
|
1861
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1862
|
+
for (const item of items) groups.set(item.group, [...groups.get(item.group) ?? [], item.key]);
|
|
1863
|
+
const out = /* @__PURE__ */ new Map();
|
|
1864
|
+
for (const list of groups.values())
|
|
1865
|
+
for (const [key, pos] of assignPositions(list, current)) out.set(key, pos);
|
|
1866
|
+
return out;
|
|
1867
|
+
}
|
|
1868
|
+
function syncConnects(ctx, connects) {
|
|
1869
|
+
for (const connect of connects) {
|
|
1870
|
+
ctx.now.set(connectId(connect.key), "");
|
|
1871
|
+
if (!ctx.keys.known.has(connectId(connect.key)) || !ctx.shared.connects.has(connect.key))
|
|
1872
|
+
ctx.write(ctx.shared.connects, connect.key, connect.entry);
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
function syncShapes(ctx, page) {
|
|
1876
|
+
const { shared } = ctx;
|
|
1877
|
+
const shapePos = groupPositions(
|
|
1878
|
+
page.shapes.map((s) => ({ key: s.key, group: s.parent ?? "" })),
|
|
1879
|
+
(key) => shapeEntry(shared.shapes.get(`${page.key}/${key}`))?.pos
|
|
1880
|
+
);
|
|
1881
|
+
for (const shape of page.shapes) {
|
|
1882
|
+
const full = `${page.key}/${shape.key}`;
|
|
1883
|
+
const room = shapeEntry(shared.shapes.get(full));
|
|
1884
|
+
const parent = shape.parent;
|
|
1885
|
+
syncEntry(
|
|
1886
|
+
ctx,
|
|
1887
|
+
shared.shapes,
|
|
1888
|
+
full,
|
|
1889
|
+
shapeId(page.key, shape.key),
|
|
1890
|
+
shellContent({ parent, open: shape.open }),
|
|
1891
|
+
room,
|
|
1892
|
+
() => shellContent(room),
|
|
1893
|
+
() => ({
|
|
1894
|
+
pos: shapePos.get(shape.key),
|
|
1895
|
+
...parent !== void 0 ? { parent } : {},
|
|
1896
|
+
open: shape.open,
|
|
1897
|
+
b: room?.b ?? ctx.batch
|
|
1898
|
+
})
|
|
1899
|
+
);
|
|
1900
|
+
const piecePos = groupPositions(
|
|
1901
|
+
shape.pieces.map((p) => ({ key: p.path, group: p.parent })),
|
|
1902
|
+
(path) => cellEntry(shared.cells.get(`${full}/${path}`))?.pos
|
|
1903
|
+
);
|
|
1904
|
+
for (const piece of shape.pieces) {
|
|
1905
|
+
const cellKey = `${full}/${piece.path}`;
|
|
1906
|
+
const roomCell = cellEntry(shared.cells.get(cellKey));
|
|
1907
|
+
const local = () => ({
|
|
1908
|
+
pos: piecePos.get(piece.path),
|
|
1909
|
+
...piece.kind === "leaf" ? { xml: piece.text } : { open: piece.text }
|
|
1910
|
+
});
|
|
1911
|
+
syncEntry(
|
|
1912
|
+
ctx,
|
|
1913
|
+
shared.cells,
|
|
1914
|
+
cellKey,
|
|
1915
|
+
cellId(page.key, shape.key, piece.path),
|
|
1916
|
+
entryContent(piece.kind === "leaf" ? { xml: piece.text } : { open: piece.text }),
|
|
1917
|
+
roomCell,
|
|
1918
|
+
() => entryContent(roomCell),
|
|
1919
|
+
local
|
|
1920
|
+
);
|
|
1007
1921
|
}
|
|
1008
|
-
const ids = item.ids.map((id) => remap.get(id) ?? id);
|
|
1009
|
-
for (const id of ids) used.add(id);
|
|
1010
|
-
done.set(item.key, {
|
|
1011
|
-
key: item.key,
|
|
1012
|
-
id: ids[0] ?? "",
|
|
1013
|
-
xml: renumberShape(item.xml, remap),
|
|
1014
|
-
remap,
|
|
1015
|
-
ids
|
|
1016
|
-
});
|
|
1017
1922
|
}
|
|
1018
|
-
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
// visio/collab/write-parts.ts
|
|
1926
|
+
var mediaKey = (hash, path) => `${hash}|${path}`;
|
|
1927
|
+
function syncMasters(ctx, snapshot) {
|
|
1928
|
+
const { shared } = ctx;
|
|
1929
|
+
const pos = assignPositions(
|
|
1930
|
+
snapshot.masters.map((m) => m.key),
|
|
1931
|
+
(key) => masterEntry(shared.masters.get(key))?.pos
|
|
1932
|
+
);
|
|
1933
|
+
for (const master of snapshot.masters) {
|
|
1934
|
+
const room = masterEntry(shared.masters.get(master.key));
|
|
1935
|
+
syncEntry(
|
|
1936
|
+
ctx,
|
|
1937
|
+
shared.masters,
|
|
1938
|
+
master.key,
|
|
1939
|
+
masterId(master.key),
|
|
1940
|
+
masterContent({ ...master, print: fingerprint(master.part) }),
|
|
1941
|
+
room,
|
|
1942
|
+
() => masterContent({
|
|
1943
|
+
...room,
|
|
1944
|
+
print: fingerprint(fromBase64(room.part))
|
|
1945
|
+
}),
|
|
1946
|
+
() => ({
|
|
1947
|
+
pos: pos.get(master.key),
|
|
1948
|
+
id: master.id,
|
|
1949
|
+
xml: master.xml,
|
|
1950
|
+
part: toBase64(master.part),
|
|
1951
|
+
...master.rels !== void 0 ? { rels: master.rels } : {}
|
|
1952
|
+
}),
|
|
1953
|
+
true
|
|
1954
|
+
);
|
|
1955
|
+
syncShapes(ctx, { key: masterScope(master.key), shapes: master.shapes });
|
|
1956
|
+
syncConnects(ctx, master.connects);
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
function syncMedia(ctx, snapshot) {
|
|
1960
|
+
const { shared } = ctx;
|
|
1961
|
+
for (const item of snapshot.media) {
|
|
1962
|
+
const known = ctx.keys.mediaKeys.get(item.path);
|
|
1963
|
+
const key = known?.startsWith(`${item.hash}|`) ? known : mediaKey(item.hash, item.path);
|
|
1964
|
+
ctx.now.set(mediaId(key), "");
|
|
1965
|
+
if (!mediaEntry(shared.media.get(key))) {
|
|
1966
|
+
ctx.write(shared.media, key, {
|
|
1967
|
+
path: item.path,
|
|
1968
|
+
hash: item.hash,
|
|
1969
|
+
ct: item.ct,
|
|
1970
|
+
d: item.d,
|
|
1971
|
+
b: ctx.batch
|
|
1972
|
+
});
|
|
1973
|
+
shared.blobs.set(item.hash, toBase64(item.data));
|
|
1974
|
+
} else if (!shared.blobs.has(item.hash)) shared.blobs.set(item.hash, toBase64(item.data));
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
function syncParts(ctx, snapshot) {
|
|
1978
|
+
const { shared, keys } = ctx;
|
|
1979
|
+
for (const [path, data] of snapshot.parts) {
|
|
1980
|
+
const print = fingerprint(data);
|
|
1981
|
+
if (keys.partPrints.get(path) === print) continue;
|
|
1982
|
+
ctx.write(shared.parts, path, toBase64(data));
|
|
1983
|
+
keys.partPrints.set(path, print);
|
|
1984
|
+
}
|
|
1985
|
+
let removed = 0;
|
|
1986
|
+
for (const path of [...keys.partPrints.keys()])
|
|
1987
|
+
if (!snapshot.parts.has(path)) {
|
|
1988
|
+
shared.parts.delete(path);
|
|
1989
|
+
keys.partPrints.delete(path);
|
|
1990
|
+
removed++;
|
|
1991
|
+
}
|
|
1992
|
+
return removed;
|
|
1993
|
+
}
|
|
1994
|
+
|
|
1995
|
+
// visio/collab/write.ts
|
|
1996
|
+
function removeScope(shared, name) {
|
|
1997
|
+
shared.renum.delete(name);
|
|
1998
|
+
for (const map of [shared.shapes, shared.cells, shared.connects, shared.renum])
|
|
1999
|
+
for (const key of [...map.keys()]) if (key.startsWith(`${name}/`)) map.delete(key);
|
|
2000
|
+
}
|
|
2001
|
+
function removePage(shared, name) {
|
|
2002
|
+
shared.dead.set(name, true);
|
|
2003
|
+
for (const map of [shared.pages, shared.bodies]) map.delete(name);
|
|
2004
|
+
removeScope(shared, name);
|
|
2005
|
+
}
|
|
2006
|
+
function writeSharedDrawing(shared, snapshot, keys) {
|
|
2007
|
+
assertSchemaVersion(shared);
|
|
2008
|
+
let writes = 0;
|
|
2009
|
+
const write = (map, key, value) => {
|
|
2010
|
+
if (setIfChanged(map, key, value)) writes++;
|
|
2011
|
+
};
|
|
2012
|
+
const now = /* @__PURE__ */ new Map();
|
|
2013
|
+
const ctx = { shared, keys, now, batch: keys.batch(), write };
|
|
2014
|
+
write(shared.meta, "v", SCHEMA_VERSION);
|
|
2015
|
+
write(shared.meta, "pagesPath", snapshot.pagesPath);
|
|
2016
|
+
write(shared.meta, "pagesOpen", snapshot.pagesOpen);
|
|
2017
|
+
write(shared.meta, "pagesClose", snapshot.pagesClose);
|
|
2018
|
+
if (snapshot.mastersPath !== void 0) {
|
|
2019
|
+
write(shared.meta, "mastersPath", snapshot.mastersPath);
|
|
2020
|
+
write(shared.meta, "mastersOpen", snapshot.mastersOpen);
|
|
2021
|
+
write(shared.meta, "mastersClose", snapshot.mastersClose);
|
|
2022
|
+
}
|
|
2023
|
+
const pagePos = assignPositions(
|
|
2024
|
+
snapshot.pages.map((p) => p.key),
|
|
2025
|
+
(key) => pageEntry(shared.pages.get(key))?.pos
|
|
2026
|
+
);
|
|
2027
|
+
for (const page of snapshot.pages) {
|
|
2028
|
+
const room = pageEntry(shared.pages.get(page.key));
|
|
2029
|
+
syncEntry(
|
|
2030
|
+
ctx,
|
|
2031
|
+
shared.pages,
|
|
2032
|
+
page.key,
|
|
2033
|
+
pageId(page.key),
|
|
2034
|
+
pageContent(page),
|
|
2035
|
+
room,
|
|
2036
|
+
() => pageContent(room),
|
|
2037
|
+
() => ({
|
|
2038
|
+
pos: pagePos.get(page.key),
|
|
2039
|
+
id: page.id,
|
|
2040
|
+
...page.back !== void 0 ? { back: page.back } : {},
|
|
2041
|
+
xml: page.xml
|
|
2042
|
+
})
|
|
2043
|
+
);
|
|
2044
|
+
const roomBody = bodyEntry(shared.bodies.get(page.key));
|
|
2045
|
+
syncEntry(
|
|
2046
|
+
ctx,
|
|
2047
|
+
shared.bodies,
|
|
2048
|
+
page.key,
|
|
2049
|
+
bodyId(page.key),
|
|
2050
|
+
bodyContent(page),
|
|
2051
|
+
roomBody,
|
|
2052
|
+
() => bodyContent(roomBody),
|
|
2053
|
+
() => ({ shell: page.shell, ...page.rels !== void 0 ? { rels: page.rels } : {} }),
|
|
2054
|
+
true
|
|
2055
|
+
);
|
|
2056
|
+
syncShapes(ctx, page);
|
|
2057
|
+
syncConnects(ctx, page.connects);
|
|
2058
|
+
}
|
|
2059
|
+
syncMasters(ctx, snapshot);
|
|
2060
|
+
syncMedia(ctx, snapshot);
|
|
2061
|
+
for (const id of keys.known.keys()) {
|
|
2062
|
+
if (now.has(id)) continue;
|
|
2063
|
+
const name = id.slice(2);
|
|
2064
|
+
switch (id.slice(0, 2)) {
|
|
2065
|
+
case "p:":
|
|
2066
|
+
removePage(shared, name);
|
|
2067
|
+
keys.forgetPage(name);
|
|
2068
|
+
writes++;
|
|
2069
|
+
break;
|
|
2070
|
+
case "s:": {
|
|
2071
|
+
const slash = name.indexOf("/");
|
|
2072
|
+
const page = name.slice(0, slash);
|
|
2073
|
+
if (!now.has(page.startsWith(masterScope("")) ? masterId(page.slice(2)) : pageId(page)))
|
|
2074
|
+
break;
|
|
2075
|
+
shared.dead.set(name, true);
|
|
2076
|
+
shared.shapes.delete(name);
|
|
2077
|
+
keys.forgetShape(page, name.slice(slash + 1));
|
|
2078
|
+
writes++;
|
|
2079
|
+
break;
|
|
2080
|
+
}
|
|
2081
|
+
case "f:":
|
|
2082
|
+
if (shared.cells.has(name)) {
|
|
2083
|
+
shared.cells.delete(name);
|
|
2084
|
+
writes++;
|
|
2085
|
+
}
|
|
2086
|
+
break;
|
|
2087
|
+
case "c:":
|
|
2088
|
+
if (shared.connects.has(name)) {
|
|
2089
|
+
shared.connects.delete(name);
|
|
2090
|
+
writes++;
|
|
2091
|
+
}
|
|
2092
|
+
break;
|
|
2093
|
+
case "m:":
|
|
2094
|
+
if (shared.masters.has(name)) {
|
|
2095
|
+
shared.masters.delete(name);
|
|
2096
|
+
removeScope(shared, masterScope(name));
|
|
2097
|
+
writes++;
|
|
2098
|
+
}
|
|
2099
|
+
keys.forgetMaster(name);
|
|
2100
|
+
break;
|
|
2101
|
+
case "i:":
|
|
2102
|
+
if (shared.media.has(name)) {
|
|
2103
|
+
shared.media.delete(name);
|
|
2104
|
+
writes++;
|
|
2105
|
+
}
|
|
2106
|
+
break;
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
keys.known = now;
|
|
2110
|
+
writes += syncParts(ctx, snapshot);
|
|
2111
|
+
return writes;
|
|
1019
2112
|
}
|
|
1020
2113
|
|
|
1021
2114
|
// visio/collab/bind.ts
|
|
1022
2115
|
var VISIO_EDIT_ORIGIN = /* @__PURE__ */ Symbol("ooxml-core:visio:edit");
|
|
1023
2116
|
var VISIO_SYNC_ORIGIN = /* @__PURE__ */ Symbol("ooxml-core:visio:sync");
|
|
2117
|
+
var VISIO_FIXUP_ORIGIN = /* @__PURE__ */ Symbol("ooxml-core:visio:fixup");
|
|
1024
2118
|
function bindDrawingSession(host, editor, options = {}) {
|
|
1025
2119
|
const { doc } = host;
|
|
1026
2120
|
const shared = sharedDrawing(doc);
|
|
@@ -1040,6 +2134,12 @@ function bindDrawingSession(host, editor, options = {}) {
|
|
|
1040
2134
|
let settled = false;
|
|
1041
2135
|
let localDirty = false;
|
|
1042
2136
|
let remoteDirty = false;
|
|
2137
|
+
let incompatible = false;
|
|
2138
|
+
let queued = false;
|
|
2139
|
+
let queuedDone;
|
|
2140
|
+
const schedule = options.schedule ?? ((run) => {
|
|
2141
|
+
setTimeout(run, 0);
|
|
2142
|
+
});
|
|
1043
2143
|
let running;
|
|
1044
2144
|
const report = (error) => options.onError?.(error);
|
|
1045
2145
|
const publish = async () => {
|
|
@@ -1058,7 +2158,14 @@ function bindDrawingSession(host, editor, options = {}) {
|
|
|
1058
2158
|
const rebuild = async () => {
|
|
1059
2159
|
const resolved = readSharedDrawing(shared);
|
|
1060
2160
|
if (!resolved) return;
|
|
2161
|
+
if (resolved.fixups.length && host.canWrite())
|
|
2162
|
+
doc.transact(() => applyFixups(shared, resolved.fixups), VISIO_FIXUP_ORIGIN);
|
|
1061
2163
|
const version = editor.version();
|
|
2164
|
+
if (keys.applied?.signature === resolved.signature && keys.applied.version === version) return;
|
|
2165
|
+
const before = keys.applied;
|
|
2166
|
+
const change = before && before.version === version && before.base === resolved.baseSignature ? {
|
|
2167
|
+
pages: resolved.pages.filter((page) => before.pages.get(page.key) !== page.contentSignature).map((page) => page.id)
|
|
2168
|
+
} : void 0;
|
|
1062
2169
|
const composed = await composeDrawing(resolved, editor.exportBytes(), keys);
|
|
1063
2170
|
if (disposed) return;
|
|
1064
2171
|
if (editor.busy() || editor.version() !== version) {
|
|
@@ -1066,15 +2173,21 @@ function bindDrawingSession(host, editor, options = {}) {
|
|
|
1066
2173
|
return;
|
|
1067
2174
|
}
|
|
1068
2175
|
try {
|
|
1069
|
-
await editor.applyRemote(composed.bytes);
|
|
2176
|
+
await editor.applyRemote(composed.bytes, change);
|
|
1070
2177
|
} catch (error) {
|
|
1071
2178
|
if (editor.busy()) remoteDirty = true;
|
|
1072
2179
|
else report(error);
|
|
1073
2180
|
return;
|
|
1074
2181
|
}
|
|
1075
2182
|
composed.commit();
|
|
2183
|
+
keys.applied = {
|
|
2184
|
+
signature: composed.signature,
|
|
2185
|
+
version: editor.version(),
|
|
2186
|
+
base: resolved.baseSignature,
|
|
2187
|
+
pages: new Map(resolved.pages.map((page) => [page.key, page.contentSignature]))
|
|
2188
|
+
};
|
|
1076
2189
|
};
|
|
1077
|
-
const blocked = () => disposed || !settled || editor.busy();
|
|
2190
|
+
const blocked = () => disposed || incompatible || !settled || editor.busy();
|
|
1078
2191
|
const pending = () => !blocked() && (localDirty && host.canWrite() || remoteDirty && !localDirty);
|
|
1079
2192
|
const loop = async () => {
|
|
1080
2193
|
while (pending()) {
|
|
@@ -1087,6 +2200,7 @@ function bindDrawingSession(host, editor, options = {}) {
|
|
|
1087
2200
|
await rebuild();
|
|
1088
2201
|
}
|
|
1089
2202
|
} catch (error) {
|
|
2203
|
+
if (error instanceof SchemaVersionError) incompatible = true;
|
|
1090
2204
|
report(error);
|
|
1091
2205
|
}
|
|
1092
2206
|
}
|
|
@@ -1113,18 +2227,30 @@ function bindDrawingSession(host, editor, options = {}) {
|
|
|
1113
2227
|
}
|
|
1114
2228
|
pump();
|
|
1115
2229
|
};
|
|
2230
|
+
const queueRemote = () => {
|
|
2231
|
+
if (queued) return;
|
|
2232
|
+
queued = true;
|
|
2233
|
+
queuedDone = new Promise(
|
|
2234
|
+
(resolve) => schedule(() => {
|
|
2235
|
+
queued = false;
|
|
2236
|
+
remoteDirty = true;
|
|
2237
|
+
resolve();
|
|
2238
|
+
pump();
|
|
2239
|
+
})
|
|
2240
|
+
);
|
|
2241
|
+
};
|
|
1116
2242
|
const afterTransaction = (transaction) => {
|
|
1117
2243
|
if (disposed) return;
|
|
1118
2244
|
const origin = transaction.origin;
|
|
1119
|
-
if (origin === VISIO_EDIT_ORIGIN || origin === VISIO_SYNC_ORIGIN)
|
|
2245
|
+
if (origin === VISIO_EDIT_ORIGIN || origin === VISIO_SYNC_ORIGIN || origin === VISIO_FIXUP_ORIGIN)
|
|
2246
|
+
return;
|
|
1120
2247
|
const changed = transaction.changed;
|
|
1121
2248
|
if (!types.some((type) => changed.has(type))) return;
|
|
1122
2249
|
if (!settled) {
|
|
1123
2250
|
if (!isSharedDrawingEmpty(shared)) settle();
|
|
1124
2251
|
return;
|
|
1125
2252
|
}
|
|
1126
|
-
|
|
1127
|
-
pump();
|
|
2253
|
+
queueRemote();
|
|
1128
2254
|
};
|
|
1129
2255
|
doc.on("afterTransaction", afterTransaction);
|
|
1130
2256
|
const stops = [
|
|
@@ -1142,7 +2268,10 @@ function bindDrawingSession(host, editor, options = {}) {
|
|
|
1142
2268
|
];
|
|
1143
2269
|
if (host.synced || host.canWrite()) settle();
|
|
1144
2270
|
const idle = async () => {
|
|
1145
|
-
while (running)
|
|
2271
|
+
while (running || queued) {
|
|
2272
|
+
if (queued) await queuedDone;
|
|
2273
|
+
if (running) await running;
|
|
2274
|
+
}
|
|
1146
2275
|
};
|
|
1147
2276
|
const replay = async (kind) => {
|
|
1148
2277
|
await idle();
|
|
@@ -1174,17 +2303,25 @@ function bindDrawingSession(host, editor, options = {}) {
|
|
|
1174
2303
|
};
|
|
1175
2304
|
}
|
|
1176
2305
|
|
|
2306
|
+
exports.BLOBS = BLOBS;
|
|
1177
2307
|
exports.BODIES = BODIES;
|
|
2308
|
+
exports.CELLS = CELLS;
|
|
1178
2309
|
exports.CONNECTS = CONNECTS;
|
|
1179
2310
|
exports.DEAD = DEAD;
|
|
1180
2311
|
exports.DrawingKeys = DrawingKeys;
|
|
2312
|
+
exports.MASTERS = MASTERS;
|
|
2313
|
+
exports.MEDIA = MEDIA;
|
|
1181
2314
|
exports.META = META;
|
|
1182
2315
|
exports.PAGES = PAGES;
|
|
1183
2316
|
exports.PARTS = PARTS;
|
|
2317
|
+
exports.RENUM = RENUM;
|
|
1184
2318
|
exports.SCHEMA_VERSION = SCHEMA_VERSION;
|
|
1185
2319
|
exports.SHAPES = SHAPES;
|
|
2320
|
+
exports.SchemaVersionError = SchemaVersionError;
|
|
1186
2321
|
exports.VISIO_EDIT_ORIGIN = VISIO_EDIT_ORIGIN;
|
|
2322
|
+
exports.VISIO_FIXUP_ORIGIN = VISIO_FIXUP_ORIGIN;
|
|
1187
2323
|
exports.VISIO_SYNC_ORIGIN = VISIO_SYNC_ORIGIN;
|
|
2324
|
+
exports.applyFixups = applyFixups;
|
|
1188
2325
|
exports.bindDrawingSession = bindDrawingSession;
|
|
1189
2326
|
exports.composeDrawing = composeDrawing;
|
|
1190
2327
|
exports.isSharedDrawingEmpty = isSharedDrawingEmpty;
|