ooxml-core 1.23.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.
Files changed (83) hide show
  1. package/dist/automation/index.cjs +553 -335
  2. package/dist/automation/index.d.ts +1 -0
  3. package/dist/automation/index.d.ts.map +1 -1
  4. package/dist/automation/index.mjs +552 -336
  5. package/dist/automation/live.d.ts +89 -0
  6. package/dist/automation/live.d.ts.map +1 -0
  7. package/dist/docx/ui/customization.d.ts +30 -0
  8. package/dist/docx/ui/customization.d.ts.map +1 -0
  9. package/dist/docx/ui/index.cjs +51 -0
  10. package/dist/docx/ui/index.d.ts +1 -0
  11. package/dist/docx/ui/index.d.ts.map +1 -1
  12. package/dist/docx/ui/index.mjs +46 -1
  13. package/dist/embedding/backstage.d.ts +48 -0
  14. package/dist/embedding/backstage.d.ts.map +1 -0
  15. package/dist/embedding/capabilities.d.ts +60 -0
  16. package/dist/embedding/capabilities.d.ts.map +1 -0
  17. package/dist/embedding/customization.d.ts +32 -0
  18. package/dist/embedding/customization.d.ts.map +1 -0
  19. package/dist/embedding/index.cjs +229 -0
  20. package/dist/embedding/index.d.ts +7 -0
  21. package/dist/embedding/index.d.ts.map +1 -0
  22. package/dist/embedding/index.mjs +204 -0
  23. package/dist/embedding/menu-commands.d.ts +66 -0
  24. package/dist/embedding/menu-commands.d.ts.map +1 -0
  25. package/dist/embedding/regions.d.ts +58 -0
  26. package/dist/embedding/regions.d.ts.map +1 -0
  27. package/dist/embedding/storage.d.ts +111 -0
  28. package/dist/embedding/storage.d.ts.map +1 -0
  29. package/dist/index.cjs +233 -0
  30. package/dist/index.d.ts +1 -0
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.mjs +233 -1
  33. package/dist/visio/collab/compose.d.ts.map +1 -1
  34. package/dist/visio/collab/fixups.d.ts.map +1 -1
  35. package/dist/visio/collab/index.cjs +167 -62
  36. package/dist/visio/collab/index.mjs +167 -62
  37. package/dist/visio/collab/keys.d.ts +2 -0
  38. package/dist/visio/collab/keys.d.ts.map +1 -1
  39. package/dist/visio/collab/pieces.d.ts +7 -0
  40. package/dist/visio/collab/pieces.d.ts.map +1 -1
  41. package/dist/visio/collab/read-ids.d.ts +7 -1
  42. package/dist/visio/collab/read-ids.d.ts.map +1 -1
  43. package/dist/visio/collab/read-parts.d.ts.map +1 -1
  44. package/dist/visio/collab/read-shapes.d.ts +0 -1
  45. package/dist/visio/collab/read-shapes.d.ts.map +1 -1
  46. package/dist/visio/collab/read.d.ts.map +1 -1
  47. package/dist/visio/collab/schema.d.ts +1 -1
  48. package/dist/visio/collab/schema.d.ts.map +1 -1
  49. package/dist/visio/collab/snapshot-contents.d.ts.map +1 -1
  50. package/dist/visio/collab/write-shapes.d.ts.map +1 -1
  51. package/dist/visio/collab/zip-store.d.ts +4 -0
  52. package/dist/visio/collab/zip-store.d.ts.map +1 -0
  53. package/dist/visio/document-level.d.ts +57 -0
  54. package/dist/visio/document-level.d.ts.map +1 -0
  55. package/dist/visio/index.cjs +543 -444
  56. package/dist/visio/index.d.ts +1 -0
  57. package/dist/visio/index.d.ts.map +1 -1
  58. package/dist/visio/index.mjs +543 -444
  59. package/dist/visio/layers.d.ts +3 -0
  60. package/dist/visio/layers.d.ts.map +1 -1
  61. package/dist/visio/package.d.ts +9 -0
  62. package/dist/visio/package.d.ts.map +1 -1
  63. package/dist/visio/parser.d.ts +7 -0
  64. package/dist/visio/parser.d.ts.map +1 -1
  65. package/dist/visio/shape-metadata.d.ts +3 -0
  66. package/dist/visio/shape-metadata.d.ts.map +1 -1
  67. package/dist/visio/ui/contract.d.ts +27 -2
  68. package/dist/visio/ui/contract.d.ts.map +1 -1
  69. package/dist/visio/ui/customization.d.ts +46 -0
  70. package/dist/visio/ui/customization.d.ts.map +1 -0
  71. package/dist/visio/ui/index.cjs +454 -316
  72. package/dist/visio/ui/index.d.ts +1 -0
  73. package/dist/visio/ui/index.d.ts.map +1 -1
  74. package/dist/visio/ui/index.mjs +452 -317
  75. package/dist/xlsx/ui/commands.d.ts +2 -0
  76. package/dist/xlsx/ui/commands.d.ts.map +1 -1
  77. package/dist/xlsx/ui/customization.d.ts +49 -0
  78. package/dist/xlsx/ui/customization.d.ts.map +1 -0
  79. package/dist/xlsx/ui/index.cjs +39 -1
  80. package/dist/xlsx/ui/index.d.ts +1 -0
  81. package/dist/xlsx/ui/index.d.ts.map +1 -1
  82. package/dist/xlsx/ui/index.mjs +37 -2
  83. 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
 
