ooxml-core 0.13.0 → 0.14.1

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;AAiBD,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,KAAK,GAAE,MAAmB,GAAG,OAAO,CAEhE;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,yBAAyB,GAAG,SAAS,CAmDtF"}
@@ -485,6 +485,63 @@ function bindDocument(session, adapter, options) {
485
485
  }
486
486
  };
487
487
  }
488
+
489
+ // src/collab/broadcast-transport.ts
490
+ var isBytes = (value) => ArrayBuffer.isView(value) && Object.prototype.toString.call(value) === "[object Uint8Array]";
491
+ var isEnvelope = (value) => {
492
+ const envelope = value;
493
+ return !!envelope && typeof envelope.from === "string" && (envelope.kind === "hello" || envelope.kind === "data" && isBytes(envelope.data));
494
+ };
495
+ function canBroadcast(scope = globalThis) {
496
+ return typeof scope.BroadcastChannel === "function";
497
+ }
498
+ function createBroadcastTransport(options) {
499
+ const roomId = validateRoomId(options.roomId);
500
+ const Channel = options.BroadcastChannel ?? globalThis.BroadcastChannel;
501
+ const self = Math.random().toString(36).slice(2) + Date.now().toString(36);
502
+ let channel = null;
503
+ let handlers = null;
504
+ const close = () => {
505
+ if (!channel) return;
506
+ channel.onmessage = null;
507
+ channel.close();
508
+ channel = null;
509
+ };
510
+ return {
511
+ connect(next) {
512
+ close();
513
+ handlers = next;
514
+ if (!Channel) {
515
+ next.error(new Error("BroadcastChannel is not available in this environment."));
516
+ next.close("unavailable");
517
+ return;
518
+ }
519
+ const open = new Channel(`${options.prefix ?? "ooxml-collab:"}${roomId}`);
520
+ channel = open;
521
+ open.onmessage = ({ data }) => {
522
+ if (channel !== open || !isEnvelope(data) || data.from === self) return;
523
+ if (data.kind === "hello") handlers?.peer?.();
524
+ else handlers?.message(new Uint8Array(data.data));
525
+ };
526
+ next.open();
527
+ open.postMessage({ kind: "hello", from: self });
528
+ },
529
+ send(data) {
530
+ try {
531
+ channel?.postMessage({ kind: "data", from: self, data });
532
+ } catch (cause) {
533
+ handlers?.error(cause instanceof Error ? cause : new Error(String(cause)));
534
+ }
535
+ },
536
+ disconnect() {
537
+ const was = handlers;
538
+ const open = channel !== null;
539
+ close();
540
+ handlers = null;
541
+ if (open) was?.close("disconnected");
542
+ }
543
+ };
544
+ }
488
545
  var MAX_UPDATE_BYTES = 32 * 1024 * 1024;
489
546
  function encodeSnapshot(doc) {
490
547
  return Y__namespace.encodeStateAsUpdate(doc);
@@ -801,6 +858,49 @@ function createMemoryHub(options = {}) {
801
858
  };
802
859
  }
803
860
 
861
+ // src/collab/package-adapter.ts
862
+ var DEFAULT_MAX_PACKAGE_BYTES = 32 * 1024 * 1024;
863
+ function packageAdapter(options = {}) {
864
+ const name = options.name ?? "package";
865
+ const maxBytes = options.maxBytes ?? DEFAULT_MAX_PACKAGE_BYTES;
866
+ const map = (doc) => doc.getMap(name);
867
+ const check = (bytes) => {
868
+ if (!(bytes instanceof Uint8Array)) throw new Error("The shared package is not binary data.");
869
+ if (bytes.byteLength > maxBytes)
870
+ throw new Error(`The shared package exceeds ${Math.round(maxBytes / 1024 / 1024)} MiB.`);
871
+ return bytes;
872
+ };
873
+ return {
874
+ isEmpty: (doc) => !(map(doc).get("bytes") instanceof Uint8Array),
875
+ read: (doc) => {
876
+ const shared = map(doc);
877
+ const revision = shared.get("revision");
878
+ return {
879
+ bytes: check(shared.get("bytes")).slice(),
880
+ revision: typeof revision === "number" && Number.isSafeInteger(revision) ? revision : 0
881
+ };
882
+ },
883
+ write: (doc, model, origin) => {
884
+ const bytes = check(model.bytes);
885
+ doc.transact(() => {
886
+ const shared = map(doc);
887
+ const current = shared.get("revision");
888
+ const revision = Math.max(model.revision, typeof current === "number" ? current : 0) + 1;
889
+ shared.set("bytes", bytes.slice());
890
+ shared.set("revision", revision);
891
+ }, origin);
892
+ },
893
+ observe: (doc, onChange) => {
894
+ const shared = map(doc);
895
+ const handler = (event) => {
896
+ if (event.keysChanged.has("bytes")) onChange(event.transaction.origin);
897
+ };
898
+ shared.observe(handler);
899
+ return () => shared.unobserve(handler);
900
+ }
901
+ };
902
+ }
903
+
804
904
  // src/collab/ordering.ts
