ooxml-core 0.13.0 → 0.14.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.
@@ -0,0 +1,21 @@
1
+ import type { Transport } from './provider.js';
2
+ /** Structural BroadcastChannel, so the area needs no DOM types. */
3
+ export interface BroadcastChannelLike {
4
+ postMessage: (message: unknown) => void;
5
+ close: () => void;
6
+ onmessage: ((event: {
7
+ data: unknown;
8
+ }) => void) | null;
9
+ }
10
+ export type BroadcastChannelConstructor = new (name: string) => BroadcastChannelLike;
11
+ export interface BroadcastTransportOptions {
12
+ roomId: string;
13
+ /** Channel name prefix; one channel per room. Default `ooxml-collab:`. */
14
+ prefix?: string;
15
+ /** Defaults to `globalThis.BroadcastChannel`. */
16
+ BroadcastChannel?: BroadcastChannelConstructor;
17
+ }
18
+ /** Whether this environment can create a BroadcastChannel transport. */
19
+ export declare function canBroadcast(scope?: object): boolean;
20
+ export declare function createBroadcastTransport(options: BroadcastTransportOptions): Transport;
21
+ //# sourceMappingURL=broadcast-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"broadcast-transport.d.ts","sourceRoot":"","sources":["../../src/collab/broadcast-transport.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAqB,MAAM,eAAe,CAAC;AAGlE,mEAAmE;AACnE,MAAM,WAAW,oBAAoB;IACpC,WAAW,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,SAAS,EAAE,CAAC,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;CACvD;AACD,MAAM,MAAM,2BAA2B,GAAG,KAAK,IAAI,EAAE,MAAM,KAAK,oBAAoB,CAAC;AAErF,MAAM,WAAW,yBAAyB;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,2BAA2B,CAAC;CAC/C;AAaD,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,KAAK,GAAE,MAAmB,GAAG,OAAO,CAEhE;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,yBAAyB,GAAG,SAAS,CAmDtF"}
@@ -485,6 +485,62 @@ function bindDocument(session, adapter, options) {
485
485
  }
486
486
  };
487
487
  }
488
+
489
+ // src/collab/broadcast-transport.ts
490
+ var isEnvelope = (value) => {
491
+ const envelope = value;
492
+ return !!envelope && typeof envelope.from === "string" && (envelope.kind === "hello" || envelope.kind === "data" && envelope.data instanceof Uint8Array);
493
+ };
494
+ function canBroadcast(scope = globalThis) {
495
+ return typeof scope.BroadcastChannel === "function";
496
+ }
497
+ function createBroadcastTransport(options) {
498
+ const roomId = validateRoomId(options.roomId);
499
+ const Channel = options.BroadcastChannel ?? globalThis.BroadcastChannel;
500
+ const self = Math.random().toString(36).slice(2) + Date.now().toString(36);
501
+ let channel = null;
502
+ let handlers = null;
503
+ const close = () => {
504
+ if (!channel) return;
505
+ channel.onmessage = null;
506
+ channel.close();
507
+ channel = null;
508
+ };
509
+ return {
510
+ connect(next) {
511
+ close();
512
+ handlers = next;
513
+ if (!Channel) {
514
+ next.error(new Error("BroadcastChannel is not available in this environment."));
515
+ next.close("unavailable");
516
+ return;
517
+ }
518
+ const open = new Channel(`${options.prefix ?? "ooxml-collab:"}${roomId}`);
519
+ channel = open;
520
+ open.onmessage = ({ data }) => {
521
+ if (channel !== open || !isEnvelope(data) || data.from === self) return;
522
+ if (data.kind === "hello") handlers?.peer?.();
523
+ else handlers?.message(data.data);
524
+ };
525
+ next.open();
526
+ open.postMessage({ kind: "hello", from: self });
527
+ },
528
+ send(data) {
529
+ try {
530
+ channel?.postMessage({ kind: "data", from: self, data });
531
+ } catch (cause) {
532
+ handlers?.error(cause instanceof Error ? cause : new Error(String(cause)));
533
+ }
534
+ },
535
+ disconnect() {
536
+ const was = handlers;
537
+ const open = channel !== null;
538
+ close();
539
+ handlers = null;
540
+ if (open) was?.close("disconnected");
541
+ }
542
+ };
543
+ }
488
544
  var MAX_UPDATE_BYTES = 32 * 1024 * 1024;