@@ -619,7 +619,7 @@ var entryContent = (e) => e.xml !== void 0 ? pieceContent("leaf", e.xml) : piece
619
619
  var masterContent = (e) => JSON.stringify([e.id, canon(e.xml), e.rels ?? null, e.print]);
620
620
 
621
621
  // visio/collab/schema.ts
622
- var SCHEMA_VERSION = 3;
622
+ var SCHEMA_VERSION = 4;
623
623
  var SchemaVersionError = class extends Error {
624
624
  constructor(found) {
625
625
  super(
@@ -723,7 +723,13 @@ function cellEntry(value) {
723
723
  const xml = str(value.xml);
724
724
  const open = str(value.open);
725
725
  if (pos === void 0 || xml === void 0 && open === void 0) return void 0;
726
- return { pos, ...opt("xml", xml), ...opt("open", xml === void 0 ? open : void 0) };
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
+ };
727
733
  }
728
734
  function masterEntry(value) {
729
735
  if (!isRecord(value)) return void 0;
@@ -777,6 +783,20 @@ function splitList(text, name, mark, child) {
777
783
  }
778
784
  return { text: text.slice(0, box.openEnd) + mark + text.slice(box.closeStart), items };
779
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
+ }
780
800
  function flatten(xml, parent, page, keys, out) {
781
801
  const split2 = splitShape(xml);
782
802
  const id = split2 ? attrOf(split2.open, "ID") : void 0;
@@ -797,6 +817,12 @@ function splitContents(content, scope, keys) {
797
817
  const shapes = [];
798
818
  for (const text of shapesSplit.items) flatten(text, void 0, scope, keys, shapes);
799
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
+ }
800
826
  const connects = [];
801
827
  for (const text of connectsSplit.items) {
802
828
  const a = (name) => attrOf(text, name) ?? "";
@@ -1042,6 +1068,80 @@ async function placeList(options) {
1042
1068
  );
1043
1069
  return paths;
1044
1070
  }
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;
1079
+ }
1080
+
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);
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;
1099
+ }
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;
1120
+ }
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;
1144
+ }
1045
1145
 
1046
1146
  // visio/collab/compose.ts
1047
1147
  var DEFAULT_CONTENT_TYPES = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"></Types>';
@@ -1180,12 +1280,16 @@ async function composeDrawing(drawing, local, keys, options = {}) {
1180
1280
  contentTypes = withOverrides(contentTypes, MASTER_CONTENT_TYPE, [...masterPaths.values()]);
1181
1281
  }
1182
1282
  files.set(CONTENT_TYPES, encoder.encode(contentTypes));
1183
- const zip = new JSZip__default.default();
1184
1283
  const names = [...files.keys()].sort(
1185
1284
  (a, b) => a === CONTENT_TYPES ? -1 : b === CONTENT_TYPES ? 1 : 0
1186
1285
  );