805
905
  function classifyVersion(messageVersion, currentVersion) {
806
906
  if (!isNonNegativeSafeInteger(messageVersion) || !isNonNegativeSafeInteger(currentVersion))
@@ -1253,6 +1353,7 @@ exports.COLLAB_LEAVE_MESSAGE = COLLAB_LEAVE_MESSAGE;
1253
1353
  exports.CONNECTION_TIMEOUT_MS = CONNECTION_TIMEOUT_MS;
1254
1354
  exports.CURSOR_PALETTE = CURSOR_PALETTE;
1255
1355
  exports.DEFAULT_COLOR = DEFAULT_COLOR;
1356
+ exports.DEFAULT_MAX_PACKAGE_BYTES = DEFAULT_MAX_PACKAGE_BYTES;
1256
1357
  exports.DEPARTURE_CHANNEL = DEPARTURE_CHANNEL;
1257
1358
  exports.Emitter = Emitter;
1258
1359
  exports.INITIAL_SYNC_GRACE_MS = INITIAL_SYNC_GRACE_MS;
@@ -1276,11 +1377,13 @@ exports.assignUserColor = assignUserColor;
1276
1377
  exports.bindDocument = bindDocument;
1277
1378
  exports.borrowAwareness = borrowAwareness;
1278
1379
  exports.buildRoster = buildRoster;
1380
+ exports.canBroadcast = canBroadcast;
1279
1381
  exports.canWrite = canWrite;
1280
1382
  exports.clampCoordinate = clampCoordinate;
1281
1383
  exports.classifyVersion = classifyVersion;
1282
1384
  exports.clearLocalAwareness = clearLocalAwareness;
1283
1385
  exports.createAssetSync = createAssetSync;
1386
+ exports.createBroadcastTransport = createBroadcastTransport;
1284
1387
  exports.createClientId = createClientId;
1285
1388
  exports.createCollabSession = createCollabSession;
1286
1389
  exports.createDepartureChannel = createDepartureChannel;
@@ -1306,6 +1409,7 @@ exports.isValidId = isValidId;
1306
1409
  exports.isValidRoomId = isValidRoomId;
1307
1410
  exports.mergeUpdates = mergeUpdates2;
1308
1411
  exports.observeExternalSession = observeExternalSession;
1412
+ exports.packageAdapter = packageAdapter;
1309
1413
  exports.presenceToCursors = presenceToCursors;
1310
1414
  exports.registerTeardown = registerTeardown;
1311
1415
  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,63 @@ function bindDocument(session, adapter, options) {
461
461
  }
462
462
  };
463
463
  }