489
545
  function encodeSnapshot(doc) {
490
546
  return Y__namespace.encodeStateAsUpdate(doc);
@@ -801,6 +857,49 @@ function createMemoryHub(options = {}) {
801
857
  };
802
858
  }
803
859
 
860
+ // src/collab/package-adapter.ts
861
+ var DEFAULT_MAX_PACKAGE_BYTES = 32 * 1024 * 1024;
862
+ function packageAdapter(options = {}) {
863
+ const name = options.name ?? "package";
864
+ const maxBytes = options.maxBytes ?? DEFAULT_MAX_PACKAGE_BYTES;
865
+ const map = (doc) => doc.getMap(name);
866
+ const check = (bytes) => {
867
+ if (!(bytes instanceof Uint8Array)) throw new Error("The shared package is not binary data.");
868
+ if (bytes.byteLength > maxBytes)
869
+ throw new Error(`The shared package exceeds ${Math.round(maxBytes / 1024 / 1024)} MiB.`);
870
+ return bytes;
871
+ };
872
+ return {
873
+ isEmpty: (doc) => !(map(doc).get("bytes") instanceof Uint8Array),
874
+ read: (doc) => {
875
+ const shared = map(doc);
876
+ const revision = shared.get("revision");
877
+ return {
878
+ bytes: check(shared.get("bytes")).slice(),
879
+ revision: typeof revision === "number" && Number.isSafeInteger(revision) ? revision : 0
880
+ };
881
+ },
882
+ write: (doc, model, origin) => {
883
+ const bytes = check(model.bytes);
884
+ doc.transact(() => {
885
+ const shared = map(doc);
886
+ const current = shared.get("revision");
887
+ const revision = Math.max(model.revision, typeof current === "number" ? current : 0) + 1;
888
+ shared.set("bytes", bytes.slice());
889
+ shared.set("revision", revision);
890
+ }, origin);
891
+ },
892
+ observe: (doc, onChange) => {
893
+ const shared = map(doc);
894
+ const handler = (event) => {
895
+ if (event.keysChanged.has("bytes")) onChange(event.transaction.origin);
896
+ };
897
+ shared.observe(handler);
898
+ return () => shared.unobserve(handler);
899
+ }
900
+ };
901
+ }
902
+
804
903
  // src/collab/ordering.ts
