ooxml-core 1.22.0 → 1.24.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 +559 -339
- package/dist/automation/index.d.ts +1 -0
- package/dist/automation/index.d.ts.map +1 -1
- package/dist/automation/index.mjs +558 -340
- package/dist/automation/live.d.ts +89 -0
- package/dist/automation/live.d.ts.map +1 -0
- 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/docx/ui/customization.d.ts +30 -0
- package/dist/docx/ui/customization.d.ts.map +1 -0
- package/dist/docx/ui/index.cjs +51 -0
- package/dist/docx/ui/index.d.ts +1 -0
- package/dist/docx/ui/index.d.ts.map +1 -1
- package/dist/docx/ui/index.mjs +46 -1
- package/dist/embedding/backstage.d.ts +48 -0
- package/dist/embedding/backstage.d.ts.map +1 -0
- package/dist/embedding/capabilities.d.ts +60 -0
- package/dist/embedding/capabilities.d.ts.map +1 -0
- package/dist/embedding/customization.d.ts +32 -0
- package/dist/embedding/customization.d.ts.map +1 -0
- package/dist/embedding/index.cjs +229 -0
- package/dist/embedding/index.d.ts +7 -0
- package/dist/embedding/index.d.ts.map +1 -0
- package/dist/embedding/index.mjs +204 -0
- package/dist/embedding/menu-commands.d.ts +66 -0
- package/dist/embedding/menu-commands.d.ts.map +1 -0
- package/dist/embedding/regions.d.ts +58 -0
- package/dist/embedding/regions.d.ts.map +1 -0
- package/dist/embedding/storage.d.ts +111 -0
- package/dist/embedding/storage.d.ts.map +1 -0
- package/dist/index.cjs +233 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +233 -1
- 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 +1603 -361
- 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 +1596 -362
- package/dist/visio/collab/keys.d.ts +32 -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 +41 -0
- package/dist/visio/collab/pieces.d.ts.map +1 -0
- package/dist/visio/collab/read-ids.d.ts +35 -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 +34 -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/collab/zip-store.d.ts +4 -0
- package/dist/visio/collab/zip-store.d.ts.map +1 -0
- package/dist/visio/document-level.d.ts +57 -0
- package/dist/visio/document-level.d.ts.map +1 -0
- package/dist/visio/index.cjs +485 -333
- package/dist/visio/index.d.ts +2 -0
- package/dist/visio/index.d.ts.map +1 -1
- package/dist/visio/index.mjs +484 -334
- package/dist/visio/layers.d.ts +3 -0
- package/dist/visio/layers.d.ts.map +1 -1
- package/dist/visio/package.d.ts +9 -0
- package/dist/visio/package.d.ts.map +1 -1
- 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 +14 -0
- package/dist/visio/parser.d.ts.map +1 -1
- package/dist/visio/shape-metadata.d.ts +3 -0
- package/dist/visio/shape-metadata.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/contract.d.ts +27 -2
- package/dist/visio/ui/contract.d.ts.map +1 -1
- package/dist/visio/ui/customization.d.ts +46 -0
- package/dist/visio/ui/customization.d.ts.map +1 -0
- package/dist/visio/ui/index.cjs +460 -320
- package/dist/visio/ui/index.d.ts +1 -0
- package/dist/visio/ui/index.d.ts.map +1 -1
- package/dist/visio/ui/index.mjs +458 -321
- package/dist/xlsx/ui/commands.d.ts +2 -0
- package/dist/xlsx/ui/commands.d.ts.map +1 -1
- package/dist/xlsx/ui/customization.d.ts +49 -0
- package/dist/xlsx/ui/customization.d.ts.map +1 -0
- package/dist/xlsx/ui/index.cjs +39 -1
- package/dist/xlsx/ui/index.d.ts +1 -0
- package/dist/xlsx/ui/index.d.ts.map +1 -1
- package/dist/xlsx/ui/index.mjs +37 -2
- package/package.json +6 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var Y = require('yjs');
|
|
4
|
-
var JSZip = require('jszip');
|
|
5
4
|
var xmldom = require('@xmldom/xmldom');
|
|
5
|
+
var JSZip = require('jszip');
|
|
6
6
|
|
|
7
7
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
8
|
|
|
@@ -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 = 4;
|
|
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,59 @@ 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
|
+
const r = Array.isArray(value.r) && value.r.length % 2 === 0 && value.r.every((v) => typeof v === "string") ? value.r : void 0;
|
|
727
|
+
return {
|
|
728
|
+
pos,
|
|
729
|
+
...opt("xml", xml),
|
|
730
|
+
...opt("open", xml === void 0 ? open : void 0),
|
|
731
|
+
...r && r.length ? { r } : {}
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
function masterEntry(value) {
|
|
735
|
+
if (!isRecord(value)) return void 0;
|
|
736
|
+
const pos = num(value.pos);
|
|
737
|
+
const id = str(value.id);
|
|
738
|
+
const xml = str(value.xml);
|
|
739
|
+
const part = str(value.part);
|
|
740
|
+
if (pos === void 0 || id === void 0 || xml === void 0 || part === void 0)
|
|
741
|
+
return void 0;
|
|
742
|
+
return { pos, id, xml, part, ...opt("rels", str(value.rels)), ...opt("b", str(value.b)) };
|
|
743
|
+
}
|
|
744
|
+
function mediaEntry(value) {
|
|
745
|
+
if (!isRecord(value)) return void 0;
|
|
746
|
+
const path = str(value.path);
|
|
747
|
+
const hash = str(value.hash);
|
|
748
|
+
const ct = str(value.ct);
|
|
749
|
+
if (path === void 0 || hash === void 0 || ct === void 0) return void 0;
|
|
750
|
+
return { path, hash, ct, d: value.d === true, ...opt("b", str(value.b)) };
|
|
388
751
|
}
|
|
389
752
|
function connectEntry(value) {
|
|
390
753
|
if (!isRecord(value)) return void 0;
|
|
@@ -396,11 +759,15 @@ function connectEntry(value) {
|
|
|
396
759
|
}
|
|
397
760
|
return out;
|
|
398
761
|
}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
762
|
+
function renumEntry(value) {
|
|
763
|
+
if (!isRecord(value)) return void 0;
|
|
764
|
+
const pair = (v) => Array.isArray(v) && v.length === 2 && typeof v[0] === "string" && typeof v[1] === "string" ? [v[0], v[1]] : void 0;
|
|
765
|
+
const i = pair(value.i);
|
|
766
|
+
const m = pair(value.m);
|
|
767
|
+
return i || m ? { ...i ? { i } : {}, ...m ? { m } : {} } : void 0;
|
|
403
768
|
}
|
|
769
|
+
|
|
770
|
+
// visio/collab/snapshot-contents.ts
|
|
404
771
|
function splitList(text, name, mark, child) {
|
|
405
772
|
const box = scanContainer(text, name);
|
|
406
773
|
if (!box) return { text, items: [] };
|
|
@@ -416,6 +783,66 @@ function splitList(text, name, mark, child) {
|
|
|
416
783
|
}
|
|
417
784
|
return { text: text.slice(0, box.openEnd) + mark + text.slice(box.closeStart), items };
|
|
418
785
|
}
|
|
786
|
+
function formulaRefs(text, owner) {
|
|
787
|
+
const out = [];
|
|
788
|
+
const seen = /* @__PURE__ */ new Set();
|
|
789
|
+
for (const f of text.matchAll(/\sF\s*=\s*("[^"]*"|'[^']*')/g))
|
|
790
|
+
for (const m of f[1].matchAll(/Sheet\.(\d+)(?!\d)/g)) {
|
|
791
|
+
const id = m[1];
|
|
792
|
+
const key = owner.get(id);
|
|
793
|
+
if (key !== void 0 && !seen.has(id)) {
|
|
794
|
+
seen.add(id);
|
|
795
|
+
out.push(id, key);
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
return out;
|
|
799
|
+
}
|
|
800
|
+
function flatten(xml, parent, page, keys, out) {
|
|
801
|
+
const split2 = splitShape(xml);
|
|
802
|
+
const id = split2 ? attrOf(split2.open, "ID") : void 0;
|
|
803
|
+
if (!split2 || id === void 0) return;
|
|
804
|
+
const key = keys.shapeKey(page, id);
|
|
805
|
+
out.push({
|
|
806
|
+
key,
|
|
807
|
+
id,
|
|
808
|
+
...parent !== void 0 ? { parent } : {},
|
|
809
|
+
open: split2.open,
|
|
810
|
+
pieces: split2.pieces
|
|
811
|
+
});
|
|
812
|
+
for (const nested of split2.nested) flatten(nested, key, page, keys, out);
|
|
813
|
+
}
|
|
814
|
+
function splitContents(content, scope, keys) {
|
|
815
|
+
const shapesSplit = splitList(content, "Shapes", SHAPES_MARK, "Shape");
|
|
816
|
+
const connectsSplit = splitList(shapesSplit.text, "Connects", CONNECTS_MARK, "Connect");
|
|
817
|
+
const shapes = [];
|
|
818
|
+
for (const text of shapesSplit.items) flatten(text, void 0, scope, keys, shapes);
|
|
819
|
+
const owner = new Map(shapes.map((s) => [s.id, s.key]));
|
|
820
|
+
for (const shape of shapes)
|
|
821
|
+
for (const piece of shape.pieces)
|
|
822
|
+
if (piece.kind === "leaf") {
|
|
823
|
+
const refs = formulaRefs(piece.text, owner);
|
|
824
|
+
if (refs.length) piece.refs = refs;
|
|
825
|
+
}
|
|
826
|
+
const connects = [];
|
|
827
|
+
for (const text of connectsSplit.items) {
|
|
828
|
+
const a = (name) => attrOf(text, name) ?? "";
|
|
829
|
+
const entry = {
|
|
830
|
+
fk: owner.get(a("FromSheet")) ?? "",
|
|
831
|
+
fi: a("FromSheet"),
|
|
832
|
+
tk: owner.get(a("ToSheet")) ?? "",
|
|
833
|
+
ti: a("ToSheet"),
|
|
834
|
+
fc: a("FromCell"),
|
|
835
|
+
tc: a("ToCell"),
|
|
836
|
+
fp: a("FromPart"),
|
|
837
|
+
tp: a("ToPart")
|
|
838
|
+
};
|
|
839
|
+
connects.push({
|
|
840
|
+
key: `${scope}/${entry.fk}.${entry.fi}.${entry.fc}.${entry.fp}>${entry.tk}.${entry.ti}.${entry.tc}.${entry.tp}`,
|
|
841
|
+
entry
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
return { shell: connectsSplit.text, shapes, connects };
|
|
845
|
+
}
|
|
419
846
|
var readZip = (bytes) => JSZip__default.default.loadAsync(bytes);
|
|
420
847
|
var zipText = async (zip, path) => zip.file(path)?.async("string");
|
|
421
848
|
async function readLayout(zip) {
|
|
@@ -426,19 +853,25 @@ async function readLayout(zip) {
|
|
|
426
853
|
const documentPath = resolveTarget("", root.target);
|
|
427
854
|
const rels = parseRelationships(await zipText(zip, relsPathOf(documentPath)));
|
|
428
855
|
const pages = rels.find((r) => r.type.endsWith("/pages"));
|
|
429
|
-
|
|
856
|
+
const masters = rels.find((r) => r.type.endsWith("/masters"));
|
|
857
|
+
const dir = dirName(documentPath);
|
|
858
|
+
return pages ? {
|
|
859
|
+
documentPath,
|
|
860
|
+
pagesPath: resolveTarget(dir, pages.target),
|
|
861
|
+
...masters ? { mastersPath: resolveTarget(dir, masters.target) } : {}
|
|
862
|
+
} : void 0;
|
|
430
863
|
}
|
|
431
|
-
async function
|
|
432
|
-
const box = scanContainer(
|
|
864
|
+
async function readLocalItems(zip, listPath, xml, container, child) {
|
|
865
|
+
const box = scanContainer(xml, container);
|
|
433
866
|
if (!box) return void 0;
|
|
434
867
|
const rels = new Map(
|
|
435
|
-
parseRelationships(await zipText(zip, relsPathOf(
|
|
868
|
+
parseRelationships(await zipText(zip, relsPathOf(listPath))).map((r) => [r.id, r])
|
|
436
869
|
);
|
|
437
|
-
const
|
|
870
|
+
const items = [];
|
|
438
871
|
for (const span of box.children) {
|
|
439
|
-
if (span.name !==
|
|
440
|
-
const text =
|
|
441
|
-
const inner = scanContainer(text,
|
|
872
|
+
if (span.name !== child) continue;
|
|
873
|
+
const text = xml.slice(span.start, span.end);
|
|
874
|
+
const inner = scanContainer(text, child);
|
|
442
875
|
const relSpan = inner?.children.find((c) => c.name === "Rel");
|
|
443
876
|
if (!inner || !relSpan) return void 0;
|
|
444
877
|
const relTag = text.slice(relSpan.start, relSpan.openEnd);
|
|
@@ -446,239 +879,268 @@ async function readLocalPages(zip, layout, pagesXml) {
|
|
|
446
879
|
const target = rid ? rels.get(rid)?.target : void 0;
|
|
447
880
|
const id = attrOf(text.slice(0, inner.openEnd), "ID");
|
|
448
881
|
if (target === void 0 || id === void 0) return void 0;
|
|
449
|
-
|
|
882
|
+
items.push({
|
|
450
883
|
id,
|
|
451
884
|
text,
|
|
452
|
-
path: resolveTarget(dirName(
|
|
885
|
+
path: resolveTarget(dirName(listPath), target),
|
|
453
886
|
rel: { start: relSpan.start, end: relSpan.end }
|
|
454
887
|
});
|
|
455
888
|
}
|
|
456
|
-
return { box,
|
|
889
|
+
return { box, items };
|
|
457
890
|
}
|
|
891
|
+
var withMark = (item) => item.text.slice(0, item.rel.start) + REL_MARK + item.text.slice(item.rel.end);
|
|
892
|
+
|
|
893
|
+
// visio/collab/snapshot-parts.ts
|
|
894
|
+
async function snapshotMasters(zip, layout, keys, derived) {
|
|
895
|
+
const masters = [];
|
|
896
|
+
let mastersOpen;
|
|
897
|
+
let mastersClose;
|
|
898
|
+
if (layout.mastersPath) {
|
|
899
|
+
const listXml = await zipText(zip, layout.mastersPath) ?? "";
|
|
900
|
+
const list = await readLocalItems(zip, layout.mastersPath, listXml, "Masters", "Master");
|
|
901
|
+
if (list) {
|
|
902
|
+
derived.add(layout.mastersPath).add(relsPathOf(layout.mastersPath));
|
|
903
|
+
mastersOpen = listXml.slice(0, list.box.openEnd);
|
|
904
|
+
mastersClose = listXml.slice(list.box.closeStart);
|
|
905
|
+
for (const item of list.items) {
|
|
906
|
+
const content = await zipText(zip, item.path);
|
|
907
|
+
if (content === void 0) continue;
|
|
908
|
+
derived.add(item.path).add(relsPathOf(item.path));
|
|
909
|
+
const key = keys.masterKey(item.id);
|
|
910
|
+
keys.masterPaths.set(key, item.path);
|
|
911
|
+
const rels = await zipText(zip, relsPathOf(item.path));
|
|
912
|
+
const { shell, shapes, connects } = splitContents(content, masterScope(key), keys);
|
|
913
|
+
masters.push({
|
|
914
|
+
key,
|
|
915
|
+
id: item.id,
|
|
916
|
+
xml: withMark(item),
|
|
917
|
+
path: item.path,
|
|
918
|
+
part: encoder.encode(shell),
|
|
919
|
+
...rels !== void 0 ? { rels } : {},
|
|
920
|
+
shapes,
|
|
921
|
+
connects
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
return { masters, mastersOpen, mastersClose };
|
|
927
|
+
}
|
|
928
|
+
async function snapshotRest(zip, derived, limit) {
|
|
929
|
+
const parts = /* @__PURE__ */ new Map();
|
|
930
|
+
const media = [];
|
|
931
|
+
const typesXml = await zipText(zip, CONTENT_TYPES) ?? "";
|
|
932
|
+
const mediaPaths = /* @__PURE__ */ new Set();
|
|
933
|
+
let total = 0;
|
|
934
|
+
for (const path of Object.keys(zip.files)) {
|
|
935
|
+
const file = zip.files[path];
|
|
936
|
+
if (file.dir || derived.has(path) || isLocalOnlyPart(path)) continue;
|
|
937
|
+
const data = await file.async("uint8array");
|
|
938
|
+
total += data.length;
|
|
939
|
+
if (total > limit) throw new Error("The package parts exceed the shared size limit.");
|
|
940
|
+
const declared = isMediaPart(path) ? declaredType(typesXml, path) : void 0;
|
|
941
|
+
if (declared) {
|
|
942
|
+
mediaPaths.add(path);
|
|
943
|
+
media.push({
|
|
944
|
+
path,
|
|
945
|
+
hash: contentHash(data),
|
|
946
|
+
ct: declared.type,
|
|
947
|
+
d: declared.byDefault,
|
|
948
|
+
data
|
|
949
|
+
});
|
|
950
|
+
} else parts.set(path, data);
|
|
951
|
+
}
|
|
952
|
+
const types = parts.get(CONTENT_TYPES);
|
|
953
|
+
if (types)
|
|
954
|
+
parts.set(
|
|
955
|
+
CONTENT_TYPES,
|
|
956
|
+
encoder.encode(
|
|
957
|
+
stripOverrides(decoder.decode(types), [PAGE_CONTENT_TYPE, MASTER_CONTENT_TYPE], mediaPaths)
|
|
958
|
+
)
|
|
959
|
+
);
|
|
960
|
+
return { parts, media };
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
// visio/collab/snapshot.ts
|
|
964
|
+
var DEFAULT_MAX_PART_BYTES = 48 * 1024 * 1024;
|
|
458
965
|
async function snapshotDrawing(bytes, keys, options = {}) {
|
|
459
966
|
const zip = await readZip(bytes);
|
|
460
967
|
const layout = await readLayout(zip);
|
|
461
968
|
if (!layout) throw new Error("The package has no Visio pages part.");
|
|
462
969
|
const pagesXml = await zipText(zip, layout.pagesPath) ?? "";
|
|
463
|
-
const local = await
|
|
970
|
+
const local = await readLocalItems(zip, layout.pagesPath, pagesXml, "Pages", "Page");
|
|
464
971
|
if (!local) throw new Error("The pages part cannot be split into pages.");
|
|
465
972
|
const derived = /* @__PURE__ */ new Set([layout.pagesPath, relsPathOf(layout.pagesPath)]);
|
|
466
|
-
const idToKey = new Map(local.
|
|
973
|
+
const idToKey = new Map(local.items.map((p) => [p.id, keys.pageKey(p.id)]));
|
|
467
974
|
const pages = [];
|
|
468
|
-
for (const page of local.
|
|
975
|
+
for (const page of local.items) {
|
|
469
976
|
const key = idToKey.get(page.id);
|
|
470
977
|
derived.add(page.path).add(relsPathOf(page.path));
|
|
471
978
|
const head = page.text.slice(0, scanContainer(page.text, "Page").openEnd);
|
|
472
979
|
const backId = attrOf(head, "BackPage");
|
|
473
|
-
const xml = page.text.slice(0, page.rel.start) + REL_MARK + page.text.slice(page.rel.end);
|
|
474
980
|
const content = await zipText(zip, page.path) ?? "";
|
|
475
981
|
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
|
-
}
|
|
982
|
+
const { shell, shapes, connects } = splitContents(content, key, keys);
|
|
506
983
|
keys.pagePaths.set(key, page.path);
|
|
507
984
|
pages.push({
|
|
508
985
|
key,
|
|
509
986
|
id: page.id,
|
|
510
987
|
...backId !== void 0 && idToKey.has(backId) ? { back: idToKey.get(backId) } : {},
|
|
511
|
-
xml,
|
|
512
|
-
shell
|
|
988
|
+
xml: withMark(page),
|
|
989
|
+
shell,
|
|
513
990
|
...rels !== void 0 ? { rels } : {},
|
|
514
991
|
path: page.path,
|
|
515
992
|
shapes,
|
|
516
993
|
connects
|
|
517
994
|
});
|
|
518
995
|
}
|
|
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
|
-
}
|
|
996
|
+
const { masters, mastersOpen, mastersClose } = await snapshotMasters(zip, layout, keys, derived);
|
|
997
|
+
const { parts, media } = await snapshotRest(
|
|
998
|
+
zip,
|
|
999
|
+
derived,
|
|
1000
|
+
options.maxPartBytes ?? DEFAULT_MAX_PART_BYTES
|
|
1001
|
+
);
|
|
531
1002
|
return {
|
|
532
1003
|
pagesPath: layout.pagesPath,
|
|
533
1004
|
pagesOpen: pagesXml.slice(0, local.box.openEnd),
|
|
534
1005
|
pagesClose: pagesXml.slice(local.box.closeStart),
|
|
535
1006
|
pages,
|
|
1007
|
+
...mastersOpen !== void 0 && mastersClose !== void 0 && layout.mastersPath ? { mastersPath: layout.mastersPath, mastersOpen, mastersClose } : {},
|
|
1008
|
+
masters,
|
|
1009
|
+
media,
|
|
536
1010
|
parts
|
|
537
1011
|
};
|
|
538
1012
|
}
|
|
539
1013
|
|
|
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);
|
|
1014
|
+
// visio/collab/compose-lists.ts
|
|
1015
|
+
var relTarget = (dir, path) => dir && path.startsWith(`${dir}/`) ? path.slice(dir.length + 1) : `/${path}`;
|
|
1016
|
+
async function placeList(options) {
|
|
1017
|
+
const { files, taken, localZip, items } = options;
|
|
1018
|
+
const dir = dirName(options.listPath);
|
|
1019
|
+
taken.add(options.listPath).add(relsPathOf(options.listPath));
|
|
1020
|
+
const paths = /* @__PURE__ */ new Map();
|
|
1021
|
+
for (const item of items) {
|
|
1022
|
+
const known = options.known.get(item.key);
|
|
1023
|
+
if (known && !taken.has(known) && localZip?.file(known)) {
|
|
1024
|
+
paths.set(item.key, known);
|
|
1025
|
+
taken.add(known);
|
|
572
1026
|
}
|
|
573
|
-
i = end;
|
|
574
1027
|
}
|
|
575
|
-
|
|
1028
|
+
let counter = 0;
|
|
1029
|
+
for (const item of items) {
|
|
1030
|
+
if (paths.has(item.key)) continue;
|
|
1031
|
+
let path;
|
|
1032
|
+
do
|
|
1033
|
+
path = `${dir ? `${dir}/` : ""}${options.stem}${++counter}.xml`;
|
|
1034
|
+
while (taken.has(path) || localZip?.file(path));
|
|
1035
|
+
paths.set(item.key, path);
|
|
1036
|
+
taken.add(path);
|
|
1037
|
+
}
|
|
1038
|
+
const others = parseRelationships(
|
|
1039
|
+
localZip ? await zipText(localZip, relsPathOf(options.listPath)) : void 0
|
|
1040
|
+
).filter((r) => r.type !== options.relType);
|
|
1041
|
+
const usedIds = new Set(others.map((r) => r.id));
|
|
1042
|
+
let nextRel = 0;
|
|
1043
|
+
const rels = [];
|
|
1044
|
+
const elements = [];
|
|
1045
|
+
for (const item of items) {
|
|
1046
|
+
const path = paths.get(item.key);
|
|
1047
|
+
let id;
|
|
1048
|
+
do
|
|
1049
|
+
id = `rId${++nextRel}`;
|
|
1050
|
+
while (usedIds.has(id));
|
|
1051
|
+
usedIds.add(id);
|
|
1052
|
+
rels.push(
|
|
1053
|
+
`<Relationship Id="${id}" Type="${options.relType}" Target="${escapeAttr(relTarget(dir, path))}"/>`
|
|
1054
|
+
);
|
|
1055
|
+
const rel = `<Rel xmlns:r="${REL_NS}" r:id="${id}"/>`;
|
|
1056
|
+
elements.push(
|
|
1057
|
+
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("</"))
|
|
1058
|
+
);
|
|
1059
|
+
files.set(path, item.part);
|
|
1060
|
+
if (item.rels !== void 0) files.set(relsPathOf(path), encoder.encode(item.rels));
|
|
1061
|
+
}
|
|
1062
|
+
files.set(options.listPath, encoder.encode(options.open + elements.join("") + options.close));
|
|
1063
|
+
files.set(
|
|
1064
|
+
relsPathOf(options.listPath),
|
|
1065
|
+
encoder.encode(
|
|
1066
|
+
'<?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>"
|
|
1067
|
+
)
|
|
1068
|
+
);
|
|
1069
|
+
return paths;
|
|
576
1070
|
}
|
|
577
|
-
|
|
578
|
-
|
|
1071
|
+
new TextDecoder("utf-8", { fatal: true });
|
|
1072
|
+
var crcTable = Uint32Array.from({ length: 256 }, (_, value) => {
|
|
1073
|
+
for (let i = 0; i < 8; i++) value = value & 1 ? 3988292384 ^ value >>> 1 : value >>> 1;
|
|
1074
|
+
return value >>> 0;
|
|
1075
|
+
});
|
|
1076
|
+
function crc32(bytes, crc = 4294967295) {
|
|
1077
|
+
for (const byte of bytes) crc = (crcTable[(crc ^ byte) & 255] ?? 0) ^ crc >>> 8;
|
|
1078
|
+
return crc >>> 0;
|
|
579
1079
|
}
|
|
580
1080
|
|
|
581
|
-
// visio/collab/
|
|
582
|
-
var
|
|
583
|
-
var
|
|
584
|
-
var
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
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);
|
|
1081
|
+
// visio/collab/zip-store.ts
|
|
1082
|
+
var encoder2 = new TextEncoder();
|
|
1083
|
+
var DOS_TIME = 0;
|
|
1084
|
+
var DOS_DATE = 33;
|
|
1085
|
+
function writeStoredZip(files, crcs) {
|
|
1086
|
+
const prepared = files.map(([name, data]) => {
|
|
1087
|
+
let crc = crcs.get(data);
|
|
1088
|
+
if (crc === void 0) {
|
|
1089
|
+
crc = (crc32(data) ^ 4294967295) >>> 0;
|
|
1090
|
+
crcs.set(data, crc);
|
|
643
1091
|
}
|
|
1092
|
+
return { name: encoder2.encode(name), data, crc };
|
|
1093
|
+
});
|
|
1094
|
+
let local = 0;
|
|
1095
|
+
let central = 0;
|
|
1096
|
+
for (const f of prepared) {
|
|
1097
|
+
local += 30 + f.name.length + f.data.length;
|
|
1098
|
+
central += 46 + f.name.length;
|
|
644
1099
|
}
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
writes++;
|
|
666
|
-
}
|
|
1100
|
+
const out = new Uint8Array(local + central + 22);
|
|
1101
|
+
const view = new DataView(out.buffer);
|
|
1102
|
+
let at = 0;
|
|
1103
|
+
const offsets = [];
|
|
1104
|
+
for (const f of prepared) {
|
|
1105
|
+
offsets.push(at);
|
|
1106
|
+
view.setUint32(at, 67324752, true);
|
|
1107
|
+
view.setUint16(at + 4, 20, true);
|
|
1108
|
+
view.setUint16(at + 6, 2048, true);
|
|
1109
|
+
view.setUint16(at + 8, 0, true);
|
|
1110
|
+
view.setUint16(at + 10, DOS_TIME, true);
|
|
1111
|
+
view.setUint16(at + 12, DOS_DATE, true);
|
|
1112
|
+
view.setUint32(at + 14, f.crc, true);
|
|
1113
|
+
view.setUint32(at + 18, f.data.length, true);
|
|
1114
|
+
view.setUint32(at + 22, f.data.length, true);
|
|
1115
|
+
view.setUint16(at + 26, f.name.length, true);
|
|
1116
|
+
view.setUint16(at + 28, 0, true);
|
|
1117
|
+
out.set(f.name, at + 30);
|
|
1118
|
+
out.set(f.data, at + 30 + f.name.length);
|
|
1119
|
+
at += 30 + f.name.length + f.data.length;
|
|
667
1120
|
}
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
1121
|
+
const centralStart = at;
|
|
1122
|
+
prepared.forEach((f, i) => {
|
|
1123
|
+
view.setUint32(at, 33639248, true);
|
|
1124
|
+
view.setUint16(at + 4, 20, true);
|
|
1125
|
+
view.setUint16(at + 6, 20, true);
|
|
1126
|
+
view.setUint16(at + 8, 2048, true);
|
|
1127
|
+
view.setUint16(at + 10, 0, true);
|
|
1128
|
+
view.setUint16(at + 12, DOS_TIME, true);
|
|
1129
|
+
view.setUint16(at + 14, DOS_DATE, true);
|
|
1130
|
+
view.setUint32(at + 16, f.crc, true);
|
|
1131
|
+
view.setUint32(at + 20, f.data.length, true);
|
|
1132
|
+
view.setUint32(at + 24, f.data.length, true);
|
|
1133
|
+
view.setUint16(at + 28, f.name.length, true);
|
|
1134
|
+
view.setUint32(at + 42, offsets[i], true);
|
|
1135
|
+
out.set(f.name, at + 46);
|
|
1136
|
+
at += 46 + f.name.length;
|
|
1137
|
+
});
|
|
1138
|
+
view.setUint32(at, 101010256, true);
|
|
1139
|
+
view.setUint16(at + 8, prepared.length, true);
|
|
1140
|
+
view.setUint16(at + 10, prepared.length, true);
|
|
1141
|
+
view.setUint32(at + 12, at - centralStart, true);
|
|
1142
|
+
view.setUint32(at + 16, centralStart, true);
|
|
1143
|
+
return out;
|
|
682
1144
|
}
|
|
683
1145
|
|
|
684
1146
|
// visio/collab/compose.ts
|
|
@@ -694,32 +1156,51 @@ function connectXml(item) {
|
|
|
694
1156
|
];
|
|
695
1157
|
return `<Connect ${attrs.filter(([, v]) => v !== "").map(([k, v]) => `${k}="${escapeAttr(v)}"`).join(" ")}/>`;
|
|
696
1158
|
}
|
|
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}`;
|
|
1159
|
+
function contentsXml(shell, root, shapesXml, hasShapes, connects) {
|
|
1160
|
+
const outer = scanContainer(shell, root);
|
|
1161
|
+
if (hasShapes && !shell.includes(SHAPES_MARK) && outer && !outer.selfClosing)
|
|
1162
|
+
shell = shell.slice(0, outer.openEnd) + `<Shapes>${SHAPES_MARK}</Shapes>` + shell.slice(outer.openEnd);
|
|
1163
|
+
const outer2 = scanContainer(shell, root);
|
|
1164
|
+
if (connects.length && !shell.includes(CONNECTS_MARK) && outer2 && !outer2.selfClosing)
|
|
1165
|
+
shell = shell.slice(0, outer2.closeStart) + `<Connects>${CONNECTS_MARK}</Connects>` + shell.slice(outer2.closeStart);
|
|
1166
|
+
return shell.replace(SHAPES_MARK, () => shapesXml).replace(CONNECTS_MARK, () => connects.map(connectXml).join(""));
|
|
709
1167
|
}
|
|
1168
|
+
var pagePartXml = (page) => contentsXml(
|
|
1169
|
+
page.body.shell,
|
|
1170
|
+
"PageContents",
|
|
1171
|
+
page.shapesXml,
|
|
1172
|
+
page.shapes.length > 0,
|
|
1173
|
+
page.connects
|
|
1174
|
+
);
|
|
1175
|
+
var masterPartXml = (master) => contentsXml(
|
|
1176
|
+
decoder.decode(fromBase64(master.part)),
|
|
1177
|
+
"MasterContents",
|
|
1178
|
+
master.shapesXml,
|
|
1179
|
+
master.shapes.length > 0,
|
|
1180
|
+
master.connects
|
|
1181
|
+
);
|
|
710
1182
|
async function composeDrawing(drawing, local, keys, options = {}) {
|
|
711
1183
|
const localZip = local ? await readZip(local) : void 0;
|
|
712
1184
|
const files = /* @__PURE__ */ new Map();
|
|
713
1185
|
const prints = /* @__PURE__ */ new Map();
|
|
714
1186
|
let total = 0;
|
|
715
1187
|
const limit = options.maxPartBytes ?? 48 * 1024 * 1024;
|
|
716
|
-
|
|
717
|
-
|
|
1188
|
+
const cache = keys.cache.parts;
|
|
1189
|
+
const decode = (path, b64) => {
|
|
1190
|
+
const hit = cache.get(path);
|
|
1191
|
+
const data = hit && hit.b64 === b64 ? hit.data : fromBase64(b64);
|
|
1192
|
+
if (!hit || hit.b64 !== b64) cache.set(path, { b64, data });
|
|
718
1193
|
total += data.length;
|
|
719
1194
|
if (total > limit) throw new Error("The shared parts exceed the size limit.");
|
|
1195
|
+
return data;
|
|
1196
|
+
};
|
|
1197
|
+
for (const [path, b64] of drawing.parts) {
|
|
1198
|
+
const data = decode(path, b64);
|
|
720
1199
|
files.set(path, data);
|
|
721
1200
|
prints.set(path, fingerprint(data));
|
|
722
1201
|
}
|
|
1202
|
+
for (const path of [...cache.keys()])
|
|
1203
|
+
if (!drawing.parts.has(path) && !path.startsWith("media:")) cache.delete(path);
|
|
723
1204
|
if (localZip)
|
|
724
1205
|
for (const path of Object.keys(localZip.files)) {
|
|
725
1206
|
const file = localZip.files[path];
|
|
@@ -727,6 +1208,10 @@ async function composeDrawing(drawing, local, keys, options = {}) {
|
|
|
727
1208
|
files.set(path, await file.async("uint8array"));
|
|
728
1209
|
}
|
|
729
1210
|
let contentTypes = files.get(CONTENT_TYPES) !== void 0 ? decoder.decode(files.get(CONTENT_TYPES)) : (localZip && await zipText(localZip, CONTENT_TYPES)) ?? DEFAULT_CONTENT_TYPES;
|
|
1211
|
+
for (const item of drawing.media) {
|
|
1212
|
+
files.set(item.path, decode(`media:${item.path}`, item.data));
|
|
1213
|
+
contentTypes = ensureType(contentTypes, item.path, item.declared);
|
|
1214
|
+
}
|
|
730
1215
|
for (const [path, data] of [...files]) {
|
|
731
1216
|
if (!path.endsWith(".rels") || typeof data === "string") continue;
|
|
732
1217
|
const source = path.replace(/(^|\/)_rels\/([^/]+)\.rels$/, "$1$2");
|
|
@@ -745,91 +1230,119 @@ async function composeDrawing(drawing, local, keys, options = {}) {
|
|
|
745
1230
|
});
|
|
746
1231
|
if (next !== text) files.set(path, encoder.encode(next));
|
|
747
1232
|
}
|
|
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
|
-
|
|
1233
|
+
const taken = new Set(files.keys());
|
|
1234
|
+
const pageCache = keys.cache.pageParts;
|
|
1235
|
+
const pageItems = drawing.pages.map((page) => {
|
|
1236
|
+
const hit = pageCache.get(page.key);
|
|
1237
|
+
const bytes2 = hit && hit.sig === page.signature ? hit.bytes : encoder.encode(pagePartXml(page));
|
|
1238
|
+
pageCache.set(page.key, { sig: page.signature, bytes: bytes2 });
|
|
1239
|
+
return {
|
|
1240
|
+
key: page.key,
|
|
1241
|
+
xml: page.xml,
|
|
1242
|
+
part: bytes2,
|
|
1243
|
+
...page.body.rels !== void 0 ? { rels: page.body.rels } : {}
|
|
1244
|
+
};
|
|
1245
|
+
});
|
|
1246
|
+
for (const key of [...pageCache.keys()])
|
|
1247
|
+
if (!drawing.pages.some((p) => p.key === key)) pageCache.delete(key);
|
|
1248
|
+
const pagePaths = await placeList({
|
|
1249
|
+
listPath: drawing.pagesPath,
|
|
1250
|
+
open: drawing.pagesOpen,
|
|
1251
|
+
close: drawing.pagesClose,
|
|
1252
|
+
relType: PAGE_TYPE,
|
|
1253
|
+
stem: "page",
|
|
1254
|
+
items: pageItems,
|
|
1255
|
+
known: keys.pagePaths,
|
|
1256
|
+
files,
|
|
1257
|
+
taken,
|
|
1258
|
+
localZip
|
|
1259
|
+
});
|
|
1260
|
+
contentTypes = withPageOverrides(contentTypes, [...pagePaths.values()]);
|
|
1261
|
+
let masterPaths = /* @__PURE__ */ new Map();
|
|
1262
|
+
if (drawing.mastersPath !== void 0) {
|
|
1263
|
+
masterPaths = await placeList({
|
|
1264
|
+
listPath: drawing.mastersPath,
|
|
1265
|
+
open: drawing.mastersOpen ?? "<Masters>",
|
|
1266
|
+
close: drawing.mastersClose ?? "</Masters>",
|
|
1267
|
+
relType: MASTER_TYPE,
|
|
1268
|
+
stem: "master",
|
|
1269
|
+
items: drawing.masters.map((m) => ({
|
|
1270
|
+
key: m.key,
|
|
1271
|
+
xml: m.xml,
|
|
1272
|
+
part: encoder.encode(masterPartXml(m)),
|
|
1273
|
+
...m.rels !== void 0 ? { rels: m.rels } : {}
|
|
1274
|
+
})),
|
|
1275
|
+
known: keys.masterPaths,
|
|
1276
|
+
files,
|
|
1277
|
+
taken,
|
|
1278
|
+
localZip
|
|
1279
|
+
});
|
|
1280
|
+
contentTypes = withOverrides(contentTypes, MASTER_CONTENT_TYPE, [...masterPaths.values()]);
|
|
795
1281
|
}
|
|
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()])));
|
|
807
|
-
const zip = new JSZip__default.default();
|
|
1282
|
+
files.set(CONTENT_TYPES, encoder.encode(contentTypes));
|
|
808
1283
|
const names = [...files.keys()].sort(
|
|
809
1284
|
(a, b) => a === CONTENT_TYPES ? -1 : b === CONTENT_TYPES ? 1 : 0
|
|
810
1285
|
);
|
|
811
|
-
|
|
812
|
-
|
|
1286
|
+
const bytes = writeStoredZip(
|
|
1287
|
+
names.map((name) => {
|
|
1288
|
+
const data = files.get(name);
|
|
1289
|
+
return [name, typeof data === "string" ? encoder.encode(data) : data];
|
|
1290
|
+
}),
|
|
1291
|
+
keys.cache.crcs
|
|
1292
|
+
);
|
|
813
1293
|
const commit = () => {
|
|
814
1294
|
const pageIds = /* @__PURE__ */ new Map();
|
|
815
|
-
const
|
|
1295
|
+
const shapeIds = /* @__PURE__ */ new Map();
|
|
1296
|
+
const masterIds = /* @__PURE__ */ new Map();
|
|
816
1297
|
const known = /* @__PURE__ */ new Map();
|
|
1298
|
+
const recordShapes = (scope, shapes, connects) => {
|
|
1299
|
+
shapeIds.set(scope, new Map(shapes.map((s) => [s.id, s.key])));
|
|
1300
|
+
for (const shape of shapes) {
|
|
1301
|
+
known.set(shapeId(scope, shape.key), shellContent(shape));
|
|
1302
|
+
for (const [path, entry] of shape.entries)
|
|
1303
|
+
known.set(cellId(scope, shape.key, path), entryContent(entry));
|
|
1304
|
+
}
|
|
1305
|
+
for (const connect of connects) known.set(connectId(connect.key), "");
|
|
1306
|
+
};
|
|
817
1307
|
keys.pagePaths.clear();
|
|
1308
|
+
keys.masterPaths.clear();
|
|
1309
|
+
keys.mediaKeys.clear();
|
|
818
1310
|
for (const page of drawing.pages) {
|
|
819
1311
|
pageIds.set(page.id, page.key);
|
|
820
|
-
keys.pagePaths.set(page.key,
|
|
1312
|
+
keys.pagePaths.set(page.key, pagePaths.get(page.key));
|
|
821
1313
|
known.set(pageId(page.key), pageContent(page));
|
|
822
1314
|
known.set(bodyId(page.key), bodyContent(page.body));
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
1315
|
+
recordShapes(page.key, page.shapes, page.connects);
|
|
1316
|
+
}
|
|
1317
|
+
for (const master of drawing.masters) {
|
|
1318
|
+
masterIds.set(master.id, master.key);
|
|
1319
|
+
recordShapes(masterScope(master.key), master.shapes, master.connects);
|
|
1320
|
+
const path = masterPaths.get(master.key);
|
|
1321
|
+
if (path) keys.masterPaths.set(master.key, path);
|
|
1322
|
+
known.set(
|
|
1323
|
+
masterId(master.key),
|
|
1324
|
+
masterContent({ ...master, print: fingerprint(fromBase64(master.part)) })
|
|
1325
|
+
);
|
|
826
1326
|
}
|
|
827
|
-
|
|
1327
|
+
for (const item of drawing.media) {
|
|
1328
|
+
known.set(mediaId(item.key), "");
|
|
1329
|
+
keys.mediaKeys.set(item.path, item.key);
|
|
1330
|
+
}
|
|
1331
|
+
keys.reset(pageIds, shapeIds, masterIds);
|
|
828
1332
|
keys.known = known;
|
|
829
1333
|
keys.partPrints.clear();
|
|
830
1334
|
for (const [path, print] of prints) keys.partPrints.set(path, print);
|
|
831
1335
|
};
|
|
832
|
-
return { bytes, commit };
|
|
1336
|
+
return { bytes, signature: drawing.signature, commit };
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
// visio/collab/fixups.ts
|
|
1340
|
+
function applyFixups(shared, fixups) {
|
|
1341
|
+
let changed = 0;
|
|
1342
|
+
for (const fixup of fixups) {
|
|
1343
|
+
if (setIfChanged(shared.renum, fixup.key, fixup.value)) changed++;
|
|
1344
|
+
}
|
|
1345
|
+
return changed;
|
|
833
1346
|
}
|
|
834
1347
|
|
|
835
1348
|
// visio/collab/keys.ts
|
|
@@ -843,15 +1356,36 @@ var DrawingKeys = class {
|
|
|
843
1356
|
seeding = false;
|
|
844
1357
|
#pages = /* @__PURE__ */ new Map();
|
|
845
1358
|
#shapes = /* @__PURE__ */ new Map();
|
|
1359
|
+
#masters = /* @__PURE__ */ new Map();
|
|
846
1360
|
/** 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
1361
|
known = /* @__PURE__ */ new Map();
|
|
848
1362
|
/** Fingerprints of the parts this peer last wrote or applied. */
|
|
849
1363
|
partPrints = /* @__PURE__ */ new Map();
|
|
850
1364
|
/** The part path of each page key in the local package. */
|
|
851
1365
|
pagePaths = /* @__PURE__ */ new Map();
|
|
1366
|
+
/** The part path of each master key in the local package. */
|
|
1367
|
+
masterPaths = /* @__PURE__ */ new Map();
|
|
1368
|
+
/** The room key of each media path in the local package. */
|
|
1369
|
+
mediaKeys = /* @__PURE__ */ new Map();
|
|
1370
|
+
/** Serialised page parts and decoded shared parts of the last rebuild, to skip unchanged work. */
|
|
1371
|
+
cache = {
|
|
1372
|
+
pageParts: /* @__PURE__ */ new Map(),
|
|
1373
|
+
parts: /* @__PURE__ */ new Map(),
|
|
1374
|
+
/** CRC-32 of the bytes of each stored part, by identity (see zip-store.ts). */
|
|
1375
|
+
crcs: /* @__PURE__ */ new WeakMap()
|
|
1376
|
+
};
|
|
1377
|
+
/**
|
|
1378
|
+
* What was last applied to the editor: the drawing signature, the editor version it produced,
|
|
1379
|
+
* the signature of everything but page content and the content signature of each page.
|
|
1380
|
+
*/
|
|
1381
|
+
applied;
|
|
852
1382
|
mint() {
|
|
853
1383
|
return `${this.tag}.${(++this.#counter).toString(36)}`;
|
|
854
1384
|
}
|
|
1385
|
+
/** A fresh id for one write batch: entries written together share it. */
|
|
1386
|
+
batch() {
|
|
1387
|
+
return this.mint();
|
|
1388
|
+
}
|
|
855
1389
|
pageKey(id) {
|
|
856
1390
|
let key = this.#pages.get(id);
|
|
857
1391
|
if (key === void 0) {
|
|
@@ -870,6 +1404,14 @@ var DrawingKeys = class {
|
|
|
870
1404
|
}
|
|
871
1405
|
return key;
|
|
872
1406
|
}
|
|
1407
|
+
masterKey(id) {
|
|
1408
|
+
let key = this.#masters.get(id);
|
|
1409
|
+
if (key === void 0) {
|
|
1410
|
+
key = this.seeding ? `s${id}` : this.mint();
|
|
1411
|
+
this.#masters.set(id, key);
|
|
1412
|
+
}
|
|
1413
|
+
return key;
|
|
1414
|
+
}
|
|
873
1415
|
findPage(id) {
|
|
874
1416
|
return this.#pages.get(id);
|
|
875
1417
|
}
|
|
@@ -883,38 +1425,352 @@ var DrawingKeys = class {
|
|
|
883
1425
|
for (const [id, k] of map) if (k === key) map.delete(id);
|
|
884
1426
|
}
|
|
885
1427
|
}
|
|
1428
|
+
forgetMaster(key) {
|
|
1429
|
+
for (const [id, k] of this.#masters) if (k === key) this.#masters.delete(id);
|
|
1430
|
+
this.#shapes.delete(masterScope(key));
|
|
1431
|
+
this.masterPaths.delete(key);
|
|
1432
|
+
}
|
|
886
1433
|
/** Replaces the id-to-key tables with those of a freshly composed package. */
|
|
887
|
-
reset(pages, shapes) {
|
|
1434
|
+
reset(pages, shapes, masters = /* @__PURE__ */ new Map()) {
|
|
888
1435
|
this.#pages.clear();
|
|
889
1436
|
this.#shapes.clear();
|
|
1437
|
+
this.#masters.clear();
|
|
890
1438
|
for (const [id, key] of pages) this.#pages.set(id, key);
|
|
891
1439
|
for (const [page, map] of shapes) this.#shapes.set(page, new Map(map));
|
|
1440
|
+
for (const [id, key] of masters) this.#masters.set(id, key);
|
|
892
1441
|
}
|
|
893
1442
|
};
|
|
894
1443
|
|
|
895
|
-
// visio/collab/
|
|
1444
|
+
// visio/collab/order.ts
|
|
1445
|
+
function assignPositions(order, current) {
|
|
1446
|
+
const result = /* @__PURE__ */ new Map();
|
|
1447
|
+
const kept = [];
|
|
1448
|
+
let last = -Infinity;
|
|
1449
|
+
for (const key of order) {
|
|
1450
|
+
const pos = current(key);
|
|
1451
|
+
if (pos !== void 0 && pos > last) {
|
|
1452
|
+
kept.push(pos);
|
|
1453
|
+
last = pos;
|
|
1454
|
+
} else kept.push(void 0);
|
|
1455
|
+
}
|
|
1456
|
+
let i = 0;
|
|
1457
|
+
while (i < order.length) {
|
|
1458
|
+
const known = kept[i];
|
|
1459
|
+
if (known !== void 0) {
|
|
1460
|
+
result.set(order[i], known);
|
|
1461
|
+
i++;
|
|
1462
|
+
continue;
|
|
1463
|
+
}
|
|
1464
|
+
let end = i;
|
|
1465
|
+
while (end < order.length && kept[end] === void 0) end++;
|
|
1466
|
+
const lo = i > 0 ? kept[i - 1] : void 0;
|
|
1467
|
+
const hi = end < order.length ? kept[end] : void 0;
|
|
1468
|
+
const count = end - i;
|
|
1469
|
+
for (let j = 0; j < count; j++) {
|
|
1470
|
+
const key = order[i + j];
|
|
1471
|
+
if (lo !== void 0 && hi !== void 0)
|
|
1472
|
+
result.set(key, lo + (hi - lo) * (j + 1) / (count + 1));
|
|
1473
|
+
else if (lo !== void 0) result.set(key, lo + j + 1);
|
|
1474
|
+
else if (hi !== void 0) result.set(key, hi - count + j);
|
|
1475
|
+
else result.set(key, j + 1);
|
|
1476
|
+
}
|
|
1477
|
+
i = end;
|
|
1478
|
+
}
|
|
1479
|
+
return result;
|
|
1480
|
+
}
|
|
1481
|
+
function byPosition(items) {
|
|
1482
|
+
return items.sort((a, b) => a.pos - b.pos || (a.key < b.key ? -1 : a.key > b.key ? 1 : 0));
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
// visio/collab/read-ids.ts
|
|
896
1486
|
var compare = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
897
1487
|
var numeric = (id) => /^\d+$/.test(id) ? Number(id) : 0;
|
|
1488
|
+
function assignIds(items) {
|
|
1489
|
+
const effective = (item) => item.fixed ?? item.id;
|
|
1490
|
+
let max = Math.max(0, ...items.map((item) => numeric(effective(item))));
|
|
1491
|
+
const order = [...items].sort(
|
|
1492
|
+
(a, b) => Number(b.fixed !== void 0) - Number(a.fixed !== void 0) || compare(a.key, b.key)
|
|
1493
|
+
);
|
|
1494
|
+
const ids = /* @__PURE__ */ new Map();
|
|
1495
|
+
const fresh = /* @__PURE__ */ new Map();
|
|
1496
|
+
const holder = /* @__PURE__ */ new Map();
|
|
1497
|
+
const claims = /* @__PURE__ */ new Set();
|
|
1498
|
+
for (const item of order) {
|
|
1499
|
+
let id = effective(item);
|
|
1500
|
+
const taken = holder.get(id);
|
|
1501
|
+
if (taken) {
|
|
1502
|
+
if (taken.fixed === void 0) claims.add(taken.key);
|
|
1503
|
+
id = String(++max);
|
|
1504
|
+
fresh.set(item.key, { from: item.id, to: id });
|
|
1505
|
+
}
|
|
1506
|
+
holder.set(id, item);
|
|
1507
|
+
ids.set(item.key, id);
|
|
1508
|
+
}
|
|
1509
|
+
return { ids, fresh, claims };
|
|
1510
|
+
}
|
|
1511
|
+
var fixedId = (renum, key, id) => {
|
|
1512
|
+
const pair = renum.get(key)?.i;
|
|
1513
|
+
return pair && pair[0] === id ? pair[1] : void 0;
|
|
1514
|
+
};
|
|
1515
|
+
function readRenum(shared) {
|
|
1516
|
+
const out = /* @__PURE__ */ new Map();
|
|
1517
|
+
for (const [key, value] of shared.renum) {
|
|
1518
|
+
const entry = renumEntry(value);
|
|
1519
|
+
if (entry) out.set(key, entry);
|
|
1520
|
+
}
|
|
1521
|
+
return out;
|
|
1522
|
+
}
|
|
1523
|
+
function renumRecord(renum, recordKey, item, change, claimed) {
|
|
1524
|
+
if (change) return { ...renum.get(recordKey), i: [change.from, change.to] };
|
|
1525
|
+
if (claimed) return { ...renum.get(recordKey), i: [item.id, item.id] };
|
|
1526
|
+
return void 0;
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
// visio/collab/read-util.ts
|
|
1530
|
+
function hashTexts(texts) {
|
|
1531
|
+
let a = 2166136261;
|
|
1532
|
+
let b = 16777619 ^ 2654435769;
|
|
1533
|
+
for (const text of texts) {
|
|
1534
|
+
for (let i = 0; i < text.length; i++) {
|
|
1535
|
+
const c = text.charCodeAt(i);
|
|
1536
|
+
a = Math.imul(a ^ c, 16777619);
|
|
1537
|
+
b = Math.imul(b + c, 2246822507) ^ b >>> 13;
|
|
1538
|
+
}
|
|
1539
|
+
a = Math.imul(a ^ 255, 16777619);
|
|
1540
|
+
b = Math.imul(b ^ 255, 3266489909);
|
|
1541
|
+
}
|
|
1542
|
+
return `${(a >>> 0).toString(16)}${(b >>> 0).toString(16)}`;
|
|
1543
|
+
}
|
|
1544
|
+
var split = (key, depth) => {
|
|
1545
|
+
const out = [];
|
|
1546
|
+
let from = 0;
|
|
1547
|
+
for (let i = 0; i < depth; i++) {
|
|
1548
|
+
const slash = key.indexOf("/", from);
|
|
1549
|
+
if (slash < 0) return void 0;
|
|
1550
|
+
out.push(key.slice(from, slash));
|
|
1551
|
+
from = slash + 1;
|
|
1552
|
+
}
|
|
1553
|
+
out.push(key.slice(from));
|
|
1554
|
+
return out;
|
|
1555
|
+
};
|
|
1556
|
+
var connectSignature = (connects) => connects.flatMap((c) => [c.from, c.to, c.entry.fc, c.entry.tc, c.entry.fp, c.entry.tp]);
|
|
1557
|
+
function resolveConnects(list, shapes) {
|
|
1558
|
+
const byKey = new Map(shapes.map((s) => [s.key, s]));
|
|
1559
|
+
const out = [];
|
|
1560
|
+
for (const item of [...list ?? []].sort((a, b) => compare(a.key, b.key))) {
|
|
1561
|
+
const { entry } = item;
|
|
1562
|
+
const from = entry.fk ? byKey.get(entry.fk) : void 0;
|
|
1563
|
+
const to = entry.tk ? byKey.get(entry.tk) : void 0;
|
|
1564
|
+
if (entry.fk && !from || entry.tk && !to) continue;
|
|
1565
|
+
out.push({ key: item.key, entry, from: from?.id ?? entry.fi, to: to?.id ?? entry.ti });
|
|
1566
|
+
}
|
|
1567
|
+
return out;
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
// visio/collab/read-shapes.ts
|
|
898
1571
|
function setAttr(open, name, value) {
|
|
899
1572
|
return open.replace(
|
|
900
1573
|
new RegExp(String.raw`(\s${name}\s*=\s*)(?:"[^"]*"|'[^']*')`),
|
|
901
1574
|
(_m, head) => `${head}"${value}"`
|
|
902
1575
|
);
|
|
903
1576
|
}
|
|
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) => {
|
|
1577
|
+
function renumberFormulas(xml, remap) {
|
|
1578
|
+
if (!remap.size || !xml.includes("Sheet.")) return xml;
|
|
1579
|
+
return xml.replace(/(\sF\s*=\s*)("[^"]*"|'[^']*')/g, (_m, head, value) => {
|
|
1580
|
+
const body = value.slice(1, -1).replace(/Sheet\.(\d+)(?!\d)/g, (m, id) => {
|
|
909
1581
|
const next = remap.get(id);
|
|
910
|
-
return next === void 0 ? m :
|
|
1582
|
+
return next === void 0 ? m : `Sheet.${next}`;
|
|
1583
|
+
});
|
|
1584
|
+
return `${head}${value[0]}${body}${value[0]}`;
|
|
1585
|
+
});
|
|
1586
|
+
}
|
|
1587
|
+
function referenced(r, finalId) {
|
|
1588
|
+
const out = /* @__PURE__ */ new Map();
|
|
1589
|
+
for (let i = 0; i + 1 < r.length; i += 2) {
|
|
1590
|
+
const next = finalId.get(r[i + 1]);
|
|
1591
|
+
if (next !== void 0) out.set(r[i], next);
|
|
1592
|
+
}
|
|
1593
|
+
return out;
|
|
1594
|
+
}
|
|
1595
|
+
function resolveShapes(input) {
|
|
1596
|
+
const raw = /* @__PURE__ */ new Map();
|
|
1597
|
+
for (const [key, entry] of input.shapes) {
|
|
1598
|
+
const id = attrOf(entry.open, "ID");
|
|
1599
|
+
if (id !== void 0) raw.set(key, { entry, id });
|
|
1600
|
+
}
|
|
1601
|
+
const state = /* @__PURE__ */ new Map();
|
|
1602
|
+
const valid = (key, seen = /* @__PURE__ */ new Set()) => {
|
|
1603
|
+
const known = state.get(key);
|
|
1604
|
+
if (known !== void 0) return known;
|
|
1605
|
+
const item = raw.get(key);
|
|
1606
|
+
const parent = item?.entry.parent;
|
|
1607
|
+
let ok = !!item;
|
|
1608
|
+
if (ok && parent !== void 0) ok = !seen.has(key) && valid(parent, seen.add(key));
|
|
1609
|
+
state.set(key, ok);
|
|
1610
|
+
return ok;
|
|
1611
|
+
};
|
|
1612
|
+
const live = [...raw.keys()].filter((k) => valid(k)).sort(compare);
|
|
1613
|
+
const {
|
|
1614
|
+
ids: finalId,
|
|
1615
|
+
fresh: renumbered,
|
|
1616
|
+
claims
|
|
1617
|
+
} = assignIds(
|
|
1618
|
+
live.map((key) => {
|
|
1619
|
+
const { id } = raw.get(key);
|
|
1620
|
+
return { key, id, fixed: fixedId(input.renum, key, id) };
|
|
911
1621
|
})
|
|
912
|
-
)
|
|
913
|
-
|
|
914
|
-
|
|
1622
|
+
);
|
|
1623
|
+
const children = /* @__PURE__ */ new Map();
|
|
1624
|
+
for (const key of live) {
|
|
1625
|
+
const parent = raw.get(key).entry.parent ?? "";
|
|
1626
|
+
children.set(parent, [...children.get(parent) ?? [], key]);
|
|
1627
|
+
}
|
|
1628
|
+
const sortSiblings = (keys) => keys.sort((a, b) => raw.get(a).entry.pos - raw.get(b).entry.pos || compare(a, b));
|
|
1629
|
+
const shapes = [];
|
|
1630
|
+
const fixups = [];
|
|
1631
|
+
const render = (key) => {
|
|
1632
|
+
const { entry } = raw.get(key);
|
|
1633
|
+
const id = finalId.get(key);
|
|
1634
|
+
let open = setAttr(entry.open, "ID", id);
|
|
1635
|
+
const idRecord = renumRecord(
|
|
1636
|
+
input.renum,
|
|
1637
|
+
`${input.scope}/${key}`,
|
|
1638
|
+
{ id: raw.get(key).id },
|
|
1639
|
+
renumbered.get(key),
|
|
1640
|
+
claims.has(key)
|
|
1641
|
+
);
|
|
1642
|
+
const record = { ...idRecord ?? input.renum.get(key) };
|
|
1643
|
+
let dirty = idRecord !== void 0;
|
|
1644
|
+
const master = attrOf(open, "Master");
|
|
1645
|
+
const persisted = record.m && record.m[0] === master ? record.m[1] : void 0;
|
|
1646
|
+
const batched = master !== void 0 ? input.masterRemap.get(entry.b ?? "")?.get(master) : void 0;
|
|
1647
|
+
const next = persisted ?? batched;
|
|
1648
|
+
if (next !== void 0) open = setAttr(open, "Master", next);
|
|
1649
|
+
if (persisted === void 0 && batched !== void 0) {
|
|
1650
|
+
record.m = [master, batched];
|
|
1651
|
+
dirty = true;
|
|
1652
|
+
}
|
|
1653
|
+
if (dirty) fixups.push({ map: "renum", key: `${input.scope}/${key}`, value: record });
|
|
1654
|
+
const entries = /* @__PURE__ */ new Map();
|
|
1655
|
+
for (const [path, piece] of input.cells.get(key) ?? []) {
|
|
1656
|
+
const leaf = piece.xml !== void 0 && piece.r !== void 0;
|
|
1657
|
+
const xml2 = leaf ? renumberFormulas(piece.xml, referenced(piece.r, finalId)) : void 0;
|
|
1658
|
+
entries.set(path, xml2 !== void 0 && xml2 !== piece.xml ? { ...piece, xml: xml2 } : piece);
|
|
1659
|
+
}
|
|
1660
|
+
shapes.push({
|
|
1661
|
+
key,
|
|
1662
|
+
id,
|
|
1663
|
+
...entry.parent !== void 0 ? { parent: entry.parent } : {},
|
|
1664
|
+
open,
|
|
1665
|
+
entries
|
|
1666
|
+
});
|
|
1667
|
+
const inner = sortSiblings(children.get(key) ?? []).map(render).join("");
|
|
1668
|
+
return buildShape(open, entries, inner ? `<Shapes>${inner}</Shapes>` : "");
|
|
1669
|
+
};
|
|
1670
|
+
const xml = sortSiblings(children.get("") ?? []).map(render).join("");
|
|
1671
|
+
return { shapes, xml, fixups };
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1674
|
+
// visio/collab/read-parts.ts
|
|
1675
|
+
var compare2 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
1676
|
+
function resolveMasters(shared, renum) {
|
|
1677
|
+
const alive = [];
|
|
1678
|
+
for (const [key, value] of shared.masters) {
|
|
1679
|
+
const entry = masterEntry(value);
|
|
1680
|
+
if (entry) alive.push({ key, entry });
|
|
1681
|
+
}
|
|
1682
|
+
const { ids, fresh, claims } = assignIds(
|
|
1683
|
+
alive.map(({ key, entry }) => ({
|
|
1684
|
+
key,
|
|
1685
|
+
id: entry.id,
|
|
1686
|
+
fixed: fixedId(renum, masterScope(key), entry.id)
|
|
1687
|
+
}))
|
|
1688
|
+
);
|
|
1689
|
+
const remap = /* @__PURE__ */ new Map();
|
|
1690
|
+
const fixups = [];
|
|
1691
|
+
for (const [key, change] of [...fresh].sort((a, b) => compare2(a[0], b[0]))) {
|
|
1692
|
+
const b = alive.find((m) => m.key === key).entry.b;
|
|
1693
|
+
if (b !== void 0) {
|
|
1694
|
+
const map = remap.get(b) ?? /* @__PURE__ */ new Map();
|
|
1695
|
+
map.set(change.from, change.to);
|
|
1696
|
+
remap.set(b, map);
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1699
|
+
for (const { key, entry } of [...alive].sort((a, b) => compare2(a.key, b.key))) {
|
|
1700
|
+
const value = renumRecord(renum, masterScope(key), entry, fresh.get(key), claims.has(key));
|
|
1701
|
+
if (value) fixups.push({ map: "renum", key: masterScope(key), value });
|
|
1702
|
+
}
|
|
1703
|
+
alive.sort((a, b) => a.entry.pos - b.entry.pos || compare2(a.key, b.key));
|
|
1704
|
+
return {
|
|
1705
|
+
masters: alive.map(({ key, entry }) => {
|
|
1706
|
+
const id = ids.get(key);
|
|
1707
|
+
const open = /^<[^>]*>/.exec(entry.xml)?.[0];
|
|
1708
|
+
return {
|
|
1709
|
+
key,
|
|
1710
|
+
id,
|
|
1711
|
+
xml: open ? setAttr(open, "ID", id) + entry.xml.slice(open.length) : entry.xml,
|
|
1712
|
+
part: entry.part,
|
|
1713
|
+
...entry.rels !== void 0 ? { rels: entry.rels } : {}
|
|
1714
|
+
};
|
|
1715
|
+
}),
|
|
1716
|
+
remap,
|
|
1717
|
+
fixups
|
|
1718
|
+
};
|
|
1719
|
+
}
|
|
1720
|
+
function resolveMedia(shared) {
|
|
1721
|
+
const items = [...shared.media].flatMap(([key, value]) => {
|
|
1722
|
+
const entry = mediaEntry(value);
|
|
1723
|
+
const data = entry ? str(shared.blobs.get(entry.hash)) : void 0;
|
|
1724
|
+
return entry && data !== void 0 ? [{ key, entry, data }] : [];
|
|
1725
|
+
}).sort((a, b) => compare2(a.key, b.key));
|
|
1726
|
+
const taken = /* @__PURE__ */ new Set();
|
|
1727
|
+
const first = /* @__PURE__ */ new Map();
|
|
1728
|
+
for (const item of items) if (!first.has(item.entry.path)) first.set(item.entry.path, item.key);
|
|
1729
|
+
for (const path of first.keys()) taken.add(path);
|
|
1730
|
+
const renames = /* @__PURE__ */ new Map();
|
|
1731
|
+
const media = [];
|
|
1732
|
+
for (const { key, entry, data } of items) {
|
|
1733
|
+
let path = entry.path;
|
|
1734
|
+
if (first.get(entry.path) !== key) {
|
|
1735
|
+
const dot = path.lastIndexOf(".");
|
|
1736
|
+
const stem = dot > path.lastIndexOf("/") ? path.slice(0, dot) : path;
|
|
1737
|
+
const ext = dot > path.lastIndexOf("/") ? path.slice(dot) : "";
|
|
1738
|
+
path = `${stem}-${entry.hash.slice(0, 8)}${ext}`;
|
|
1739
|
+
for (let n = 2; taken.has(path); n++) path = `${stem}-${entry.hash.slice(0, 8)}-${n}${ext}`;
|
|
1740
|
+
taken.add(path);
|
|
1741
|
+
if (entry.b !== void 0) {
|
|
1742
|
+
const map = renames.get(entry.b) ?? /* @__PURE__ */ new Map();
|
|
1743
|
+
map.set(entry.path, path);
|
|
1744
|
+
renames.set(entry.b, map);
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
media.push({
|
|
1748
|
+
key,
|
|
1749
|
+
path,
|
|
1750
|
+
hash: entry.hash,
|
|
1751
|
+
declared: { type: entry.ct, byDefault: entry.d },
|
|
1752
|
+
data
|
|
1753
|
+
});
|
|
1754
|
+
}
|
|
1755
|
+
return { media, renames };
|
|
1756
|
+
}
|
|
1757
|
+
function renameTargets(rels, baseDir, renames) {
|
|
1758
|
+
return rels.replace(/<(?:\w+:)?Relationship\b[^>]*>/g, (tag) => {
|
|
1759
|
+
const target = attrOf(tag, "Target");
|
|
1760
|
+
if (target === void 0 || attrOf(tag, "TargetMode") === "External") return tag;
|
|
1761
|
+
const next = renames.get(resolveTarget(baseDir, target));
|
|
1762
|
+
if (next === void 0) return tag;
|
|
1763
|
+
const value = target.startsWith("/") ? `/${next}` : relativeTarget(baseDir, next);
|
|
1764
|
+
return tag.replace(
|
|
1765
|
+
/(\sTarget\s*=\s*)(?:"[^"]*"|'[^']*')/,
|
|
1766
|
+
(_m, head) => `${head}"${value}"`
|
|
1767
|
+
);
|
|
915
1768
|
});
|
|
916
1769
|
}
|
|
1770
|
+
|
|
1771
|
+
// visio/collab/read.ts
|
|
917
1772
|
function readSharedDrawing(shared) {
|
|
1773
|
+
assertSchemaVersion(shared);
|
|
918
1774
|
if (isSharedDrawingEmpty(shared)) return void 0;
|
|
919
1775
|
const pagesPath = str(shared.meta.get("pagesPath"));
|
|
920
1776
|
const pagesOpen = str(shared.meta.get("pagesOpen"));
|
|
@@ -926,25 +1782,52 @@ function readSharedDrawing(shared) {
|
|
|
926
1782
|
const body = bodyEntry(shared.bodies.get(key));
|
|
927
1783
|
return entry && body ? [{ key, pos: entry.pos, entry, body }] : [];
|
|
928
1784
|
});
|
|
929
|
-
const
|
|
930
|
-
const
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
1785
|
+
const renum = readRenum(shared);
|
|
1786
|
+
const fixups = [];
|
|
1787
|
+
const {
|
|
1788
|
+
ids: pageIds,
|
|
1789
|
+
fresh: freshPages,
|
|
1790
|
+
claims: pageClaims
|
|
1791
|
+
} = assignIds(
|
|
1792
|
+
alive.map((p) => ({
|
|
1793
|
+
key: p.key,
|
|
1794
|
+
id: p.entry.id,
|
|
1795
|
+
fixed: fixedId(renum, p.key, p.entry.id)
|
|
1796
|
+
}))
|
|
1797
|
+
);
|
|
1798
|
+
for (const p of [...alive].sort((a, b) => compare(a.key, b.key))) {
|
|
1799
|
+
const value = renumRecord(renum, p.key, p.entry, freshPages.get(p.key), pageClaims.has(p.key));
|
|
1800
|
+
if (value) fixups.push({ map: "renum", key: p.key, value });
|
|
937
1801
|
}
|
|
938
1802
|
const shapesByPage = /* @__PURE__ */ new Map();
|
|
939
1803
|
for (const [full, value] of shared.shapes) {
|
|
940
|
-
const
|
|
941
|
-
if (
|
|
1804
|
+
const parts2 = split(full, 1);
|
|
1805
|
+
if (!parts2 || shared.dead.has(full)) continue;
|
|
942
1806
|
const entry = shapeEntry(value);
|
|
943
1807
|
if (!entry) continue;
|
|
944
|
-
const
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
1808
|
+
const map = shapesByPage.get(parts2[0]) ?? /* @__PURE__ */ new Map();
|
|
1809
|
+
map.set(parts2[1], entry);
|
|
1810
|
+
shapesByPage.set(parts2[0], map);
|
|
1811
|
+
}
|
|
1812
|
+
const cellsByPage = /* @__PURE__ */ new Map();
|
|
1813
|
+
for (const [full, value] of shared.cells) {
|
|
1814
|
+
const parts2 = split(full, 2);
|
|
1815
|
+
const entry = parts2 && cellEntry(value);
|
|
1816
|
+
if (!parts2 || !entry) continue;
|
|
1817
|
+
const [page, shape, path] = parts2;
|
|
1818
|
+
const shapes = cellsByPage.get(page) ?? /* @__PURE__ */ new Map();
|
|
1819
|
+
const cells = shapes.get(shape) ?? /* @__PURE__ */ new Map();
|
|
1820
|
+
cells.set(path, entry);
|
|
1821
|
+
shapes.set(shape, cells);
|
|
1822
|
+
cellsByPage.set(page, shapes);
|
|
1823
|
+
}
|
|
1824
|
+
const renumByScope = /* @__PURE__ */ new Map();
|
|
1825
|
+
for (const [full, entry] of renum) {
|
|
1826
|
+
const parts2 = split(full, 1);
|
|
1827
|
+
if (!parts2) continue;
|
|
1828
|
+
const map = renumByScope.get(parts2[0]) ?? /* @__PURE__ */ new Map();
|
|
1829
|
+
map.set(parts2[1], entry);
|
|
1830
|
+
renumByScope.set(parts2[0], map);
|
|
948
1831
|
}
|
|
949
1832
|
const connectsByPage = /* @__PURE__ */ new Map();
|
|
950
1833
|
for (const [full, value] of shared.connects) {
|
|
@@ -955,24 +1838,25 @@ function readSharedDrawing(shared) {
|
|
|
955
1838
|
list.push({ key: full, entry });
|
|
956
1839
|
connectsByPage.set(full.slice(0, slash), list);
|
|
957
1840
|
}
|
|
1841
|
+
const { masters, remap: masterRemap, fixups: masterFixups } = resolveMasters(shared, renum);
|
|
1842
|
+
fixups.push(...masterFixups);
|
|
1843
|
+
const { media, renames } = resolveMedia(shared);
|
|
1844
|
+
const mastersPath = str(shared.meta.get("mastersPath"));
|
|
1845
|
+
const mastersOpen = str(shared.meta.get("mastersOpen"));
|
|
1846
|
+
const mastersClose = str(shared.meta.get("mastersClose"));
|
|
1847
|
+
const pagesDir = dirName(pagesPath);
|
|
958
1848
|
const pages = [];
|
|
959
1849
|
for (const page of byPosition(alive)) {
|
|
960
1850
|
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
|
-
}
|
|
1851
|
+
const resolved = resolveShapes({
|
|
1852
|
+
scope: page.key,
|
|
1853
|
+
shapes: shapesByPage.get(page.key) ?? /* @__PURE__ */ new Map(),
|
|
1854
|
+
cells: cellsByPage.get(page.key) ?? /* @__PURE__ */ new Map(),
|
|
1855
|
+
renum: renumByScope.get(page.key) ?? /* @__PURE__ */ new Map(),
|
|
1856
|
+
masterRemap
|
|
1857
|
+
});
|
|
1858
|
+
fixups.push(...resolved.fixups);
|
|
1859
|
+
const connects = resolveConnects(connectsByPage.get(page.key), resolved.shapes);
|
|
976
1860
|
let xml = page.entry.xml;
|
|
977
1861
|
const open = /^<[^>]*>/.exec(xml)?.[0];
|
|
978
1862
|
if (open) {
|
|
@@ -981,46 +1865,361 @@ function readSharedDrawing(shared) {
|
|
|
981
1865
|
if (back !== void 0) next = setAttr(next, "BackPage", back);
|
|
982
1866
|
xml = next + xml.slice(open.length);
|
|
983
1867
|
}
|
|
1868
|
+
const rename = page.body.b !== void 0 ? renames.get(page.body.b) : void 0;
|
|
1869
|
+
const body = rename && page.body.rels !== void 0 ? { ...page.body, rels: renameTargets(page.body.rels, pagesDir, rename) } : page.body;
|
|
1870
|
+
const contentSignature = hashTexts([
|
|
1871
|
+
body.shell,
|
|
1872
|
+
body.rels ?? "\0",
|
|
1873
|
+
resolved.xml,
|
|
1874
|
+
...connectSignature(connects)
|
|
1875
|
+
]);
|
|
984
1876
|
pages.push({
|
|
985
1877
|
key: page.key,
|
|
986
1878
|
id: finalId,
|
|
987
1879
|
...page.entry.back !== void 0 ? { back: page.entry.back } : {},
|
|
988
1880
|
xml,
|
|
989
|
-
body
|
|
990
|
-
shapes,
|
|
991
|
-
|
|
1881
|
+
body,
|
|
1882
|
+
shapes: resolved.shapes,
|
|
1883
|
+
shapesXml: resolved.xml,
|
|
1884
|
+
connects,
|
|
1885
|
+
signature: hashTexts([xml, contentSignature]),
|
|
1886
|
+
contentSignature
|
|
992
1887
|
});
|
|
993
1888
|
}
|
|
1889
|
+
const mastersDir = mastersPath !== void 0 ? dirName(mastersPath) : pagesDir;
|
|
1890
|
+
const finalMasters = masters.map((m) => {
|
|
1891
|
+
const batch = shared.masters.get(m.key)?.b;
|
|
1892
|
+
const rename = typeof batch === "string" ? renames.get(batch) : void 0;
|
|
1893
|
+
const scope = masterScope(m.key);
|
|
1894
|
+
const resolved = resolveShapes({
|
|
1895
|
+
scope,
|
|
1896
|
+
shapes: shapesByPage.get(scope) ?? /* @__PURE__ */ new Map(),
|
|
1897
|
+
cells: cellsByPage.get(scope) ?? /* @__PURE__ */ new Map(),
|
|
1898
|
+
renum: renumByScope.get(scope) ?? /* @__PURE__ */ new Map(),
|
|
1899
|
+
masterRemap: /* @__PURE__ */ new Map()
|
|
1900
|
+
});
|
|
1901
|
+
fixups.push(...resolved.fixups);
|
|
1902
|
+
return {
|
|
1903
|
+
...m,
|
|
1904
|
+
...rename && m.rels !== void 0 ? { rels: renameTargets(m.rels, mastersDir, rename) } : {},
|
|
1905
|
+
shapes: resolved.shapes,
|
|
1906
|
+
shapesXml: resolved.xml,
|
|
1907
|
+
connects: resolveConnects(connectsByPage.get(scope), resolved.shapes)
|
|
1908
|
+
};
|
|
1909
|
+
});
|
|
994
1910
|
const parts = /* @__PURE__ */ new Map();
|
|
995
1911
|
for (const [path, value] of shared.parts) if (typeof value === "string") parts.set(path, value);
|
|
996
|
-
|
|
1912
|
+
const baseSignature = hashTexts([
|
|
1913
|
+
pagesPath,
|
|
1914
|
+
pagesOpen,
|
|
1915
|
+
pagesClose,
|
|
1916
|
+
mastersPath ?? "",
|
|
1917
|
+
mastersOpen ?? "",
|
|
1918
|
+
mastersClose ?? "",
|
|
1919
|
+
...pages.map((p) => `${p.key}:${p.id}:${p.xml}`),
|
|
1920
|
+
...finalMasters.flatMap((m) => [
|
|
1921
|
+
m.key,
|
|
1922
|
+
m.id,
|
|
1923
|
+
m.xml,
|
|
1924
|
+
m.part,
|
|
1925
|
+
m.rels ?? "\0",
|
|
1926
|
+
m.shapesXml,
|
|
1927
|
+
...connectSignature(m.connects)
|
|
1928
|
+
]),
|
|
1929
|
+
...media.flatMap((m) => [m.path, m.hash, m.declared.type, String(m.declared.byDefault)]),
|
|
1930
|
+
...[...parts].flatMap(([path, data]) => [path, data])
|
|
1931
|
+
]);
|
|
1932
|
+
const signature = hashTexts([
|
|
1933
|
+
baseSignature,
|
|
1934
|
+
...pages.map((p) => `${p.key}:${p.contentSignature}`)
|
|
1935
|
+
]);
|
|
1936
|
+
return {
|
|
1937
|
+
pagesPath,
|
|
1938
|
+
pagesOpen,
|
|
1939
|
+
pagesClose,
|
|
1940
|
+
pages,
|
|
1941
|
+
...mastersPath !== void 0 && mastersOpen !== void 0 && mastersClose !== void 0 ? { mastersPath, mastersOpen, mastersClose } : {},
|
|
1942
|
+
masters: finalMasters,
|
|
1943
|
+
media,
|
|
1944
|
+
parts,
|
|
1945
|
+
signature,
|
|
1946
|
+
baseSignature,
|
|
1947
|
+
fixups
|
|
1948
|
+
};
|
|
997
1949
|
}
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
const
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1950
|
+
|
|
1951
|
+
// visio/collab/write-shapes.ts
|
|
1952
|
+
function syncEntry(ctx, map, mapKey, id, content, room, roomContent, local, stamp = false) {
|
|
1953
|
+
ctx.now.set(id, content);
|
|
1954
|
+
const base = ctx.keys.known.get(id);
|
|
1955
|
+
const own = base === void 0 ? !room || roomContent() !== content : base !== content;
|
|
1956
|
+
if (own || !room) {
|
|
1957
|
+
const value = local();
|
|
1958
|
+
ctx.write(map, mapKey, stamp ? { ...value, b: ctx.batch } : value);
|
|
1959
|
+
} else {
|
|
1960
|
+
const pos = local().pos;
|
|
1961
|
+
ctx.write(map, mapKey, pos === void 0 ? room : { ...room, pos });
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
function groupPositions(items, current) {
|
|
1965
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1966
|
+
for (const item of items) groups.set(item.group, [...groups.get(item.group) ?? [], item.key]);
|
|
1967
|
+
const out = /* @__PURE__ */ new Map();
|
|
1968
|
+
for (const list of groups.values())
|
|
1969
|
+
for (const [key, pos] of assignPositions(list, current)) out.set(key, pos);
|
|
1970
|
+
return out;
|
|
1971
|
+
}
|
|
1972
|
+
function syncConnects(ctx, connects) {
|
|
1973
|
+
for (const connect of connects) {
|
|
1974
|
+
ctx.now.set(connectId(connect.key), "");
|
|
1975
|
+
if (!ctx.keys.known.has(connectId(connect.key)) || !ctx.shared.connects.has(connect.key))
|
|
1976
|
+
ctx.write(ctx.shared.connects, connect.key, connect.entry);
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
function syncShapes(ctx, page) {
|
|
1980
|
+
const { shared } = ctx;
|
|
1981
|
+
const shapePos = groupPositions(
|
|
1982
|
+
page.shapes.map((s) => ({ key: s.key, group: s.parent ?? "" })),
|
|
1983
|
+
(key) => shapeEntry(shared.shapes.get(`${page.key}/${key}`))?.pos
|
|
1984
|
+
);
|
|
1985
|
+
for (const shape of page.shapes) {
|
|
1986
|
+
const full = `${page.key}/${shape.key}`;
|
|
1987
|
+
const room = shapeEntry(shared.shapes.get(full));
|
|
1988
|
+
const parent = shape.parent;
|
|
1989
|
+
syncEntry(
|
|
1990
|
+
ctx,
|
|
1991
|
+
shared.shapes,
|
|
1992
|
+
full,
|
|
1993
|
+
shapeId(page.key, shape.key),
|
|
1994
|
+
shellContent({ parent, open: shape.open }),
|
|
1995
|
+
room,
|
|
1996
|
+
() => shellContent(room),
|
|
1997
|
+
() => ({
|
|
1998
|
+
pos: shapePos.get(shape.key),
|
|
1999
|
+
...parent !== void 0 ? { parent } : {},
|
|
2000
|
+
open: shape.open,
|
|
2001
|
+
b: room?.b ?? ctx.batch
|
|
2002
|
+
})
|
|
2003
|
+
);
|
|
2004
|
+
const piecePos = groupPositions(
|
|
2005
|
+
shape.pieces.map((p) => ({ key: p.path, group: p.parent })),
|
|
2006
|
+
(path) => cellEntry(shared.cells.get(`${full}/${path}`))?.pos
|
|
2007
|
+
);
|
|
2008
|
+
for (const piece of shape.pieces) {
|
|
2009
|
+
const cellKey = `${full}/${piece.path}`;
|
|
2010
|
+
const roomCell = cellEntry(shared.cells.get(cellKey));
|
|
2011
|
+
const local = () => ({
|
|
2012
|
+
pos: piecePos.get(piece.path),
|
|
2013
|
+
...piece.kind === "leaf" ? { xml: piece.text } : { open: piece.text },
|
|
2014
|
+
...piece.refs ? { r: piece.refs } : {}
|
|
2015
|
+
});
|
|
2016
|
+
syncEntry(
|
|
2017
|
+
ctx,
|
|
2018
|
+
shared.cells,
|
|
2019
|
+
cellKey,
|
|
2020
|
+
cellId(page.key, shape.key, piece.path),
|
|
2021
|
+
entryContent(piece.kind === "leaf" ? { xml: piece.text } : { open: piece.text }),
|
|
2022
|
+
roomCell,
|
|
2023
|
+
() => entryContent(roomCell),
|
|
2024
|
+
local
|
|
2025
|
+
);
|
|
1007
2026
|
}
|
|
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
2027
|
}
|
|
1018
|
-
|
|
2028
|
+
}
|
|
2029
|
+
|
|
2030
|
+
// visio/collab/write-parts.ts
|
|
2031
|
+
var mediaKey = (hash, path) => `${hash}|${path}`;
|
|
2032
|
+
function syncMasters(ctx, snapshot) {
|
|
2033
|
+
const { shared } = ctx;
|
|
2034
|
+
const pos = assignPositions(
|
|
2035
|
+
snapshot.masters.map((m) => m.key),
|
|
2036
|
+
(key) => masterEntry(shared.masters.get(key))?.pos
|
|
2037
|
+
);
|
|
2038
|
+
for (const master of snapshot.masters) {
|
|
2039
|
+
const room = masterEntry(shared.masters.get(master.key));
|
|
2040
|
+
syncEntry(
|
|
2041
|
+
ctx,
|
|
2042
|
+
shared.masters,
|
|
2043
|
+
master.key,
|
|
2044
|
+
masterId(master.key),
|
|
2045
|
+
masterContent({ ...master, print: fingerprint(master.part) }),
|
|
2046
|
+
room,
|
|
2047
|
+
() => masterContent({
|
|
2048
|
+
...room,
|
|
2049
|
+
print: fingerprint(fromBase64(room.part))
|
|
2050
|
+
}),
|
|
2051
|
+
() => ({
|
|
2052
|
+
pos: pos.get(master.key),
|
|
2053
|
+
id: master.id,
|
|
2054
|
+
xml: master.xml,
|
|
2055
|
+
part: toBase64(master.part),
|
|
2056
|
+
...master.rels !== void 0 ? { rels: master.rels } : {}
|
|
2057
|
+
}),
|
|
2058
|
+
true
|
|
2059
|
+
);
|
|
2060
|
+
syncShapes(ctx, { key: masterScope(master.key), shapes: master.shapes });
|
|
2061
|
+
syncConnects(ctx, master.connects);
|
|
2062
|
+
}
|
|
2063
|
+
}
|
|
2064
|
+
function syncMedia(ctx, snapshot) {
|
|
2065
|
+
const { shared } = ctx;
|
|
2066
|
+
for (const item of snapshot.media) {
|
|
2067
|
+
const known = ctx.keys.mediaKeys.get(item.path);
|
|
2068
|
+
const key = known?.startsWith(`${item.hash}|`) ? known : mediaKey(item.hash, item.path);
|
|
2069
|
+
ctx.now.set(mediaId(key), "");
|
|
2070
|
+
if (!mediaEntry(shared.media.get(key))) {
|
|
2071
|
+
ctx.write(shared.media, key, {
|
|
2072
|
+
path: item.path,
|
|
2073
|
+
hash: item.hash,
|
|
2074
|
+
ct: item.ct,
|
|
2075
|
+
d: item.d,
|
|
2076
|
+
b: ctx.batch
|
|
2077
|
+
});
|
|
2078
|
+
shared.blobs.set(item.hash, toBase64(item.data));
|
|
2079
|
+
} else if (!shared.blobs.has(item.hash)) shared.blobs.set(item.hash, toBase64(item.data));
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2082
|
+
function syncParts(ctx, snapshot) {
|
|
2083
|
+
const { shared, keys } = ctx;
|
|
2084
|
+
for (const [path, data] of snapshot.parts) {
|
|
2085
|
+
const print = fingerprint(data);
|
|
2086
|
+
if (keys.partPrints.get(path) === print) continue;
|
|
2087
|
+
ctx.write(shared.parts, path, toBase64(data));
|
|
2088
|
+
keys.partPrints.set(path, print);
|
|
2089
|
+
}
|
|
2090
|
+
let removed = 0;
|
|
2091
|
+
for (const path of [...keys.partPrints.keys()])
|
|
2092
|
+
if (!snapshot.parts.has(path)) {
|
|
2093
|
+
shared.parts.delete(path);
|
|
2094
|
+
keys.partPrints.delete(path);
|
|
2095
|
+
removed++;
|
|
2096
|
+
}
|
|
2097
|
+
return removed;
|
|
2098
|
+
}
|
|
2099
|
+
|
|
2100
|
+
// visio/collab/write.ts
|
|
2101
|
+
function removeScope(shared, name) {
|
|
2102
|
+
shared.renum.delete(name);
|
|
2103
|
+
for (const map of [shared.shapes, shared.cells, shared.connects, shared.renum])
|
|
2104
|
+
for (const key of [...map.keys()]) if (key.startsWith(`${name}/`)) map.delete(key);
|
|
2105
|
+
}
|
|
2106
|
+
function removePage(shared, name) {
|
|
2107
|
+
shared.dead.set(name, true);
|
|
2108
|
+
for (const map of [shared.pages, shared.bodies]) map.delete(name);
|
|
2109
|
+
removeScope(shared, name);
|
|
2110
|
+
}
|
|
2111
|
+
function writeSharedDrawing(shared, snapshot, keys) {
|
|
2112
|
+
assertSchemaVersion(shared);
|
|
2113
|
+
let writes = 0;
|
|
2114
|
+
const write = (map, key, value) => {
|
|
2115
|
+
if (setIfChanged(map, key, value)) writes++;
|
|
2116
|
+
};
|
|
2117
|
+
const now = /* @__PURE__ */ new Map();
|
|
2118
|
+
const ctx = { shared, keys, now, batch: keys.batch(), write };
|
|
2119
|
+
write(shared.meta, "v", SCHEMA_VERSION);
|
|
2120
|
+
write(shared.meta, "pagesPath", snapshot.pagesPath);
|
|
2121
|
+
write(shared.meta, "pagesOpen", snapshot.pagesOpen);
|
|
2122
|
+
write(shared.meta, "pagesClose", snapshot.pagesClose);
|
|
2123
|
+
if (snapshot.mastersPath !== void 0) {
|
|
2124
|
+
write(shared.meta, "mastersPath", snapshot.mastersPath);
|
|
2125
|
+
write(shared.meta, "mastersOpen", snapshot.mastersOpen);
|
|
2126
|
+
write(shared.meta, "mastersClose", snapshot.mastersClose);
|
|
2127
|
+
}
|
|
2128
|
+
const pagePos = assignPositions(
|
|
2129
|
+
snapshot.pages.map((p) => p.key),
|
|
2130
|
+
(key) => pageEntry(shared.pages.get(key))?.pos
|
|
2131
|
+
);
|
|
2132
|
+
for (const page of snapshot.pages) {
|
|
2133
|
+
const room = pageEntry(shared.pages.get(page.key));
|
|
2134
|
+
syncEntry(
|
|
2135
|
+
ctx,
|
|
2136
|
+
shared.pages,
|
|
2137
|
+
page.key,
|
|
2138
|
+
pageId(page.key),
|
|
2139
|
+
pageContent(page),
|
|
2140
|
+
room,
|
|
2141
|
+
() => pageContent(room),
|
|
2142
|
+
() => ({
|
|
2143
|
+
pos: pagePos.get(page.key),
|
|
2144
|
+
id: page.id,
|
|
2145
|
+
...page.back !== void 0 ? { back: page.back } : {},
|
|
2146
|
+
xml: page.xml
|
|
2147
|
+
})
|
|
2148
|
+
);
|
|
2149
|
+
const roomBody = bodyEntry(shared.bodies.get(page.key));
|
|
2150
|
+
syncEntry(
|
|
2151
|
+
ctx,
|
|
2152
|
+
shared.bodies,
|
|
2153
|
+
page.key,
|
|
2154
|
+
bodyId(page.key),
|
|
2155
|
+
bodyContent(page),
|
|
2156
|
+
roomBody,
|
|
2157
|
+
() => bodyContent(roomBody),
|
|
2158
|
+
() => ({ shell: page.shell, ...page.rels !== void 0 ? { rels: page.rels } : {} }),
|
|
2159
|
+
true
|
|
2160
|
+
);
|
|
2161
|
+
syncShapes(ctx, page);
|
|
2162
|
+
syncConnects(ctx, page.connects);
|
|
2163
|
+
}
|
|
2164
|
+
syncMasters(ctx, snapshot);
|
|
2165
|
+
syncMedia(ctx, snapshot);
|
|
2166
|
+
for (const id of keys.known.keys()) {
|
|
2167
|
+
if (now.has(id)) continue;
|
|
2168
|
+
const name = id.slice(2);
|
|
2169
|
+
switch (id.slice(0, 2)) {
|
|
2170
|
+
case "p:":
|
|
2171
|
+
removePage(shared, name);
|
|
2172
|
+
keys.forgetPage(name);
|
|
2173
|
+
writes++;
|
|
2174
|
+
break;
|
|
2175
|
+
case "s:": {
|
|
2176
|
+
const slash = name.indexOf("/");
|
|
2177
|
+
const page = name.slice(0, slash);
|
|
2178
|
+
if (!now.has(page.startsWith(masterScope("")) ? masterId(page.slice(2)) : pageId(page)))
|
|
2179
|
+
break;
|
|
2180
|
+
shared.dead.set(name, true);
|
|
2181
|
+
shared.shapes.delete(name);
|
|
2182
|
+
keys.forgetShape(page, name.slice(slash + 1));
|
|
2183
|
+
writes++;
|
|
2184
|
+
break;
|
|
2185
|
+
}
|
|
2186
|
+
case "f:":
|
|
2187
|
+
if (shared.cells.has(name)) {
|
|
2188
|
+
shared.cells.delete(name);
|
|
2189
|
+
writes++;
|
|
2190
|
+
}
|
|
2191
|
+
break;
|
|
2192
|
+
case "c:":
|
|
2193
|
+
if (shared.connects.has(name)) {
|
|
2194
|
+
shared.connects.delete(name);
|
|
2195
|
+
writes++;
|
|
2196
|
+
}
|
|
2197
|
+
break;
|
|
2198
|
+
case "m:":
|
|
2199
|
+
if (shared.masters.has(name)) {
|
|
2200
|
+
shared.masters.delete(name);
|
|
2201
|
+
removeScope(shared, masterScope(name));
|
|
2202
|
+
writes++;
|
|
2203
|
+
}
|
|
2204
|
+
keys.forgetMaster(name);
|
|
2205
|
+
break;
|
|
2206
|
+
case "i:":
|
|
2207
|
+
if (shared.media.has(name)) {
|
|
2208
|
+
shared.media.delete(name);
|
|
2209
|
+
writes++;
|
|
2210
|
+
}
|
|
2211
|
+
break;
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
keys.known = now;
|
|
2215
|
+
writes += syncParts(ctx, snapshot);
|
|
2216
|
+
return writes;
|
|
1019
2217
|
}
|
|
1020
2218
|
|
|
1021
2219
|
// visio/collab/bind.ts
|
|
1022
2220
|
var VISIO_EDIT_ORIGIN = /* @__PURE__ */ Symbol("ooxml-core:visio:edit");
|
|
1023
2221
|
var VISIO_SYNC_ORIGIN = /* @__PURE__ */ Symbol("ooxml-core:visio:sync");
|
|
2222
|
+
var VISIO_FIXUP_ORIGIN = /* @__PURE__ */ Symbol("ooxml-core:visio:fixup");
|
|
1024
2223
|
function bindDrawingSession(host, editor, options = {}) {
|
|
1025
2224
|
const { doc } = host;
|
|
1026
2225
|
const shared = sharedDrawing(doc);
|
|
@@ -1040,6 +2239,12 @@ function bindDrawingSession(host, editor, options = {}) {
|
|
|
1040
2239
|
let settled = false;
|
|
1041
2240
|
let localDirty = false;
|
|
1042
2241
|
let remoteDirty = false;
|
|
2242
|
+
let incompatible = false;
|
|
2243
|
+
let queued = false;
|
|
2244
|
+
let queuedDone;
|
|
2245
|
+
const schedule = options.schedule ?? ((run) => {
|
|
2246
|
+
setTimeout(run, 0);
|
|
2247
|
+
});
|
|
1043
2248
|
let running;
|
|
1044
2249
|
const report = (error) => options.onError?.(error);
|
|
1045
2250
|
const publish = async () => {
|
|
@@ -1058,7 +2263,14 @@ function bindDrawingSession(host, editor, options = {}) {
|
|
|
1058
2263
|
const rebuild = async () => {
|
|
1059
2264
|
const resolved = readSharedDrawing(shared);
|
|
1060
2265
|
if (!resolved) return;
|
|
2266
|
+
if (resolved.fixups.length && host.canWrite())
|
|
2267
|
+
doc.transact(() => applyFixups(shared, resolved.fixups), VISIO_FIXUP_ORIGIN);
|
|
1061
2268
|
const version = editor.version();
|
|
2269
|
+
if (keys.applied?.signature === resolved.signature && keys.applied.version === version) return;
|
|
2270
|
+
const before = keys.applied;
|
|
2271
|
+
const change = before && before.version === version && before.base === resolved.baseSignature ? {
|
|
2272
|
+
pages: resolved.pages.filter((page) => before.pages.get(page.key) !== page.contentSignature).map((page) => page.id)
|
|
2273
|
+
} : void 0;
|
|
1062
2274
|
const composed = await composeDrawing(resolved, editor.exportBytes(), keys);
|
|
1063
2275
|
if (disposed) return;
|
|
1064
2276
|
if (editor.busy() || editor.version() !== version) {
|
|
@@ -1066,15 +2278,21 @@ function bindDrawingSession(host, editor, options = {}) {
|
|
|
1066
2278
|
return;
|
|
1067
2279
|
}
|
|
1068
2280
|
try {
|
|
1069
|
-
await editor.applyRemote(composed.bytes);
|
|
2281
|
+
await editor.applyRemote(composed.bytes, change);
|
|
1070
2282
|
} catch (error) {
|
|
1071
2283
|
if (editor.busy()) remoteDirty = true;
|
|
1072
2284
|
else report(error);
|
|
1073
2285
|
return;
|
|
1074
2286
|
}
|
|
1075
2287
|
composed.commit();
|
|
2288
|
+
keys.applied = {
|
|
2289
|
+
signature: composed.signature,
|
|
2290
|
+
version: editor.version(),
|
|
2291
|
+
base: resolved.baseSignature,
|
|
2292
|
+
pages: new Map(resolved.pages.map((page) => [page.key, page.contentSignature]))
|
|
2293
|
+
};
|
|
1076
2294
|
};
|
|
1077
|
-
const blocked = () => disposed || !settled || editor.busy();
|
|
2295
|
+
const blocked = () => disposed || incompatible || !settled || editor.busy();
|
|
1078
2296
|
const pending = () => !blocked() && (localDirty && host.canWrite() || remoteDirty && !localDirty);
|
|
1079
2297
|
const loop = async () => {
|
|
1080
2298
|
while (pending()) {
|
|
@@ -1087,6 +2305,7 @@ function bindDrawingSession(host, editor, options = {}) {
|
|
|
1087
2305
|
await rebuild();
|
|
1088
2306
|
}
|
|
1089
2307
|
} catch (error) {
|
|
2308
|
+
if (error instanceof SchemaVersionError) incompatible = true;
|
|
1090
2309
|
report(error);
|
|
1091
2310
|
}
|
|
1092
2311
|
}
|
|
@@ -1113,18 +2332,30 @@ function bindDrawingSession(host, editor, options = {}) {
|
|
|
1113
2332
|
}
|
|
1114
2333
|
pump();
|
|
1115
2334
|
};
|
|
2335
|
+
const queueRemote = () => {
|
|
2336
|
+
if (queued) return;
|
|
2337
|
+
queued = true;
|
|
2338
|
+
queuedDone = new Promise(
|
|
2339
|
+
(resolve) => schedule(() => {
|
|
2340
|
+
queued = false;
|
|
2341
|
+
remoteDirty = true;
|
|
2342
|
+
resolve();
|
|
2343
|
+
pump();
|
|
2344
|
+
})
|
|
2345
|
+
);
|
|
2346
|
+
};
|
|
1116
2347
|
const afterTransaction = (transaction) => {
|
|
1117
2348
|
if (disposed) return;
|
|
1118
2349
|
const origin = transaction.origin;
|
|
1119
|
-
if (origin === VISIO_EDIT_ORIGIN || origin === VISIO_SYNC_ORIGIN)
|
|
2350
|
+
if (origin === VISIO_EDIT_ORIGIN || origin === VISIO_SYNC_ORIGIN || origin === VISIO_FIXUP_ORIGIN)
|
|
2351
|
+
return;
|
|
1120
2352
|
const changed = transaction.changed;
|
|
1121
2353
|
if (!types.some((type) => changed.has(type))) return;
|
|
1122
2354
|
if (!settled) {
|
|
1123
2355
|
if (!isSharedDrawingEmpty(shared)) settle();
|
|
1124
2356
|
return;
|
|
1125
2357
|
}
|
|
1126
|
-
|
|
1127
|
-
pump();
|
|
2358
|
+
queueRemote();
|
|
1128
2359
|
};
|
|
1129
2360
|
doc.on("afterTransaction", afterTransaction);
|
|
1130
2361
|
const stops = [
|
|
@@ -1142,7 +2373,10 @@ function bindDrawingSession(host, editor, options = {}) {
|
|
|
1142
2373
|
];
|
|
1143
2374
|
if (host.synced || host.canWrite()) settle();
|
|
1144
2375
|
const idle = async () => {
|
|
1145
|
-
while (running)
|
|
2376
|
+
while (running || queued) {
|
|
2377
|
+
if (queued) await queuedDone;
|
|
2378
|
+
if (running) await running;
|
|
2379
|
+
}
|
|
1146
2380
|
};
|
|
1147
2381
|
const replay = async (kind) => {
|
|
1148
2382
|
await idle();
|
|
@@ -1174,17 +2408,25 @@ function bindDrawingSession(host, editor, options = {}) {
|
|
|
1174
2408
|
};
|
|
1175
2409
|
}
|
|
1176
2410
|
|
|
2411
|
+
exports.BLOBS = BLOBS;
|
|
1177
2412
|
exports.BODIES = BODIES;
|
|
2413
|
+
exports.CELLS = CELLS;
|
|
1178
2414
|
exports.CONNECTS = CONNECTS;
|
|
1179
2415
|
exports.DEAD = DEAD;
|
|
1180
2416
|
exports.DrawingKeys = DrawingKeys;
|
|
2417
|
+
exports.MASTERS = MASTERS;
|
|
2418
|
+
exports.MEDIA = MEDIA;
|
|
1181
2419
|
exports.META = META;
|
|
1182
2420
|
exports.PAGES = PAGES;
|
|
1183
2421
|
exports.PARTS = PARTS;
|
|
2422
|
+
exports.RENUM = RENUM;
|
|
1184
2423
|
exports.SCHEMA_VERSION = SCHEMA_VERSION;
|
|
1185
2424
|
exports.SHAPES = SHAPES;
|
|
2425
|
+
exports.SchemaVersionError = SchemaVersionError;
|
|
1186
2426
|
exports.VISIO_EDIT_ORIGIN = VISIO_EDIT_ORIGIN;
|
|
2427
|
+
exports.VISIO_FIXUP_ORIGIN = VISIO_FIXUP_ORIGIN;
|
|
1187
2428
|
exports.VISIO_SYNC_ORIGIN = VISIO_SYNC_ORIGIN;
|
|
2429
|
+
exports.applyFixups = applyFixups;
|
|
1188
2430
|
exports.bindDrawingSession = bindDrawingSession;
|
|
1189
2431
|
exports.composeDrawing = composeDrawing;
|
|
1190
2432
|
exports.isSharedDrawingEmpty = isSharedDrawingEmpty;
|