464
+
465
+ // src/collab/broadcast-transport.ts
466
+ var isBytes = (value) => ArrayBuffer.isView(value) && Object.prototype.toString.call(value) === "[object Uint8Array]";
467
+ var isEnvelope = (value) => {
468
+ const envelope = value;
469
+ return !!envelope && typeof envelope.from === "string" && (envelope.kind === "hello" || envelope.kind === "data" && isBytes(envelope.data));
470
+ };
471
+ function canBroadcast(scope = globalThis) {
472
+ return typeof scope.BroadcastChannel === "function";
473
+ }
474
+ function createBroadcastTransport(options) {
475
+ const roomId = validateRoomId(options.roomId);
476
+ const Channel = options.BroadcastChannel ?? globalThis.BroadcastChannel;
477
+ const self = Math.random().toString(36).slice(2) + Date.now().toString(36);
478
+ let channel = null;
479
+ let handlers = null;
480
+ const close = () => {
481
+ if (!channel) return;
482
+ channel.onmessage = null;
483
+ channel.close();
484
+ channel = null;
485
+ };
486
+ return {
487
+ connect(next) {
488
+ close();
489
+ handlers = next;
490
+ if (!Channel) {
491
+ next.error(new Error("BroadcastChannel is not available in this environment."));
492
+ next.close("unavailable");
493
+ return;
494
+ }
495
+ const open = new Channel(`${options.prefix ?? "ooxml-collab:"}${roomId}`);
496
+ channel = open;
497
+ open.onmessage = ({ data }) => {
498
+ if (channel !== open || !isEnvelope(data) || data.from === self) return;
499
+ if (data.kind === "hello") handlers?.peer?.();
500
+ else handlers?.message(new Uint8Array(data.data));
501
+ };
502
+ next.open();
503
+ open.postMessage({ kind: "hello", from: self });
504
+ },
505
+ send(data) {
506
+ try {
507
+ channel?.postMessage({ kind: "data", from: self, data });
508
+ } catch (cause) {
509
+ handlers?.error(cause instanceof Error ? cause : new Error(String(cause)));
510
+ }
511
+ },
512
+ disconnect() {
513
+ const was = handlers;
514
+ const open = channel !== null;
515
+ close();
516
+ handlers = null;
517
+ if (open) was?.close("disconnected");
518
+ }
519
+ };
520
+ }
464
521
  var MAX_UPDATE_BYTES = 32 * 1024 * 1024;
465
522
  function encodeSnapshot(doc) {
466
523
  return Y.encodeStateAsUpdate(doc);
@@ -777,6 +834,49 @@ function createMemoryHub(options = {}) {
777
834
  };
778
835
  }
779
836
 
837
+ // src/collab/package-adapter.ts
838
+ var DEFAULT_MAX_PACKAGE_BYTES = 32 * 1024 * 1024;
839
+ function packageAdapter(options = {}) {
840
+ const name = options.name ?? "package";
841
+ const maxBytes = options.maxBytes ?? DEFAULT_MAX_PACKAGE_BYTES;
842
+ const map = (doc) => doc.getMap(name);
843
+ const check = (bytes) => {
844
+ if (!(bytes instanceof Uint8Array)) throw new Error("The shared package is not binary data.");
845
+ if (bytes.byteLength > maxBytes)
846
+ throw new Error(`The shared package exceeds ${Math.round(maxBytes / 1024 / 1024)} MiB.`);
847
+ return bytes;
848
+ };
849
+ return {
850
+ isEmpty: (doc) => !(map(doc).get("bytes") instanceof Uint8Array),
851
+ read: (doc) => {
852
+ const shared = map(doc);
853
+ const revision = shared.get("revision");
854
+ return {
855
+ bytes: check(shared.get("bytes")).slice(),
856
+ revision: typeof revision === "number" && Number.isSafeInteger(revision) ? revision : 0
857
+ };
858
+ },
859
+ write: (doc, model, origin) => {
860
+ const bytes = check(model.bytes);
861
+ doc.transact(() => {
862
+ const shared = map(doc);
863
+ const current = shared.get("revision");
864
+ const revision = Math.max(model.revision, typeof current === "number" ? current : 0) + 1;
865
+ shared.set("bytes", bytes.slice());
866
+ shared.set("revision", revision);
867
+ }, origin);
868
+ },
869
+ observe: (doc, onChange) => {
870
+ const shared = map(doc);
871
+ const handler = (event) => {
872
+ if (event.keysChanged.has("bytes")) onChange(event.transaction.origin);
873
+ };
874
+ shared.observe(handler);
875
+ return () => shared.unobserve(handler);
876
+ }
877
+ };
878
+ }
879
+
780
880
  // src/collab/ordering.ts
781
881
  function classifyVersion(messageVersion, currentVersion) {
782
882
  if (!isNonNegativeSafeInteger(messageVersion) || !isNonNegativeSafeInteger(currentVersion))
@@ -1222,4 +1322,4 @@ function createWebSocketTransport(options) {
1222
1322
  };
1223
1323
  }
1224
1324
 
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 };
1325
+ 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.1",
4
4
  "description": "Shared OOXML logic for the Word, PowerPoint and Excel viewers: everything except the UI",
5
5
  "keywords": [
6
6
  "charts",