805
904
  function classifyVersion(messageVersion, currentVersion) {
806
905
  if (!isNonNegativeSafeInteger(messageVersion) || !isNonNegativeSafeInteger(currentVersion))
@@ -1253,6 +1352,7 @@ exports.COLLAB_LEAVE_MESSAGE = COLLAB_LEAVE_MESSAGE;
1253
1352
  exports.CONNECTION_TIMEOUT_MS = CONNECTION_TIMEOUT_MS;
1254
1353
  exports.CURSOR_PALETTE = CURSOR_PALETTE;
1255
1354
  exports.DEFAULT_COLOR = DEFAULT_COLOR;
1355
+ exports.DEFAULT_MAX_PACKAGE_BYTES = DEFAULT_MAX_PACKAGE_BYTES;
1256
1356
  exports.DEPARTURE_CHANNEL = DEPARTURE_CHANNEL;
1257
1357
  exports.Emitter = Emitter;
1258
1358
  exports.INITIAL_SYNC_GRACE_MS = INITIAL_SYNC_GRACE_MS;
@@ -1276,11 +1376,13 @@ exports.assignUserColor = assignUserColor;
1276
1376
  exports.bindDocument = bindDocument;
1277
1377
  exports.borrowAwareness = borrowAwareness;
1278
1378
  exports.buildRoster = buildRoster;
1379
+ exports.canBroadcast = canBroadcast;
1279
1380
  exports.canWrite = canWrite;
1280
1381
  exports.clampCoordinate = clampCoordinate;
1281
1382
  exports.classifyVersion = classifyVersion;
1282
1383
  exports.clearLocalAwareness = clearLocalAwareness;
1283
1384
  exports.createAssetSync = createAssetSync;
1385
+ exports.createBroadcastTransport = createBroadcastTransport;
1284
1386
  exports.createClientId = createClientId;
1285
1387
  exports.createCollabSession = createCollabSession;
1286
1388
  exports.createDepartureChannel = createDepartureChannel;
@@ -1306,6 +1408,7 @@ exports.isValidId = isValidId;
1306
1408
  exports.isValidRoomId = isValidRoomId;
1307
1409
  exports.mergeUpdates = mergeUpdates2;
1308
1410
  exports.observeExternalSession = observeExternalSession;
1411
+ exports.packageAdapter = packageAdapter;
1309
1412
  exports.presenceToCursors = presenceToCursors;
1310
1413
  exports.registerTeardown = registerTeardown;
1311
1414
  exports.removeAwarenessStatesLocally = removeAwarenessStatesLocally;
@@ -1,12 +1,14 @@
1
1
  export * from './assets.js';
2
2
  export * from './awareness.js';
3
3
  export * from './binding.js';
4
+ export * from './broadcast-transport.js';
4
5
  export * from './codec.js';
5
6
  export * from './emitter.js';
6
7
  export * from './external-provider.js';
7
8
  export * from './identity.js';
8
9
  export * from './lifecycle.js';
9
10
  export * from './memory-transport.js';
11
+ export * from './package-adapter.js';
10
12
  export * from './ordering.js';
11
13
  export * from './policy.js';
12
14
  export * from './presence.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/collab/index.ts"],"names":[],"mappings":"AAIA,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,wBAAwB,CAAC;AACvC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/collab/index.ts"],"names":[],"mappings":"AAIA,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,0BAA0B,CAAC;AACzC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,wBAAwB,CAAC;AACvC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC"}
@@ -461,6 +461,62 @@ function bindDocument(session, adapter, options) {
461
461
  }
462
462
  };
463
463
  }
464
+
465
+ // src/collab/broadcast-transport.ts
466
+ var isEnvelope = (value) => {
467
+ const envelope = value;
468
+ return !!envelope && typeof envelope.from === "string" && (envelope.kind === "hello" || envelope.kind === "data" && envelope.data instanceof Uint8Array);
469
+ };
470
+ function canBroadcast(scope = globalThis) {
471
+ return typeof scope.BroadcastChannel === "function";
472
+ }
473
+ function createBroadcastTransport(options) {
474
+ const roomId = validateRoomId(options.roomId);
475
+ const Channel = options.BroadcastChannel ?? globalThis.BroadcastChannel;
476
+ const self = Math.random().toString(36).slice(2) + Date.now().toString(36);
477
+ let channel = null;
478
+ let handlers = null;
479
+ const close = () => {
480
+ if (!channel) return;
481
+ channel.onmessage = null;
482
+ channel.close();
483
+ channel = null;
484
+ };
485
+ return {
486
+ connect(next) {
487
+ close();
488
+ handlers = next;
489
+ if (!Channel) {
490
+ next.error(new Error("BroadcastChannel is not available in this environment."));
491
+ next.close("unavailable");
492
+ return;
493
+ }
494
+ const open = new Channel(`${options.prefix ?? "ooxml-collab:"}${roomId}`);
495
+ channel = open;
496
+ open.onmessage = ({ data }) => {
497
+ if (channel !== open || !isEnvelope(data) || data.from === self) return;
498
+ if (data.kind === "hello") handlers?.peer?.();
499
+ else handlers?.message(data.data);
500
+ };
501
+ next.open();
502
+ open.postMessage({ kind: "hello", from: self });
503
+ },
504
+ send(data) {
505
+ try {
506
+ channel?.postMessage({ kind: "data", from: self, data });
507
+ } catch (cause) {
508
+ handlers?.error(cause instanceof Error ? cause : new Error(String(cause)));
509
+ }
510
+ },
511
+ disconnect() {
512
+ const was = handlers;
513
+ const open = channel !== null;
514
+ close();
515
+ handlers = null;
516
+ if (open) was?.close("disconnected");
517
+ }
518
+ };
519
+ }
464
520
  var MAX_UPDATE_BYTES = 32 * 1024 * 1024;