1187
- for (const name of names) zip.file(name, files.get(name), { createFolders: false });
1188
- const bytes = await zip.generateAsync({ type: "uint8array", compression: "STORE" });
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
+ );
1189
1293
  const commit = () => {
1190
1294
  const pageIds = /* @__PURE__ */ new Map();
1191
1295
  const shapeIds = /* @__PURE__ */ new Map();
@@ -1236,8 +1340,7 @@ async function composeDrawing(drawing, local, keys, options = {}) {
1236
1340
  function applyFixups(shared, fixups) {
1237
1341
  let changed = 0;
1238
1342
  for (const fixup of fixups) {
1239
- const map = fixup.map === "renum" ? shared.renum : shared.cells;
1240
- if (setIfChanged(map, fixup.key, fixup.value)) changed++;
1343
+ if (setIfChanged(shared.renum, fixup.key, fixup.value)) changed++;
1241
1344
  }
1242
1345
  return changed;
1243
1346
  }
@@ -1267,7 +1370,9 @@ var DrawingKeys = class {
1267
1370
  /** Serialised page parts and decoded shared parts of the last rebuild, to skip unchanged work. */
1268
1371
  cache = {
1269
1372
  pageParts: /* @__PURE__ */ new Map(),
1270
- parts: /* @__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()
1271
1376
  };
1272
1377
  /**
1273
1378
  * What was last applied to the editor: the drawing signature, the editor version it produced,
@@ -1386,19 +1491,22 @@ function assignIds(items) {
1386
1491
  const order = [...items].sort(
1387
1492
  (a, b) => Number(b.fixed !== void 0) - Number(a.fixed !== void 0) || compare(a.key, b.key)
1388
1493
  );
1389
- const used = /* @__PURE__ */ new Set();
1390
1494
  const ids = /* @__PURE__ */ new Map();
1391
1495
  const fresh = /* @__PURE__ */ new Map();
1496
+ const holder = /* @__PURE__ */ new Map();
1497
+ const claims = /* @__PURE__ */ new Set();
1392
1498
  for (const item of order) {
1393
1499
  let id = effective(item);
1394
- if (used.has(id)) {
1500
+ const taken = holder.get(id);
1501
+ if (taken) {
1502
+ if (taken.fixed === void 0) claims.add(taken.key);
1395
1503
  id = String(++max);
1396
1504
  fresh.set(item.key, { from: item.id, to: id });
1397
1505
  }
1398
- used.add(id);
1506
+ holder.set(id, item);
1399
1507
  ids.set(item.key, id);
1400
1508
  }
1401
- return { ids, fresh };
1509
+ return { ids, fresh, claims };
1402
1510
  }
1403
1511
  var fixedId = (renum, key, id) => {
1404
1512
  const pair = renum.get(key)?.i;
@@ -1412,6 +1520,11 @@ function readRenum(shared) {
1412
1520
  }
1413
1521
  return out;
1414
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
+ }
1415
1528
 
1416
1529
  // visio/collab/read-util.ts
1417
1530
  function hashTexts(texts) {
@@ -1471,6 +1584,14 @@ function renumberFormulas(xml, remap) {
1471
1584
  return `${head}${value[0]}${body}${value[0]}`;
1472
1585
  });
1473
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
+ }
1474
1595
  function resolveShapes(input) {
1475
1596
  const raw = /* @__PURE__ */ new Map();
1476
1597
  for (const [key, entry] of input.shapes) {
@@ -1489,31 +1610,16 @@ function resolveShapes(input) {
1489
1610
  return ok;
1490
1611
  };
1491
1612
  const live = [...raw.keys()].filter((k) => valid(k)).sort(compare);
1492
- const { ids: finalId, fresh: renumbered } = assignIds(
1613
+ const {
1614
+ ids: finalId,
1615
+ fresh: renumbered,
1616
+ claims
1617
+ } = assignIds(
1493
1618
  live.map((key) => {
1494
1619
  const { id } = raw.get(key);
1495
1620
  return { key, id, fixed: fixedId(input.renum, key, id) };
1496
1621
  })
1497
1622
  );
1498
- const batchRemap = /* @__PURE__ */ new Map();
1499
- for (const [key, change] of renumbered) {
1500
- const b = raw.get(key).entry.b;
1501
- if (b === void 0) continue;
1502
- const map = batchRemap.get(b) ?? /* @__PURE__ */ new Map();
1503
- map.set(change.from, change.to);
1504
- batchRemap.set(b, map);
1505
- }
1506
- const remapFor = (key) => {
1507
- const out = new Map(batchRemap.get(raw.get(key).entry.b ?? "") ?? []);
1508
- const chain = [];
1509
- for (let k = key; k !== void 0; k = raw.get(k)?.entry.parent)
1510
- chain.unshift(k);
1511
- for (const k of chain) {
1512
- const change = renumbered.get(k);
1513
- if (change) out.set(change.from, change.to);
1514
- }
1515
- return out;
1516
- };
1517
1623
  const children = /* @__PURE__ */ new Map();
1518
1624
  for (const key of live) {
1519
1625
  const parent = raw.get(key).entry.parent ?? "";
@@ -1525,15 +1631,16 @@ function resolveShapes(input) {
1525
1631
  const render = (key) => {
1526
1632
  const { entry } = raw.get(key);
1527
1633
  const id = finalId.get(key);
1528
- const remap = remapFor(key);
1529
1634
  let open = setAttr(entry.open, "ID", id);
1530
- const record = { ...input.renum.get(key) };
1531
- let dirty = false;
1532
- const change = renumbered.get(key);
1533
- if (change) {
1534
- record.i = [change.from, change.to];
1535
- dirty = true;
1536
- }
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;
1537
1644
  const master = attrOf(open, "Master");
1538
1645
  const persisted = record.m && record.m[0] === master ? record.m[1] : void 0;
1539
1646
  const batched = master !== void 0 ? input.masterRemap.get(entry.b ?? "")?.get(master) : void 0;
@@ -1546,13 +1653,9 @@ function resolveShapes(input) {
1546
1653
  if (dirty) fixups.push({ map: "renum", key: `${input.scope}/${key}`, value: record });
1547
1654
  const entries = /* @__PURE__ */ new Map();
1548
1655
  for (const [path, piece] of input.cells.get(key) ?? []) {
1549
- const leaf = piece.xml !== void 0 && /(^|\/)c\/[^/]*$/.test(path);
1550
- const xml2 = leaf ? renumberFormulas(piece.xml, remap) : void 0;
1551
- if (xml2 !== void 0 && xml2 !== piece.xml) {
1552
- const value = { ...piece, xml: xml2 };
1553
- entries.set(path, value);
1554
- fixups.push({ map: "cells", key: `${input.scope}/${key}/${path}`, value });
1555
- } else entries.set(path, piece);
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);
1556
1659
  }
1557
1660
  shapes.push({
1558
1661
  key,
@@ -1576,7 +1679,7 @@ function resolveMasters(shared, renum) {
1576
1679
  const entry = masterEntry(value);
1577
1680
  if (entry) alive.push({ key, entry });
1578
1681
  }
1579
- const { ids, fresh } = assignIds(
1682
+ const { ids, fresh, claims } = assignIds(
1580
1683
  alive.map(({ key, entry }) => ({
1581
1684
  key,
1582
1685
  id: entry.id,
@@ -1592,11 +1695,10 @@ function resolveMasters(shared, renum) {
1592
1695
  map.set(change.from, change.to);
1593
1696
  remap.set(b, map);
1594
1697
  }
1595
- fixups.push({
1596
- map: "renum",
1597
- key: masterScope(key),
1598
- value: { ...renum.get(masterScope(key)), i: [change.from, change.to] }
1599
- });
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 });
1600
1702
  }
1601
1703
  alive.sort((a, b) => a.entry.pos - b.entry.pos || compare2(a.key, b.key));
1602
1704
  return {
@@ -1682,19 +1784,21 @@ function readSharedDrawing(shared) {
1682
1784
  });
1683
1785
  const renum = readRenum(shared);
1684
1786
  const fixups = [];
1685
- const { ids: pageIds, fresh: freshPages } = assignIds(
1787
+ const {
1788
+ ids: pageIds,
1789
+ fresh: freshPages,
1790
+ claims: pageClaims
1791
+ } = assignIds(
1686
1792
  alive.map((p) => ({
1687
1793
  key: p.key,
1688
1794
  id: p.entry.id,
1689
1795
  fixed: fixedId(renum, p.key, p.entry.id)
1690
1796
  }))
1691
1797
  );
1692
- for (const [key, change] of [...freshPages].sort((a, b) => compare(a[0], b[0])))
1693
- fixups.push({
1694
- map: "renum",
1695
- key,
1696
- value: { ...renum.get(key), i: [change.from, change.to] }
1697
- });
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 });
1801
+ }
1698
1802
  const shapesByPage = /* @__PURE__ */ new Map();
1699
1803
  for (const [full, value] of shared.shapes) {
1700
1804
  const parts2 = split(full, 1);
@@ -1906,7 +2010,8 @@ function syncShapes(ctx, page) {
1906
2010
  const roomCell = cellEntry(shared.cells.get(cellKey));
1907
2011
  const local = () => ({
1908
2012
  pos: piecePos.get(piece.path),
1909
- ...piece.kind === "leaf" ? { xml: piece.text } : { open: piece.text }
2013
+ ...piece.kind === "leaf" ? { xml: piece.text } : { open: piece.text },
2014
+ ...piece.refs ? { r: piece.refs } : {}
1910
2015
  });
1911
2016
  syncEntry(
1912
2017
  ctx,