465
521
  function encodeSnapshot(doc) {
466
522
  return Y.encodeStateAsUpdate(doc);
@@ -777,6 +833,49 @@ function createMemoryHub(options = {}) {
777
833
  };
778
834
  }
779
835
 
836
+ // src/collab/package-adapter.ts
837
+ var DEFAULT_MAX_PACKAGE_BYTES = 32 * 1024 * 1024;
838
+ function packageAdapter(options = {}) {
839
+ const name = options.name ?? "package";
840
+ const maxBytes = options.maxBytes ?? DEFAULT_MAX_PACKAGE_BYTES;
841
+ const map = (doc) => doc.getMap(name);
842
+ const check = (bytes) => {
843
+ if (!(bytes instanceof Uint8Array)) throw new Error("The shared package is not binary data.");
844
+ if (bytes.byteLength > maxBytes)
845
+ throw new Error(`The shared package exceeds ${Math.round(maxBytes / 1024 / 1024)} MiB.`);
846
+ return bytes;
847
+ };
848
+ return {
849
+ isEmpty: (doc) => !(map(doc).get("bytes") instanceof Uint8Array),
850
+ read: (doc) => {
851
+ const shared = map(doc);
852
+ const revision = shared.get("revision");
853
+ return {
854
+ bytes: check(shared.get("bytes")).slice(),
855
+ revision: typeof revision === "number" && Number.isSafeInteger(revision) ? revision : 0
856
+ };
857
+ },
858
+ write: (doc, model, origin) => {
859
+ const bytes = check(model.bytes);
860
+ doc.transact(() => {
861
+ const shared = map(doc);
862
+ const current = shared.get("revision");
863
+ const revision = Math.max(model.revision, typeof current === "number" ? current : 0) + 1;
864
+ shared.set("bytes", bytes.slice());
865
+ shared.set("revision", revision);
866
+ }, origin);
867
+ },
868
+ observe: (doc, onChange) => {
869
+ const shared = map(doc);
870
+ const handler = (event) => {
871
+ if (event.keysChanged.has("bytes")) onChange(event.transaction.origin);
872
+ };
873
+ shared.observe(handler);
874
+ return () => shared.unobserve(handler);
875
+ }
876
+ };
877
+ }
878
+
780
879
  // src/collab/ordering.ts
781
880
  function classifyVersion(messageVersion, currentVersion) {
782
881
  if (!isNonNegativeSafeInteger(messageVersion) || !isNonNegativeSafeInteger(currentVersion))
@@ -1222,4 +1321,4 @@ function createWebSocketTransport(options) {
1222
1321
  };
1223
1322
  }
1224
1323
 
1225
- export { BROADCAST_THROTTLE_MS, BoundedMap, COLLABORATION_ROLES, COLLAB_LEAVE_MESSAGE, CONNECTION_TIMEOUT_MS, CURSOR_PALETTE, DEFAULT_COLOR, DEPARTURE_CHANNEL, Emitter, INITIAL_SYNC_GRACE_MS, IdempotencyCache, LEGACY_PPTX_DEPARTURE_CHANNEL, LEGACY_PPTX_LEAVE_MESSAGE, LOCAL_ORIGIN, MAX_LABEL_CHARS, MAX_UPDATE_BYTES, MESSAGE_AWARENESS, MESSAGE_QUERY_AWARENESS, MESSAGE_SYNC, PRESENCE_FIELD, PRESENCE_HEARTBEAT_MS, STALE_PRESENCE_MS, SequenceTracker, adaptYjsProvider, applyUpdateSafe, asSelectionIds, assignUserColor, bindDocument, borrowAwareness, buildRoster, canWrite, clampCoordinate, classifyVersion, clearLocalAwareness, createAssetSync, createClientId, createCollabSession, createDepartureChannel, createIdGenerator, createMemoryHub, createPresencePublisher, createSyncGate, createTransportProvider, createWebSocketTransport, deriveCanvasPresence, derivePresence, encodeDiff, encodeSnapshot, encodeStateVector2 as encodeStateVector, formatCursorLabel, freezeDeep, fromBase64, getUserInitials, isMixedContentBlocked, isNonNegativeSafeInteger, isPresenceFresh, isValidId, isValidRoomId, mergeUpdates2 as mergeUpdates, observeExternalSession, presenceToCursors, registerTeardown, removeAwarenessStatesLocally, restoreSnapshot, roomUrl, sanitizeAvatarUrl, sanitizeCanvasPayload, sanitizeColor, sanitizeIdentity, sanitizeIndex, sanitizeRole, sanitizeUserName, shouldAutoFollowBroadcaster, shouldRoomReplaceLoad, stripHtmlTags, toBase64, transportProvider, validateDisplayName, validateRoomId, validateUpdate };
1324
+ export { BROADCAST_THROTTLE_MS, BoundedMap, COLLABORATION_ROLES, COLLAB_LEAVE_MESSAGE, CONNECTION_TIMEOUT_MS, CURSOR_PALETTE, DEFAULT_COLOR, DEFAULT_MAX_PACKAGE_BYTES, DEPARTURE_CHANNEL, Emitter, INITIAL_SYNC_GRACE_MS, IdempotencyCache, LEGACY_PPTX_DEPARTURE_CHANNEL, LEGACY_PPTX_LEAVE_MESSAGE, LOCAL_ORIGIN, MAX_LABEL_CHARS, MAX_UPDATE_BYTES, MESSAGE_AWARENESS, MESSAGE_QUERY_AWARENESS, MESSAGE_SYNC, PRESENCE_FIELD, PRESENCE_HEARTBEAT_MS, STALE_PRESENCE_MS, SequenceTracker, adaptYjsProvider, applyUpdateSafe, asSelectionIds, assignUserColor, bindDocument, borrowAwareness, buildRoster, canBroadcast, canWrite, clampCoordinate, classifyVersion, clearLocalAwareness, createAssetSync, createBroadcastTransport, createClientId, createCollabSession, createDepartureChannel, createIdGenerator, createMemoryHub, createPresencePublisher, createSyncGate, createTransportProvider, createWebSocketTransport, deriveCanvasPresence, derivePresence, encodeDiff, encodeSnapshot, encodeStateVector2 as encodeStateVector, formatCursorLabel, freezeDeep, fromBase64, getUserInitials, isMixedContentBlocked, isNonNegativeSafeInteger, isPresenceFresh, isValidId, isValidRoomId, mergeUpdates2 as mergeUpdates, observeExternalSession, packageAdapter, presenceToCursors, registerTeardown, removeAwarenessStatesLocally, restoreSnapshot, roomUrl, sanitizeAvatarUrl, sanitizeCanvasPayload, sanitizeColor, sanitizeIdentity, sanitizeIndex, sanitizeRole, sanitizeUserName, shouldAutoFollowBroadcaster, shouldRoomReplaceLoad, stripHtmlTags, toBase64, transportProvider, validateDisplayName, validateRoomId, validateUpdate };
@@ -0,0 +1,15 @@
1
+ import type { DocumentAdapter } from './binding.js';
2
+ export interface PackageAdapterOptions {
3
+ /** Y.Map name. Default `package`. */
4
+ name?: string;
5
+ /** Refuse to publish or adopt packages larger than this. Default 32 MiB. */
6
+ maxBytes?: number;
7
+ }
8
+ export declare const DEFAULT_MAX_PACKAGE_BYTES: number;
9
+ /** One shared package: its bytes and a revision counter peers can display or compare. */
10
+ export interface SharedPackage {
11
+ bytes: Uint8Array;
12
+ revision: number;
13
+ }
14
+ export declare function packageAdapter(options?: PackageAdapterOptions): DocumentAdapter<SharedPackage>;
15
+ //# sourceMappingURL=package-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-adapter.d.ts","sourceRoot":"","sources":["../../src/collab/package-adapter.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,WAAW,qBAAqB;IACrC,qCAAqC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,yBAAyB,QAAmB,CAAC;AAE1D,yFAAyF;AACzF,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,UAAU,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,cAAc,CAC7B,OAAO,GAAE,qBAA0B,GACjC,eAAe,CAAC,aAAa,CAAC,CAwChC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ooxml-core",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "description": "Shared OOXML logic for the Word, PowerPoint and Excel viewers: everything except the UI",
5
5
  "keywords": [
6
6
  "charts",