y-mxgraph 0.4.1 → 0.5.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.
@@ -83,17 +83,6 @@ function createIframeBridgeProvider(ydoc, awareness$1) {
83
83
  let currentMxLike = null;
84
84
  const onYdocUpdate = (update) => {
85
85
  if (applyingParentUpdate) return;
86
- if (currentMxLike) {
87
- if (currentMxLike.indexOfNextAdd < currentMxLike.history.length) {
88
- currentMxLike.history.splice(
89
- currentMxLike.indexOfNextAdd,
90
- currentMxLike.history.length - currentMxLike.indexOfNextAdd
91
- );
92
- }
93
- currentMxLike.history.push({});
94
- currentMxLike.indexOfNextAdd = currentMxLike.history.length;
95
- currentMxLike.fireEvent(createMxEventObject("add", { edit: { changes: [] } }));
96
- }
97
86
  window.parent.postMessage(
98
87
  { type: "ydoc-update", payload: Array.from(update) },
99
88
  "*"
@@ -134,15 +123,34 @@ function createIframeBridgeProvider(ydoc, awareness$1) {
134
123
  applyingParentUpdate = true;
135
124
  awareness.applyAwarenessUpdate(awareness$1, remapped, null);
136
125
  applyingParentUpdate = false;
126
+ } else if (type === "add" && currentMxLike) {
127
+ applyingParentUpdate = true;
128
+ if (currentMxLike.indexOfNextAdd < currentMxLike.history.length) {
129
+ currentMxLike.history.splice(
130
+ currentMxLike.indexOfNextAdd,
131
+ currentMxLike.history.length - currentMxLike.indexOfNextAdd
132
+ );
133
+ }
134
+ currentMxLike.history.push({});
135
+ currentMxLike.indexOfNextAdd = currentMxLike.history.length;
136
+ currentMxLike.fireEvent(
137
+ createMxEventObject("add", { edit: { changes: [] } })
138
+ );
139
+ applyingParentUpdate = false;
137
140
  } else if (type === "undo" && currentMxLike) {
138
141
  applyingParentUpdate = true;
139
142
  if (currentMxLike.indexOfNextAdd > 0) currentMxLike.indexOfNextAdd--;
140
- currentMxLike.fireEvent(createMxEventObject("undo", { edit: { changes: [] } }));
143
+ currentMxLike.fireEvent(
144
+ createMxEventObject("undo", { edit: { changes: [] } })
145
+ );
141
146
  applyingParentUpdate = false;
142
147
  } else if (type === "redo" && currentMxLike) {
143
148
  applyingParentUpdate = true;
144
- if (currentMxLike.indexOfNextAdd < currentMxLike.history.length) currentMxLike.indexOfNextAdd++;
145
- currentMxLike.fireEvent(createMxEventObject("redo", { edit: { changes: [] } }));
149
+ if (currentMxLike.indexOfNextAdd < currentMxLike.history.length)
150
+ currentMxLike.indexOfNextAdd++;
151
+ currentMxLike.fireEvent(
152
+ createMxEventObject("redo", { edit: { changes: [] } })
153
+ );
146
154
  applyingParentUpdate = false;
147
155
  } else if (type === "clear" && currentMxLike) {
148
156
  applyingParentUpdate = true;
@@ -190,7 +198,10 @@ function createIframeBridgeProvider(ydoc, awareness$1) {
190
198
  try {
191
199
  listener(this, evt);
192
200
  } catch (e) {
193
- console.warn("[iframe-bridge] undoManager event listener error:", e);
201
+ console.warn(
202
+ "[iframe-bridge] undoManager event listener error:",
203
+ e
204
+ );
194
205
  }
195
206
  }
196
207
  }
@@ -1 +1 @@
1
- {"version":3,"file":"provider.cjs.js","sources":["../../../iframe-bridge/src/provider.ts"],"sourcesContent":["import * as Y from \"yjs\";\nimport {\n Awareness,\n applyAwarenessUpdate,\n encodeAwarenessUpdate,\n} from \"y-protocols/awareness\";\n\ntype ListenerFn = (sender: unknown, evt?: unknown) => void;\n\nfunction createMxEventObject(name: string, props?: Record<string, unknown>) {\n const _props = props || {};\n return {\n name,\n getName: () => name,\n getProperty: (k: string) => _props[k],\n };\n}\n\ntype MxLike = Record<string, unknown> & {\n eventListeners: Array<string | ListenerFn>;\n history: unknown[];\n indexOfNextAdd: number;\n addListener(name: string, fn: ListenerFn): void;\n fireEvent(evt: unknown): void;\n canUndo(): boolean;\n canRedo(): boolean;\n undo(): void;\n redo(): void;\n undoableEditHappened(_edit: unknown): void;\n};\n\nexport interface DrawioEditor {\n undoManager?: {\n eventListeners?: unknown[];\n [key: string]: unknown;\n };\n undoListener?: (...args: unknown[]) => void;\n}\n\nexport interface DrawioFile {\n getUi(): { editor: DrawioEditor };\n}\n\nexport interface IframeBridgeProvider {\n serverClientId: number | null;\n takeoverUndoManager: (file: DrawioFile) => () => void;\n destroy: () => void;\n}\n\nfunction readVarUint(data: Uint8Array, pos: number): [number, number] {\n let result = 0;\n let shift = 0;\n let byte: number;\n do {\n byte = data[pos++];\n result |= (byte & 0x7f) << shift;\n shift += 7;\n } while (byte >= 0x80);\n return [result >>> 0, pos];\n}\n\nfunction writeVarUint(value: number): number[] {\n const bytes: number[] = [];\n while (value > 0x7f) {\n bytes.push((value & 0x7f) | 0x80);\n value >>>= 7;\n }\n bytes.push(value);\n return bytes;\n}\n\nfunction readVarString(data: Uint8Array, pos: number): [string, number] {\n const [len, pos2] = readVarUint(data, pos);\n const str = new TextDecoder().decode(data.subarray(pos2, pos2 + len));\n return [str, pos2 + len];\n}\n\nfunction writeVarString(str: string): number[] {\n const encoded = new TextEncoder().encode(str);\n return [...writeVarUint(encoded.length), ...encoded];\n}\n\nfunction remapClientIdInUpdate(\n update: Uint8Array,\n fromId: number,\n toId: number,\n): Uint8Array {\n const result: number[] = [];\n let pos = 0;\n\n const [count, pos2] = readVarUint(update, pos);\n pos = pos2;\n result.push(...writeVarUint(count));\n\n for (let i = 0; i < count; i++) {\n const [clientID, pos3] = readVarUint(update, pos);\n pos = pos3;\n const [clock, pos4] = readVarUint(update, pos);\n pos = pos4;\n const [state, pos5] = readVarString(update, pos);\n pos = pos5;\n\n const mappedId = clientID === fromId ? toId : clientID;\n result.push(...writeVarUint(mappedId));\n result.push(...writeVarUint(clock));\n result.push(...writeVarString(state));\n }\n\n return new Uint8Array(result);\n}\n\nexport function createIframeBridgeProvider(\n ydoc: Y.Doc,\n awareness: Awareness,\n): IframeBridgeProvider {\n let applyingParentUpdate = false;\n let serverClientId: number | null = null;\n let currentCleanup: (() => void) | null = null;\n let currentMxLike: MxLike | null = null;\n\n const onYdocUpdate = (update: Uint8Array) => {\n if (applyingParentUpdate) return;\n // 本地编辑,添加 history 条目\n if (currentMxLike) {\n if (currentMxLike.indexOfNextAdd < currentMxLike.history.length) {\n currentMxLike.history.splice(\n currentMxLike.indexOfNextAdd,\n currentMxLike.history.length - currentMxLike.indexOfNextAdd,\n );\n }\n currentMxLike.history.push({});\n currentMxLike.indexOfNextAdd = currentMxLike.history.length;\n currentMxLike.fireEvent(createMxEventObject(\"add\", { edit: { changes: [] } }));\n }\n window.parent.postMessage(\n { type: \"ydoc-update\", payload: Array.from(update) },\n \"*\",\n );\n };\n\n const onAwarenessUpdate = ({\n added,\n updated,\n removed,\n }: {\n added: number[];\n updated: number[];\n removed: number[];\n }) => {\n if (applyingParentUpdate) return;\n const changes = [...added, ...updated, ...removed];\n if (changes.length === 0) return;\n\n const update = encodeAwarenessUpdate(awareness, changes);\n const remapped =\n serverClientId != null\n ? remapClientIdInUpdate(update, awareness.clientID, serverClientId)\n : update;\n\n window.parent.postMessage(\n { type: \"awareness-update\", payload: Array.from(remapped) },\n \"*\",\n );\n };\n\n const onMessage = (event: MessageEvent) => {\n if (event.source !== window.parent) return;\n const { type, payload, serverClientId: receivedServerId } = event.data;\n\n if (type === \"pong\" && receivedServerId != null) {\n serverClientId = receivedServerId;\n return;\n }\n\n if (type === \"ydoc-sync\" || type === \"ydoc-update\") {\n applyingParentUpdate = true;\n Y.applyUpdate(ydoc, new Uint8Array(payload));\n applyingParentUpdate = false;\n } else if (type === \"awareness-sync\" || type === \"awareness-update\") {\n if (receivedServerId != null) {\n serverClientId = receivedServerId;\n }\n\n const raw = new Uint8Array(payload);\n const remapped =\n serverClientId != null\n ? remapClientIdInUpdate(raw, serverClientId, awareness.clientID)\n : raw;\n\n applyingParentUpdate = true;\n applyAwarenessUpdate(awareness, remapped, null);\n applyingParentUpdate = false;\n } else if (type === \"undo\" && currentMxLike) {\n applyingParentUpdate = true;\n if (currentMxLike.indexOfNextAdd > 0) currentMxLike.indexOfNextAdd--;\n currentMxLike.fireEvent(createMxEventObject(\"undo\", { edit: { changes: [] } }));\n applyingParentUpdate = false;\n } else if (type === \"redo\" && currentMxLike) {\n applyingParentUpdate = true;\n if (currentMxLike.indexOfNextAdd < currentMxLike.history.length) currentMxLike.indexOfNextAdd++;\n currentMxLike.fireEvent(createMxEventObject(\"redo\", { edit: { changes: [] } }));\n applyingParentUpdate = false;\n } else if (type === \"clear\" && currentMxLike) {\n applyingParentUpdate = true;\n currentMxLike.history = [];\n currentMxLike.indexOfNextAdd = 0;\n currentMxLike.fireEvent(createMxEventObject(\"clear\"));\n applyingParentUpdate = false;\n }\n };\n\n ydoc.on(\"update\", onYdocUpdate);\n awareness.on(\"update\", onAwarenessUpdate);\n window.addEventListener(\"message\", onMessage);\n\n window.parent.postMessage({ type: \"init\" }, \"*\");\n\n return {\n get serverClientId() {\n return serverClientId;\n },\n takeoverUndoManager(file: DrawioFile) {\n if (currentCleanup) {\n currentCleanup();\n }\n\n const editor = file.getUi().editor;\n const originUndoManager = editor.undoManager;\n\n const pairs: Array<[string, ListenerFn]> = [];\n const raw = Array.isArray(originUndoManager?.eventListeners)\n ? (originUndoManager.eventListeners as unknown[])\n : [];\n for (let i = 0; i + 1 < raw.length; i += 2) {\n const key = String(raw[i]);\n const fn = raw[i + 1] as ListenerFn;\n pairs.push([key, fn]);\n }\n\n const mxLike: MxLike = {\n eventListeners: [] as Array<string | ListenerFn>,\n history: [] as unknown[],\n indexOfNextAdd: 0,\n\n addListener(name: string, fn: ListenerFn) {\n this.eventListeners.push(name, fn);\n },\n\n fireEvent(evt: unknown) {\n const eventName: string =\n (evt as { name?: string } | undefined)?.name ||\n ((evt as { getName?: () => string } | undefined)?.getName?.() ?? \"\");\n for (let i = 0; i + 1 < this.eventListeners.length; i += 2) {\n const key = this.eventListeners[i];\n const listener = this.eventListeners[i + 1] as ListenerFn;\n if (key === eventName) {\n try {\n listener(this, evt);\n } catch (e) {\n console.warn(\"[iframe-bridge] undoManager event listener error:\", e);\n }\n }\n }\n },\n\n canUndo(): boolean {\n return this.indexOfNextAdd > 0;\n },\n\n canRedo(): boolean {\n return this.indexOfNextAdd < this.history.length;\n },\n\n undo() {\n if (!applyingParentUpdate) {\n window.parent.postMessage({ type: \"undo\" }, \"*\");\n }\n },\n\n redo() {\n if (!applyingParentUpdate) {\n window.parent.postMessage({ type: \"redo\" }, \"*\");\n }\n },\n\n undoableEditHappened() {\n // no-op\n },\n };\n\n pairs.forEach(([key, fn]) => {\n const k = key.toLowerCase();\n if (k === \"add\" || k === \"clear\" || k === \"undo\" || k === \"redo\") {\n mxLike.addListener(k, fn);\n }\n });\n\n currentMxLike = mxLike;\n editor.undoManager = mxLike as any;\n editor.undoListener = function () {};\n\n const cleanup = () => {\n editor.undoManager = originUndoManager;\n editor.undoListener = originUndoManager?.undoListener as ((...args: unknown[]) => void) | undefined;\n currentMxLike = null;\n };\n\n currentCleanup = cleanup;\n return cleanup;\n },\n destroy: () => {\n ydoc.off(\"update\", onYdocUpdate);\n awareness.off(\"update\", onAwarenessUpdate);\n window.removeEventListener(\"message\", onMessage);\n if (currentCleanup) {\n currentCleanup();\n }\n },\n };\n}\n"],"names":["awareness","encodeAwarenessUpdate","Y","applyAwarenessUpdate"],"mappings":";;;;;;;;;;;;;;;;;;;;;AASA,SAAS,oBAAoB,MAAc,OAAiC;AAC1E,QAAM,SAAS,SAAS,CAAA;AACxB,SAAO;AAAA,IACL;AAAA,IACA,SAAS,MAAM;AAAA,IACf,aAAa,CAAC,MAAc,OAAO,CAAC;AAAA,EAAA;AAExC;AAiCA,SAAS,YAAY,MAAkB,KAA+B;AACpE,MAAI,SAAS;AACb,MAAI,QAAQ;AACZ,MAAI;AACJ,KAAG;AACD,WAAO,KAAK,KAAK;AACjB,eAAW,OAAO,QAAS;AAC3B,aAAS;AAAA,EACX,SAAS,QAAQ;AACjB,SAAO,CAAC,WAAW,GAAG,GAAG;AAC3B;AAEA,SAAS,aAAa,OAAyB;AAC7C,QAAM,QAAkB,CAAA;AACxB,SAAO,QAAQ,KAAM;AACnB,UAAM,KAAM,QAAQ,MAAQ,GAAI;AAChC,eAAW;AAAA,EACb;AACA,QAAM,KAAK,KAAK;AAChB,SAAO;AACT;AAEA,SAAS,cAAc,MAAkB,KAA+B;AACtE,QAAM,CAAC,KAAK,IAAI,IAAI,YAAY,MAAM,GAAG;AACzC,QAAM,MAAM,IAAI,YAAA,EAAc,OAAO,KAAK,SAAS,MAAM,OAAO,GAAG,CAAC;AACpE,SAAO,CAAC,KAAK,OAAO,GAAG;AACzB;AAEA,SAAS,eAAe,KAAuB;AAC7C,QAAM,UAAU,IAAI,cAAc,OAAO,GAAG;AAC5C,SAAO,CAAC,GAAG,aAAa,QAAQ,MAAM,GAAG,GAAG,OAAO;AACrD;AAEA,SAAS,sBACP,QACA,QACA,MACY;AACZ,QAAM,SAAmB,CAAA;AACzB,MAAI,MAAM;AAEV,QAAM,CAAC,OAAO,IAAI,IAAI,YAAY,QAAQ,GAAG;AAC7C,QAAM;AACN,SAAO,KAAK,GAAG,aAAa,KAAK,CAAC;AAElC,WAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,UAAM,CAAC,UAAU,IAAI,IAAI,YAAY,QAAQ,GAAG;AAChD,UAAM;AACN,UAAM,CAAC,OAAO,IAAI,IAAI,YAAY,QAAQ,GAAG;AAC7C,UAAM;AACN,UAAM,CAAC,OAAO,IAAI,IAAI,cAAc,QAAQ,GAAG;AAC/C,UAAM;AAEN,UAAM,WAAW,aAAa,SAAS,OAAO;AAC9C,WAAO,KAAK,GAAG,aAAa,QAAQ,CAAC;AACrC,WAAO,KAAK,GAAG,aAAa,KAAK,CAAC;AAClC,WAAO,KAAK,GAAG,eAAe,KAAK,CAAC;AAAA,EACtC;AAEA,SAAO,IAAI,WAAW,MAAM;AAC9B;AAEO,SAAS,2BACd,MACAA,aACsB;AACtB,MAAI,uBAAuB;AAC3B,MAAI,iBAAgC;AACpC,MAAI,iBAAsC;AAC1C,MAAI,gBAA+B;AAEnC,QAAM,eAAe,CAAC,WAAuB;AAC3C,QAAI,qBAAsB;AAE1B,QAAI,eAAe;AACjB,UAAI,cAAc,iBAAiB,cAAc,QAAQ,QAAQ;AAC/D,sBAAc,QAAQ;AAAA,UACpB,cAAc;AAAA,UACd,cAAc,QAAQ,SAAS,cAAc;AAAA,QAAA;AAAA,MAEjD;AACA,oBAAc,QAAQ,KAAK,EAAE;AAC7B,oBAAc,iBAAiB,cAAc,QAAQ;AACrD,oBAAc,UAAU,oBAAoB,OAAO,EAAE,MAAM,EAAE,SAAS,GAAC,EAAE,CAAG,CAAC;AAAA,IAC/E;AACA,WAAO,OAAO;AAAA,MACZ,EAAE,MAAM,eAAe,SAAS,MAAM,KAAK,MAAM,EAAA;AAAA,MACjD;AAAA,IAAA;AAAA,EAEJ;AAEA,QAAM,oBAAoB,CAAC;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,EAAA,MAKI;AACJ,QAAI,qBAAsB;AAC1B,UAAM,UAAU,CAAC,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO;AACjD,QAAI,QAAQ,WAAW,EAAG;AAE1B,UAAM,SAASC,UAAAA,sBAAsBD,aAAW,OAAO;AACvD,UAAM,WACJ,kBAAkB,OACd,sBAAsB,QAAQA,YAAU,UAAU,cAAc,IAChE;AAEN,WAAO,OAAO;AAAA,MACZ,EAAE,MAAM,oBAAoB,SAAS,MAAM,KAAK,QAAQ,EAAA;AAAA,MACxD;AAAA,IAAA;AAAA,EAEJ;AAEA,QAAM,YAAY,CAAC,UAAwB;AACzC,QAAI,MAAM,WAAW,OAAO,OAAQ;AACpC,UAAM,EAAE,MAAM,SAAS,gBAAgB,iBAAA,IAAqB,MAAM;AAElE,QAAI,SAAS,UAAU,oBAAoB,MAAM;AAC/C,uBAAiB;AACjB;AAAA,IACF;AAEA,QAAI,SAAS,eAAe,SAAS,eAAe;AAClD,6BAAuB;AACvBE,mBAAE,YAAY,MAAM,IAAI,WAAW,OAAO,CAAC;AAC3C,6BAAuB;AAAA,IACzB,WAAW,SAAS,oBAAoB,SAAS,oBAAoB;AACnE,UAAI,oBAAoB,MAAM;AAC5B,yBAAiB;AAAA,MACnB;AAEA,YAAM,MAAM,IAAI,WAAW,OAAO;AAClC,YAAM,WACJ,kBAAkB,OACd,sBAAsB,KAAK,gBAAgBF,YAAU,QAAQ,IAC7D;AAEN,6BAAuB;AACvBG,qCAAqBH,aAAW,UAAU,IAAI;AAC9C,6BAAuB;AAAA,IACzB,WAAW,SAAS,UAAU,eAAe;AAC3C,6BAAuB;AACvB,UAAI,cAAc,iBAAiB,EAAG,eAAc;AACpD,oBAAc,UAAU,oBAAoB,QAAQ,EAAE,MAAM,EAAE,SAAS,GAAC,EAAE,CAAG,CAAC;AAC9E,6BAAuB;AAAA,IACzB,WAAW,SAAS,UAAU,eAAe;AAC3C,6BAAuB;AACvB,UAAI,cAAc,iBAAiB,cAAc,QAAQ,OAAQ,eAAc;AAC/E,oBAAc,UAAU,oBAAoB,QAAQ,EAAE,MAAM,EAAE,SAAS,GAAC,EAAE,CAAG,CAAC;AAC9E,6BAAuB;AAAA,IACzB,WAAW,SAAS,WAAW,eAAe;AAC5C,6BAAuB;AACvB,oBAAc,UAAU,CAAA;AACxB,oBAAc,iBAAiB;AAC/B,oBAAc,UAAU,oBAAoB,OAAO,CAAC;AACpD,6BAAuB;AAAA,IACzB;AAAA,EACF;AAEA,OAAK,GAAG,UAAU,YAAY;AAC9BA,cAAU,GAAG,UAAU,iBAAiB;AACxC,SAAO,iBAAiB,WAAW,SAAS;AAE5C,SAAO,OAAO,YAAY,EAAE,MAAM,OAAA,GAAU,GAAG;AAE/C,SAAO;AAAA,IACL,IAAI,iBAAiB;AACnB,aAAO;AAAA,IACT;AAAA,IACA,oBAAoB,MAAkB;AACpC,UAAI,gBAAgB;AAClB,uBAAA;AAAA,MACF;AAEA,YAAM,SAAS,KAAK,MAAA,EAAQ;AAC5B,YAAM,oBAAoB,OAAO;AAEjC,YAAM,QAAqC,CAAA;AAC3C,YAAM,MAAM,MAAM,QAAQ,uDAAmB,cAAc,IACtD,kBAAkB,iBACnB,CAAA;AACJ,eAAS,IAAI,GAAG,IAAI,IAAI,IAAI,QAAQ,KAAK,GAAG;AAC1C,cAAM,MAAM,OAAO,IAAI,CAAC,CAAC;AACzB,cAAM,KAAK,IAAI,IAAI,CAAC;AACpB,cAAM,KAAK,CAAC,KAAK,EAAE,CAAC;AAAA,MACtB;AAEA,YAAM,SAAiB;AAAA,QACrB,gBAAgB,CAAA;AAAA,QAChB,SAAS,CAAA;AAAA,QACT,gBAAgB;AAAA,QAEhB,YAAY,MAAc,IAAgB;AACxC,eAAK,eAAe,KAAK,MAAM,EAAE;AAAA,QACnC;AAAA,QAEA,UAAU,KAAc;;AACtB,gBAAM,aACH,2BAAuC,YACtC,gCAAgD,YAAhD,iCAA+D;AACnE,mBAAS,IAAI,GAAG,IAAI,IAAI,KAAK,eAAe,QAAQ,KAAK,GAAG;AAC1D,kBAAM,MAAM,KAAK,eAAe,CAAC;AACjC,kBAAM,WAAW,KAAK,eAAe,IAAI,CAAC;AAC1C,gBAAI,QAAQ,WAAW;AACrB,kBAAI;AACF,yBAAS,MAAM,GAAG;AAAA,cACpB,SAAS,GAAG;AACV,wBAAQ,KAAK,qDAAqD,CAAC;AAAA,cACrE;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QAEA,UAAmB;AACjB,iBAAO,KAAK,iBAAiB;AAAA,QAC/B;AAAA,QAEA,UAAmB;AACjB,iBAAO,KAAK,iBAAiB,KAAK,QAAQ;AAAA,QAC5C;AAAA,QAEA,OAAO;AACL,cAAI,CAAC,sBAAsB;AACzB,mBAAO,OAAO,YAAY,EAAE,MAAM,OAAA,GAAU,GAAG;AAAA,UACjD;AAAA,QACF;AAAA,QAEA,OAAO;AACL,cAAI,CAAC,sBAAsB;AACzB,mBAAO,OAAO,YAAY,EAAE,MAAM,OAAA,GAAU,GAAG;AAAA,UACjD;AAAA,QACF;AAAA,QAEA,uBAAuB;AAAA,QAEvB;AAAA,MAAA;AAGF,YAAM,QAAQ,CAAC,CAAC,KAAK,EAAE,MAAM;AAC3B,cAAM,IAAI,IAAI,YAAA;AACd,YAAI,MAAM,SAAS,MAAM,WAAW,MAAM,UAAU,MAAM,QAAQ;AAChE,iBAAO,YAAY,GAAG,EAAE;AAAA,QAC1B;AAAA,MACF,CAAC;AAED,sBAAgB;AAChB,aAAO,cAAc;AACrB,aAAO,eAAe,WAAY;AAAA,MAAC;AAEnC,YAAM,UAAU,MAAM;AACpB,eAAO,cAAc;AACrB,eAAO,eAAe,uDAAmB;AACzC,wBAAgB;AAAA,MAClB;AAEA,uBAAiB;AACjB,aAAO;AAAA,IACT;AAAA,IACA,SAAS,MAAM;AACb,WAAK,IAAI,UAAU,YAAY;AAC/BA,kBAAU,IAAI,UAAU,iBAAiB;AACzC,aAAO,oBAAoB,WAAW,SAAS;AAC/C,UAAI,gBAAgB;AAClB,uBAAA;AAAA,MACF;AAAA,IACF;AAAA,EAAA;AAEJ;;"}
1
+ {"version":3,"file":"provider.cjs.js","sources":["../../../iframe-bridge/src/provider.ts"],"sourcesContent":["import * as Y from \"yjs\";\nimport {\n Awareness,\n applyAwarenessUpdate,\n encodeAwarenessUpdate,\n} from \"y-protocols/awareness\";\n\ntype ListenerFn = (sender: unknown, evt?: unknown) => void;\n\nfunction createMxEventObject(name: string, props?: Record<string, unknown>) {\n const _props = props || {};\n return {\n name,\n getName: () => name,\n getProperty: (k: string) => _props[k],\n };\n}\n\ntype MxLike = Record<string, unknown> & {\n eventListeners: Array<string | ListenerFn>;\n history: unknown[];\n indexOfNextAdd: number;\n addListener(name: string, fn: ListenerFn): void;\n fireEvent(evt: unknown): void;\n canUndo(): boolean;\n canRedo(): boolean;\n undo(): void;\n redo(): void;\n undoableEditHappened(_edit: unknown): void;\n};\n\nexport interface DrawioEditor {\n undoManager?: {\n eventListeners?: unknown[];\n [key: string]: unknown;\n };\n undoListener?: (...args: unknown[]) => void;\n}\n\nexport interface DrawioFile {\n getUi(): { editor: DrawioEditor };\n}\n\nexport interface IframeBridgeProvider {\n serverClientId: number | null;\n takeoverUndoManager: (file: DrawioFile) => () => void;\n destroy: () => void;\n}\n\nfunction readVarUint(data: Uint8Array, pos: number): [number, number] {\n let result = 0;\n let shift = 0;\n let byte: number;\n do {\n byte = data[pos++];\n result |= (byte & 0x7f) << shift;\n shift += 7;\n } while (byte >= 0x80);\n return [result >>> 0, pos];\n}\n\nfunction writeVarUint(value: number): number[] {\n const bytes: number[] = [];\n while (value > 0x7f) {\n bytes.push((value & 0x7f) | 0x80);\n value >>>= 7;\n }\n bytes.push(value);\n return bytes;\n}\n\nfunction readVarString(data: Uint8Array, pos: number): [string, number] {\n const [len, pos2] = readVarUint(data, pos);\n const str = new TextDecoder().decode(data.subarray(pos2, pos2 + len));\n return [str, pos2 + len];\n}\n\nfunction writeVarString(str: string): number[] {\n const encoded = new TextEncoder().encode(str);\n return [...writeVarUint(encoded.length), ...encoded];\n}\n\nfunction remapClientIdInUpdate(\n update: Uint8Array,\n fromId: number,\n toId: number,\n): Uint8Array {\n const result: number[] = [];\n let pos = 0;\n\n const [count, pos2] = readVarUint(update, pos);\n pos = pos2;\n result.push(...writeVarUint(count));\n\n for (let i = 0; i < count; i++) {\n const [clientID, pos3] = readVarUint(update, pos);\n pos = pos3;\n const [clock, pos4] = readVarUint(update, pos);\n pos = pos4;\n const [state, pos5] = readVarString(update, pos);\n pos = pos5;\n\n const mappedId = clientID === fromId ? toId : clientID;\n result.push(...writeVarUint(mappedId));\n result.push(...writeVarUint(clock));\n result.push(...writeVarString(state));\n }\n\n return new Uint8Array(result);\n}\n\nexport function createIframeBridgeProvider(\n ydoc: Y.Doc,\n awareness: Awareness,\n): IframeBridgeProvider {\n let applyingParentUpdate = false;\n let serverClientId: number | null = null;\n let currentCleanup: (() => void) | null = null;\n let currentMxLike: MxLike | null = null;\n\n const onYdocUpdate = (update: Uint8Array) => {\n if (applyingParentUpdate) return;\n window.parent.postMessage(\n { type: \"ydoc-update\", payload: Array.from(update) },\n \"*\",\n );\n };\n\n const onAwarenessUpdate = ({\n added,\n updated,\n removed,\n }: {\n added: number[];\n updated: number[];\n removed: number[];\n }) => {\n if (applyingParentUpdate) return;\n const changes = [...added, ...updated, ...removed];\n if (changes.length === 0) return;\n\n const update = encodeAwarenessUpdate(awareness, changes);\n const remapped =\n serverClientId != null\n ? remapClientIdInUpdate(update, awareness.clientID, serverClientId)\n : update;\n\n window.parent.postMessage(\n { type: \"awareness-update\", payload: Array.from(remapped) },\n \"*\",\n );\n };\n\n const onMessage = (event: MessageEvent) => {\n if (event.source !== window.parent) return;\n const { type, payload, serverClientId: receivedServerId } = event.data;\n\n if (type === \"pong\" && receivedServerId != null) {\n serverClientId = receivedServerId;\n return;\n }\n\n if (type === \"ydoc-sync\" || type === \"ydoc-update\") {\n applyingParentUpdate = true;\n Y.applyUpdate(ydoc, new Uint8Array(payload));\n applyingParentUpdate = false;\n } else if (type === \"awareness-sync\" || type === \"awareness-update\") {\n if (receivedServerId != null) {\n serverClientId = receivedServerId;\n }\n\n const raw = new Uint8Array(payload);\n const remapped =\n serverClientId != null\n ? remapClientIdInUpdate(raw, serverClientId, awareness.clientID)\n : raw;\n\n applyingParentUpdate = true;\n applyAwarenessUpdate(awareness, remapped, null);\n applyingParentUpdate = false;\n } else if (type === \"add\" && currentMxLike) {\n applyingParentUpdate = true;\n if (currentMxLike.indexOfNextAdd < currentMxLike.history.length) {\n currentMxLike.history.splice(\n currentMxLike.indexOfNextAdd,\n currentMxLike.history.length - currentMxLike.indexOfNextAdd,\n );\n }\n currentMxLike.history.push({});\n currentMxLike.indexOfNextAdd = currentMxLike.history.length;\n currentMxLike.fireEvent(\n createMxEventObject(\"add\", { edit: { changes: [] } }),\n );\n applyingParentUpdate = false;\n } else if (type === \"undo\" && currentMxLike) {\n applyingParentUpdate = true;\n if (currentMxLike.indexOfNextAdd > 0) currentMxLike.indexOfNextAdd--;\n currentMxLike.fireEvent(\n createMxEventObject(\"undo\", { edit: { changes: [] } }),\n );\n applyingParentUpdate = false;\n } else if (type === \"redo\" && currentMxLike) {\n applyingParentUpdate = true;\n if (currentMxLike.indexOfNextAdd < currentMxLike.history.length)\n currentMxLike.indexOfNextAdd++;\n currentMxLike.fireEvent(\n createMxEventObject(\"redo\", { edit: { changes: [] } }),\n );\n applyingParentUpdate = false;\n } else if (type === \"clear\" && currentMxLike) {\n applyingParentUpdate = true;\n currentMxLike.history = [];\n currentMxLike.indexOfNextAdd = 0;\n currentMxLike.fireEvent(createMxEventObject(\"clear\"));\n applyingParentUpdate = false;\n }\n };\n\n ydoc.on(\"update\", onYdocUpdate);\n awareness.on(\"update\", onAwarenessUpdate);\n window.addEventListener(\"message\", onMessage);\n\n window.parent.postMessage({ type: \"init\" }, \"*\");\n\n return {\n get serverClientId() {\n return serverClientId;\n },\n takeoverUndoManager(file: DrawioFile) {\n if (currentCleanup) {\n currentCleanup();\n }\n\n const editor = file.getUi().editor;\n const originUndoManager = editor.undoManager;\n\n const pairs: Array<[string, ListenerFn]> = [];\n const raw = Array.isArray(originUndoManager?.eventListeners)\n ? (originUndoManager.eventListeners as unknown[])\n : [];\n for (let i = 0; i + 1 < raw.length; i += 2) {\n const key = String(raw[i]);\n const fn = raw[i + 1] as ListenerFn;\n pairs.push([key, fn]);\n }\n\n const mxLike: MxLike = {\n eventListeners: [] as Array<string | ListenerFn>,\n history: [] as unknown[],\n indexOfNextAdd: 0,\n\n addListener(name: string, fn: ListenerFn) {\n this.eventListeners.push(name, fn);\n },\n\n fireEvent(evt: unknown) {\n const eventName: string =\n (evt as { name?: string } | undefined)?.name ||\n ((evt as { getName?: () => string } | undefined)?.getName?.() ??\n \"\");\n for (let i = 0; i + 1 < this.eventListeners.length; i += 2) {\n const key = this.eventListeners[i];\n const listener = this.eventListeners[i + 1] as ListenerFn;\n if (key === eventName) {\n try {\n listener(this, evt);\n } catch (e) {\n console.warn(\n \"[iframe-bridge] undoManager event listener error:\",\n e,\n );\n }\n }\n }\n },\n\n canUndo(): boolean {\n return this.indexOfNextAdd > 0;\n },\n\n canRedo(): boolean {\n return this.indexOfNextAdd < this.history.length;\n },\n\n undo() {\n if (!applyingParentUpdate) {\n window.parent.postMessage({ type: \"undo\" }, \"*\");\n }\n },\n\n redo() {\n if (!applyingParentUpdate) {\n window.parent.postMessage({ type: \"redo\" }, \"*\");\n }\n },\n\n undoableEditHappened() {\n // no-op\n },\n };\n\n pairs.forEach(([key, fn]) => {\n const k = key.toLowerCase();\n if (k === \"add\" || k === \"clear\" || k === \"undo\" || k === \"redo\") {\n mxLike.addListener(k, fn);\n }\n });\n\n currentMxLike = mxLike;\n editor.undoManager = mxLike as any;\n editor.undoListener = function () {};\n\n const cleanup = () => {\n editor.undoManager = originUndoManager;\n editor.undoListener = originUndoManager?.undoListener as\n | ((...args: unknown[]) => void)\n | undefined;\n currentMxLike = null;\n };\n\n currentCleanup = cleanup;\n return cleanup;\n },\n destroy: () => {\n ydoc.off(\"update\", onYdocUpdate);\n awareness.off(\"update\", onAwarenessUpdate);\n window.removeEventListener(\"message\", onMessage);\n if (currentCleanup) {\n currentCleanup();\n }\n },\n };\n}\n"],"names":["awareness","encodeAwarenessUpdate","Y","applyAwarenessUpdate"],"mappings":"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"}
@@ -64,17 +64,6 @@ function createIframeBridgeProvider(ydoc, awareness) {
64
64
  let currentMxLike = null;
65
65
  const onYdocUpdate = (update) => {
66
66
  if (applyingParentUpdate) return;
67
- if (currentMxLike) {
68
- if (currentMxLike.indexOfNextAdd < currentMxLike.history.length) {
69
- currentMxLike.history.splice(
70
- currentMxLike.indexOfNextAdd,
71
- currentMxLike.history.length - currentMxLike.indexOfNextAdd
72
- );
73
- }
74
- currentMxLike.history.push({});
75
- currentMxLike.indexOfNextAdd = currentMxLike.history.length;
76
- currentMxLike.fireEvent(createMxEventObject("add", { edit: { changes: [] } }));
77
- }
78
67
  window.parent.postMessage(
79
68
  { type: "ydoc-update", payload: Array.from(update) },
80
69
  "*"
@@ -115,15 +104,34 @@ function createIframeBridgeProvider(ydoc, awareness) {
115
104
  applyingParentUpdate = true;
116
105
  applyAwarenessUpdate(awareness, remapped, null);
117
106
  applyingParentUpdate = false;
107
+ } else if (type === "add" && currentMxLike) {
108
+ applyingParentUpdate = true;
109
+ if (currentMxLike.indexOfNextAdd < currentMxLike.history.length) {
110
+ currentMxLike.history.splice(
111
+ currentMxLike.indexOfNextAdd,
112
+ currentMxLike.history.length - currentMxLike.indexOfNextAdd
113
+ );
114
+ }
115
+ currentMxLike.history.push({});
116
+ currentMxLike.indexOfNextAdd = currentMxLike.history.length;
117
+ currentMxLike.fireEvent(
118
+ createMxEventObject("add", { edit: { changes: [] } })
119
+ );
120
+ applyingParentUpdate = false;
118
121
  } else if (type === "undo" && currentMxLike) {
119
122
  applyingParentUpdate = true;
120
123
  if (currentMxLike.indexOfNextAdd > 0) currentMxLike.indexOfNextAdd--;
121
- currentMxLike.fireEvent(createMxEventObject("undo", { edit: { changes: [] } }));
124
+ currentMxLike.fireEvent(
125
+ createMxEventObject("undo", { edit: { changes: [] } })
126
+ );
122
127
  applyingParentUpdate = false;
123
128
  } else if (type === "redo" && currentMxLike) {
124
129
  applyingParentUpdate = true;
125
- if (currentMxLike.indexOfNextAdd < currentMxLike.history.length) currentMxLike.indexOfNextAdd++;
126
- currentMxLike.fireEvent(createMxEventObject("redo", { edit: { changes: [] } }));
130
+ if (currentMxLike.indexOfNextAdd < currentMxLike.history.length)
131
+ currentMxLike.indexOfNextAdd++;
132
+ currentMxLike.fireEvent(
133
+ createMxEventObject("redo", { edit: { changes: [] } })
134
+ );
127
135
  applyingParentUpdate = false;
128
136
  } else if (type === "clear" && currentMxLike) {
129
137
  applyingParentUpdate = true;
@@ -171,7 +179,10 @@ function createIframeBridgeProvider(ydoc, awareness) {
171
179
  try {
172
180
  listener(this, evt);
173
181
  } catch (e) {
174
- console.warn("[iframe-bridge] undoManager event listener error:", e);
182
+ console.warn(
183
+ "[iframe-bridge] undoManager event listener error:",
184
+ e
185
+ );
175
186
  }
176
187
  }
177
188
  }
@@ -1 +1 @@
1
- {"version":3,"file":"provider.es.js","sources":["../../../iframe-bridge/src/provider.ts"],"sourcesContent":["import * as Y from \"yjs\";\nimport {\n Awareness,\n applyAwarenessUpdate,\n encodeAwarenessUpdate,\n} from \"y-protocols/awareness\";\n\ntype ListenerFn = (sender: unknown, evt?: unknown) => void;\n\nfunction createMxEventObject(name: string, props?: Record<string, unknown>) {\n const _props = props || {};\n return {\n name,\n getName: () => name,\n getProperty: (k: string) => _props[k],\n };\n}\n\ntype MxLike = Record<string, unknown> & {\n eventListeners: Array<string | ListenerFn>;\n history: unknown[];\n indexOfNextAdd: number;\n addListener(name: string, fn: ListenerFn): void;\n fireEvent(evt: unknown): void;\n canUndo(): boolean;\n canRedo(): boolean;\n undo(): void;\n redo(): void;\n undoableEditHappened(_edit: unknown): void;\n};\n\nexport interface DrawioEditor {\n undoManager?: {\n eventListeners?: unknown[];\n [key: string]: unknown;\n };\n undoListener?: (...args: unknown[]) => void;\n}\n\nexport interface DrawioFile {\n getUi(): { editor: DrawioEditor };\n}\n\nexport interface IframeBridgeProvider {\n serverClientId: number | null;\n takeoverUndoManager: (file: DrawioFile) => () => void;\n destroy: () => void;\n}\n\nfunction readVarUint(data: Uint8Array, pos: number): [number, number] {\n let result = 0;\n let shift = 0;\n let byte: number;\n do {\n byte = data[pos++];\n result |= (byte & 0x7f) << shift;\n shift += 7;\n } while (byte >= 0x80);\n return [result >>> 0, pos];\n}\n\nfunction writeVarUint(value: number): number[] {\n const bytes: number[] = [];\n while (value > 0x7f) {\n bytes.push((value & 0x7f) | 0x80);\n value >>>= 7;\n }\n bytes.push(value);\n return bytes;\n}\n\nfunction readVarString(data: Uint8Array, pos: number): [string, number] {\n const [len, pos2] = readVarUint(data, pos);\n const str = new TextDecoder().decode(data.subarray(pos2, pos2 + len));\n return [str, pos2 + len];\n}\n\nfunction writeVarString(str: string): number[] {\n const encoded = new TextEncoder().encode(str);\n return [...writeVarUint(encoded.length), ...encoded];\n}\n\nfunction remapClientIdInUpdate(\n update: Uint8Array,\n fromId: number,\n toId: number,\n): Uint8Array {\n const result: number[] = [];\n let pos = 0;\n\n const [count, pos2] = readVarUint(update, pos);\n pos = pos2;\n result.push(...writeVarUint(count));\n\n for (let i = 0; i < count; i++) {\n const [clientID, pos3] = readVarUint(update, pos);\n pos = pos3;\n const [clock, pos4] = readVarUint(update, pos);\n pos = pos4;\n const [state, pos5] = readVarString(update, pos);\n pos = pos5;\n\n const mappedId = clientID === fromId ? toId : clientID;\n result.push(...writeVarUint(mappedId));\n result.push(...writeVarUint(clock));\n result.push(...writeVarString(state));\n }\n\n return new Uint8Array(result);\n}\n\nexport function createIframeBridgeProvider(\n ydoc: Y.Doc,\n awareness: Awareness,\n): IframeBridgeProvider {\n let applyingParentUpdate = false;\n let serverClientId: number | null = null;\n let currentCleanup: (() => void) | null = null;\n let currentMxLike: MxLike | null = null;\n\n const onYdocUpdate = (update: Uint8Array) => {\n if (applyingParentUpdate) return;\n // 本地编辑,添加 history 条目\n if (currentMxLike) {\n if (currentMxLike.indexOfNextAdd < currentMxLike.history.length) {\n currentMxLike.history.splice(\n currentMxLike.indexOfNextAdd,\n currentMxLike.history.length - currentMxLike.indexOfNextAdd,\n );\n }\n currentMxLike.history.push({});\n currentMxLike.indexOfNextAdd = currentMxLike.history.length;\n currentMxLike.fireEvent(createMxEventObject(\"add\", { edit: { changes: [] } }));\n }\n window.parent.postMessage(\n { type: \"ydoc-update\", payload: Array.from(update) },\n \"*\",\n );\n };\n\n const onAwarenessUpdate = ({\n added,\n updated,\n removed,\n }: {\n added: number[];\n updated: number[];\n removed: number[];\n }) => {\n if (applyingParentUpdate) return;\n const changes = [...added, ...updated, ...removed];\n if (changes.length === 0) return;\n\n const update = encodeAwarenessUpdate(awareness, changes);\n const remapped =\n serverClientId != null\n ? remapClientIdInUpdate(update, awareness.clientID, serverClientId)\n : update;\n\n window.parent.postMessage(\n { type: \"awareness-update\", payload: Array.from(remapped) },\n \"*\",\n );\n };\n\n const onMessage = (event: MessageEvent) => {\n if (event.source !== window.parent) return;\n const { type, payload, serverClientId: receivedServerId } = event.data;\n\n if (type === \"pong\" && receivedServerId != null) {\n serverClientId = receivedServerId;\n return;\n }\n\n if (type === \"ydoc-sync\" || type === \"ydoc-update\") {\n applyingParentUpdate = true;\n Y.applyUpdate(ydoc, new Uint8Array(payload));\n applyingParentUpdate = false;\n } else if (type === \"awareness-sync\" || type === \"awareness-update\") {\n if (receivedServerId != null) {\n serverClientId = receivedServerId;\n }\n\n const raw = new Uint8Array(payload);\n const remapped =\n serverClientId != null\n ? remapClientIdInUpdate(raw, serverClientId, awareness.clientID)\n : raw;\n\n applyingParentUpdate = true;\n applyAwarenessUpdate(awareness, remapped, null);\n applyingParentUpdate = false;\n } else if (type === \"undo\" && currentMxLike) {\n applyingParentUpdate = true;\n if (currentMxLike.indexOfNextAdd > 0) currentMxLike.indexOfNextAdd--;\n currentMxLike.fireEvent(createMxEventObject(\"undo\", { edit: { changes: [] } }));\n applyingParentUpdate = false;\n } else if (type === \"redo\" && currentMxLike) {\n applyingParentUpdate = true;\n if (currentMxLike.indexOfNextAdd < currentMxLike.history.length) currentMxLike.indexOfNextAdd++;\n currentMxLike.fireEvent(createMxEventObject(\"redo\", { edit: { changes: [] } }));\n applyingParentUpdate = false;\n } else if (type === \"clear\" && currentMxLike) {\n applyingParentUpdate = true;\n currentMxLike.history = [];\n currentMxLike.indexOfNextAdd = 0;\n currentMxLike.fireEvent(createMxEventObject(\"clear\"));\n applyingParentUpdate = false;\n }\n };\n\n ydoc.on(\"update\", onYdocUpdate);\n awareness.on(\"update\", onAwarenessUpdate);\n window.addEventListener(\"message\", onMessage);\n\n window.parent.postMessage({ type: \"init\" }, \"*\");\n\n return {\n get serverClientId() {\n return serverClientId;\n },\n takeoverUndoManager(file: DrawioFile) {\n if (currentCleanup) {\n currentCleanup();\n }\n\n const editor = file.getUi().editor;\n const originUndoManager = editor.undoManager;\n\n const pairs: Array<[string, ListenerFn]> = [];\n const raw = Array.isArray(originUndoManager?.eventListeners)\n ? (originUndoManager.eventListeners as unknown[])\n : [];\n for (let i = 0; i + 1 < raw.length; i += 2) {\n const key = String(raw[i]);\n const fn = raw[i + 1] as ListenerFn;\n pairs.push([key, fn]);\n }\n\n const mxLike: MxLike = {\n eventListeners: [] as Array<string | ListenerFn>,\n history: [] as unknown[],\n indexOfNextAdd: 0,\n\n addListener(name: string, fn: ListenerFn) {\n this.eventListeners.push(name, fn);\n },\n\n fireEvent(evt: unknown) {\n const eventName: string =\n (evt as { name?: string } | undefined)?.name ||\n ((evt as { getName?: () => string } | undefined)?.getName?.() ?? \"\");\n for (let i = 0; i + 1 < this.eventListeners.length; i += 2) {\n const key = this.eventListeners[i];\n const listener = this.eventListeners[i + 1] as ListenerFn;\n if (key === eventName) {\n try {\n listener(this, evt);\n } catch (e) {\n console.warn(\"[iframe-bridge] undoManager event listener error:\", e);\n }\n }\n }\n },\n\n canUndo(): boolean {\n return this.indexOfNextAdd > 0;\n },\n\n canRedo(): boolean {\n return this.indexOfNextAdd < this.history.length;\n },\n\n undo() {\n if (!applyingParentUpdate) {\n window.parent.postMessage({ type: \"undo\" }, \"*\");\n }\n },\n\n redo() {\n if (!applyingParentUpdate) {\n window.parent.postMessage({ type: \"redo\" }, \"*\");\n }\n },\n\n undoableEditHappened() {\n // no-op\n },\n };\n\n pairs.forEach(([key, fn]) => {\n const k = key.toLowerCase();\n if (k === \"add\" || k === \"clear\" || k === \"undo\" || k === \"redo\") {\n mxLike.addListener(k, fn);\n }\n });\n\n currentMxLike = mxLike;\n editor.undoManager = mxLike as any;\n editor.undoListener = function () {};\n\n const cleanup = () => {\n editor.undoManager = originUndoManager;\n editor.undoListener = originUndoManager?.undoListener as ((...args: unknown[]) => void) | undefined;\n currentMxLike = null;\n };\n\n currentCleanup = cleanup;\n return cleanup;\n },\n destroy: () => {\n ydoc.off(\"update\", onYdocUpdate);\n awareness.off(\"update\", onAwarenessUpdate);\n window.removeEventListener(\"message\", onMessage);\n if (currentCleanup) {\n currentCleanup();\n }\n },\n };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"provider.es.js","sources":["../../../iframe-bridge/src/provider.ts"],"sourcesContent":["import * as Y from \"yjs\";\nimport {\n Awareness,\n applyAwarenessUpdate,\n encodeAwarenessUpdate,\n} from \"y-protocols/awareness\";\n\ntype ListenerFn = (sender: unknown, evt?: unknown) => void;\n\nfunction createMxEventObject(name: string, props?: Record<string, unknown>) {\n const _props = props || {};\n return {\n name,\n getName: () => name,\n getProperty: (k: string) => _props[k],\n };\n}\n\ntype MxLike = Record<string, unknown> & {\n eventListeners: Array<string | ListenerFn>;\n history: unknown[];\n indexOfNextAdd: number;\n addListener(name: string, fn: ListenerFn): void;\n fireEvent(evt: unknown): void;\n canUndo(): boolean;\n canRedo(): boolean;\n undo(): void;\n redo(): void;\n undoableEditHappened(_edit: unknown): void;\n};\n\nexport interface DrawioEditor {\n undoManager?: {\n eventListeners?: unknown[];\n [key: string]: unknown;\n };\n undoListener?: (...args: unknown[]) => void;\n}\n\nexport interface DrawioFile {\n getUi(): { editor: DrawioEditor };\n}\n\nexport interface IframeBridgeProvider {\n serverClientId: number | null;\n takeoverUndoManager: (file: DrawioFile) => () => void;\n destroy: () => void;\n}\n\nfunction readVarUint(data: Uint8Array, pos: number): [number, number] {\n let result = 0;\n let shift = 0;\n let byte: number;\n do {\n byte = data[pos++];\n result |= (byte & 0x7f) << shift;\n shift += 7;\n } while (byte >= 0x80);\n return [result >>> 0, pos];\n}\n\nfunction writeVarUint(value: number): number[] {\n const bytes: number[] = [];\n while (value > 0x7f) {\n bytes.push((value & 0x7f) | 0x80);\n value >>>= 7;\n }\n bytes.push(value);\n return bytes;\n}\n\nfunction readVarString(data: Uint8Array, pos: number): [string, number] {\n const [len, pos2] = readVarUint(data, pos);\n const str = new TextDecoder().decode(data.subarray(pos2, pos2 + len));\n return [str, pos2 + len];\n}\n\nfunction writeVarString(str: string): number[] {\n const encoded = new TextEncoder().encode(str);\n return [...writeVarUint(encoded.length), ...encoded];\n}\n\nfunction remapClientIdInUpdate(\n update: Uint8Array,\n fromId: number,\n toId: number,\n): Uint8Array {\n const result: number[] = [];\n let pos = 0;\n\n const [count, pos2] = readVarUint(update, pos);\n pos = pos2;\n result.push(...writeVarUint(count));\n\n for (let i = 0; i < count; i++) {\n const [clientID, pos3] = readVarUint(update, pos);\n pos = pos3;\n const [clock, pos4] = readVarUint(update, pos);\n pos = pos4;\n const [state, pos5] = readVarString(update, pos);\n pos = pos5;\n\n const mappedId = clientID === fromId ? toId : clientID;\n result.push(...writeVarUint(mappedId));\n result.push(...writeVarUint(clock));\n result.push(...writeVarString(state));\n }\n\n return new Uint8Array(result);\n}\n\nexport function createIframeBridgeProvider(\n ydoc: Y.Doc,\n awareness: Awareness,\n): IframeBridgeProvider {\n let applyingParentUpdate = false;\n let serverClientId: number | null = null;\n let currentCleanup: (() => void) | null = null;\n let currentMxLike: MxLike | null = null;\n\n const onYdocUpdate = (update: Uint8Array) => {\n if (applyingParentUpdate) return;\n window.parent.postMessage(\n { type: \"ydoc-update\", payload: Array.from(update) },\n \"*\",\n );\n };\n\n const onAwarenessUpdate = ({\n added,\n updated,\n removed,\n }: {\n added: number[];\n updated: number[];\n removed: number[];\n }) => {\n if (applyingParentUpdate) return;\n const changes = [...added, ...updated, ...removed];\n if (changes.length === 0) return;\n\n const update = encodeAwarenessUpdate(awareness, changes);\n const remapped =\n serverClientId != null\n ? remapClientIdInUpdate(update, awareness.clientID, serverClientId)\n : update;\n\n window.parent.postMessage(\n { type: \"awareness-update\", payload: Array.from(remapped) },\n \"*\",\n );\n };\n\n const onMessage = (event: MessageEvent) => {\n if (event.source !== window.parent) return;\n const { type, payload, serverClientId: receivedServerId } = event.data;\n\n if (type === \"pong\" && receivedServerId != null) {\n serverClientId = receivedServerId;\n return;\n }\n\n if (type === \"ydoc-sync\" || type === \"ydoc-update\") {\n applyingParentUpdate = true;\n Y.applyUpdate(ydoc, new Uint8Array(payload));\n applyingParentUpdate = false;\n } else if (type === \"awareness-sync\" || type === \"awareness-update\") {\n if (receivedServerId != null) {\n serverClientId = receivedServerId;\n }\n\n const raw = new Uint8Array(payload);\n const remapped =\n serverClientId != null\n ? remapClientIdInUpdate(raw, serverClientId, awareness.clientID)\n : raw;\n\n applyingParentUpdate = true;\n applyAwarenessUpdate(awareness, remapped, null);\n applyingParentUpdate = false;\n } else if (type === \"add\" && currentMxLike) {\n applyingParentUpdate = true;\n if (currentMxLike.indexOfNextAdd < currentMxLike.history.length) {\n currentMxLike.history.splice(\n currentMxLike.indexOfNextAdd,\n currentMxLike.history.length - currentMxLike.indexOfNextAdd,\n );\n }\n currentMxLike.history.push({});\n currentMxLike.indexOfNextAdd = currentMxLike.history.length;\n currentMxLike.fireEvent(\n createMxEventObject(\"add\", { edit: { changes: [] } }),\n );\n applyingParentUpdate = false;\n } else if (type === \"undo\" && currentMxLike) {\n applyingParentUpdate = true;\n if (currentMxLike.indexOfNextAdd > 0) currentMxLike.indexOfNextAdd--;\n currentMxLike.fireEvent(\n createMxEventObject(\"undo\", { edit: { changes: [] } }),\n );\n applyingParentUpdate = false;\n } else if (type === \"redo\" && currentMxLike) {\n applyingParentUpdate = true;\n if (currentMxLike.indexOfNextAdd < currentMxLike.history.length)\n currentMxLike.indexOfNextAdd++;\n currentMxLike.fireEvent(\n createMxEventObject(\"redo\", { edit: { changes: [] } }),\n );\n applyingParentUpdate = false;\n } else if (type === \"clear\" && currentMxLike) {\n applyingParentUpdate = true;\n currentMxLike.history = [];\n currentMxLike.indexOfNextAdd = 0;\n currentMxLike.fireEvent(createMxEventObject(\"clear\"));\n applyingParentUpdate = false;\n }\n };\n\n ydoc.on(\"update\", onYdocUpdate);\n awareness.on(\"update\", onAwarenessUpdate);\n window.addEventListener(\"message\", onMessage);\n\n window.parent.postMessage({ type: \"init\" }, \"*\");\n\n return {\n get serverClientId() {\n return serverClientId;\n },\n takeoverUndoManager(file: DrawioFile) {\n if (currentCleanup) {\n currentCleanup();\n }\n\n const editor = file.getUi().editor;\n const originUndoManager = editor.undoManager;\n\n const pairs: Array<[string, ListenerFn]> = [];\n const raw = Array.isArray(originUndoManager?.eventListeners)\n ? (originUndoManager.eventListeners as unknown[])\n : [];\n for (let i = 0; i + 1 < raw.length; i += 2) {\n const key = String(raw[i]);\n const fn = raw[i + 1] as ListenerFn;\n pairs.push([key, fn]);\n }\n\n const mxLike: MxLike = {\n eventListeners: [] as Array<string | ListenerFn>,\n history: [] as unknown[],\n indexOfNextAdd: 0,\n\n addListener(name: string, fn: ListenerFn) {\n this.eventListeners.push(name, fn);\n },\n\n fireEvent(evt: unknown) {\n const eventName: string =\n (evt as { name?: string } | undefined)?.name ||\n ((evt as { getName?: () => string } | undefined)?.getName?.() ??\n \"\");\n for (let i = 0; i + 1 < this.eventListeners.length; i += 2) {\n const key = this.eventListeners[i];\n const listener = this.eventListeners[i + 1] as ListenerFn;\n if (key === eventName) {\n try {\n listener(this, evt);\n } catch (e) {\n console.warn(\n \"[iframe-bridge] undoManager event listener error:\",\n e,\n );\n }\n }\n }\n },\n\n canUndo(): boolean {\n return this.indexOfNextAdd > 0;\n },\n\n canRedo(): boolean {\n return this.indexOfNextAdd < this.history.length;\n },\n\n undo() {\n if (!applyingParentUpdate) {\n window.parent.postMessage({ type: \"undo\" }, \"*\");\n }\n },\n\n redo() {\n if (!applyingParentUpdate) {\n window.parent.postMessage({ type: \"redo\" }, \"*\");\n }\n },\n\n undoableEditHappened() {\n // no-op\n },\n };\n\n pairs.forEach(([key, fn]) => {\n const k = key.toLowerCase();\n if (k === \"add\" || k === \"clear\" || k === \"undo\" || k === \"redo\") {\n mxLike.addListener(k, fn);\n }\n });\n\n currentMxLike = mxLike;\n editor.undoManager = mxLike as any;\n editor.undoListener = function () {};\n\n const cleanup = () => {\n editor.undoManager = originUndoManager;\n editor.undoListener = originUndoManager?.undoListener as\n | ((...args: unknown[]) => void)\n | undefined;\n currentMxLike = null;\n };\n\n currentCleanup = cleanup;\n return cleanup;\n },\n destroy: () => {\n ydoc.off(\"update\", onYdocUpdate);\n awareness.off(\"update\", onAwarenessUpdate);\n window.removeEventListener(\"message\", onMessage);\n if (currentCleanup) {\n currentCleanup();\n }\n },\n };\n}\n"],"names":[],"mappings":"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"}
@@ -20,13 +20,17 @@ function _interopNamespaceDefault(e) {
20
20
  }
21
21
  const Y__namespace = /* @__PURE__ */ _interopNamespaceDefault(Y);
22
22
  const IFRAME_ORIGIN = {};
23
- function createIframeBridgeServer(ydoc, awareness$1, options) {
23
+ function createIframeBridgeServer(iframe, ydoc, awareness$1, options) {
24
24
  const { undoManager } = options ?? {};
25
- const iframes = /* @__PURE__ */ new Map();
26
- const iframeReady = /* @__PURE__ */ new Set();
25
+ function postToIframe(type, payload) {
26
+ const cw = iframe.contentWindow;
27
+ if (cw) {
28
+ cw.postMessage({ type, payload }, "*");
29
+ }
30
+ }
27
31
  const onYdocUpdate = (update, origin) => {
28
32
  if (origin === IFRAME_ORIGIN) return;
29
- broadcastToAll("ydoc-update", update);
33
+ postToIframe("ydoc-update", update);
30
34
  };
31
35
  const onAwarenessUpdate = ({
32
36
  added,
@@ -36,56 +40,33 @@ function createIframeBridgeServer(ydoc, awareness$1, options) {
36
40
  const changes = [...added, ...updated, ...removed];
37
41
  if (changes.length === 0) return;
38
42
  const update = awareness.encodeAwarenessUpdate(awareness$1, changes);
39
- broadcastToAll("awareness-update", update);
43
+ postToIframe("awareness-update", update);
40
44
  };
41
- function broadcastToAll(type, payload, excludeSource) {
42
- for (const iframe of iframes.values()) {
43
- if (iframe.contentWindow && iframe.contentWindow !== excludeSource) {
44
- iframe.contentWindow.postMessage({ type, payload }, "*");
45
- }
46
- }
47
- }
48
45
  const onMessage = (event) => {
49
- let iframeId = null;
50
- for (const [id, iframe] of iframes) {
51
- if (event.source === iframe.contentWindow) {
52
- iframeId = id;
53
- break;
54
- }
55
- }
56
- if (!iframeId) return;
46
+ if (event.source !== iframe.contentWindow) return;
57
47
  const { type: msgType, payload } = event.data;
58
- const sourceWindow = event.source;
59
48
  if (msgType === "init") {
60
- if (!iframeReady.has(iframeId)) {
61
- iframeReady.add(iframeId);
62
- }
63
49
  const docState = Y__namespace.encodeStateAsUpdate(ydoc);
64
50
  const awarenessState = awareness.encodeAwarenessUpdate(
65
51
  awareness$1,
66
52
  Array.from(awareness$1.getStates().keys())
67
53
  );
68
- sourceWindow.postMessage(
69
- { type: "ydoc-sync", payload: Array.from(docState) },
70
- "*"
71
- );
72
- sourceWindow.postMessage(
73
- {
74
- type: "awareness-sync",
75
- payload: Array.from(awarenessState),
76
- serverClientId: awareness$1.clientID
77
- },
78
- "*"
54
+ postToIframe("ydoc-sync", new Uint8Array(Array.from(docState)));
55
+ postToIframe(
56
+ "awareness-sync",
57
+ new Uint8Array(Array.from(awarenessState))
79
58
  );
80
59
  } else if (msgType === "ping") {
81
- sourceWindow.postMessage(
82
- { type: "pong", serverClientId: awareness$1.clientID },
83
- "*"
84
- );
60
+ const cw = iframe.contentWindow;
61
+ if (cw) {
62
+ cw.postMessage(
63
+ { type: "pong", serverClientId: awareness$1.clientID },
64
+ "*"
65
+ );
66
+ }
85
67
  } else if (msgType === "ydoc-update") {
86
68
  const update = new Uint8Array(payload);
87
69
  Y__namespace.applyUpdate(ydoc, update, IFRAME_ORIGIN);
88
- broadcastToAll("ydoc-update", update, sourceWindow);
89
70
  } else if (msgType === "awareness-update") {
90
71
  awareness.applyAwarenessUpdate(awareness$1, new Uint8Array(payload), null);
91
72
  } else if (msgType === "undo" && undoManager) {
@@ -94,23 +75,19 @@ function createIframeBridgeServer(ydoc, awareness$1, options) {
94
75
  undoManager.redo();
95
76
  }
96
77
  };
97
- function addIframe(iframe, iframeId) {
98
- iframes.set(iframeId, iframe);
99
- }
100
- function removeIframe(iframeId) {
101
- iframes.delete(iframeId);
102
- iframeReady.delete(iframeId);
103
- }
104
78
  const onUndoPopped = (e) => {
105
79
  const t = e && (e.type || e.reason || e.kind);
106
80
  if (t === "undo") {
107
- broadcastToAll("undo", new Uint8Array());
81
+ postToIframe("undo", new Uint8Array());
108
82
  } else if (t === "redo") {
109
- broadcastToAll("redo", new Uint8Array());
83
+ postToIframe("redo", new Uint8Array());
110
84
  }
111
85
  };
112
86
  const onStackCleared = () => {
113
- broadcastToAll("clear", new Uint8Array());
87
+ postToIframe("clear", new Uint8Array());
88
+ };
89
+ const onStackItemAdded = () => {
90
+ postToIframe("add", new Uint8Array());
114
91
  };
115
92
  ydoc.on("update", onYdocUpdate);
116
93
  awareness$1.on("update", onAwarenessUpdate);
@@ -118,10 +95,9 @@ function createIframeBridgeServer(ydoc, awareness$1, options) {
118
95
  if (undoManager) {
119
96
  undoManager.on("stack-item-popped", onUndoPopped);
120
97
  undoManager.on("stack-cleared", onStackCleared);
98
+ undoManager.on("stack-item-added", onStackItemAdded);
121
99
  }
122
100
  return {
123
- addIframe,
124
- removeIframe,
125
101
  destroy: () => {
126
102
  ydoc.off("update", onYdocUpdate);
127
103
  awareness$1.off("update", onAwarenessUpdate);
@@ -129,9 +105,8 @@ function createIframeBridgeServer(ydoc, awareness$1, options) {
129
105
  if (undoManager) {
130
106
  undoManager.off("stack-item-popped", onUndoPopped);
131
107
  undoManager.off("stack-cleared", onStackCleared);
108
+ undoManager.off("stack-item-added", onStackItemAdded);
132
109
  }
133
- iframes.clear();
134
- iframeReady.clear();
135
110
  }
136
111
  };
137
112
  }
@@ -1 +1 @@
1
- {"version":3,"file":"server.cjs.js","sources":["../../../iframe-bridge/src/origin.ts","../../../iframe-bridge/src/server.ts"],"sourcesContent":["/**\n * iframe bridge 内部变更的 origin 标识。\n * 当 provider 端产生 ydoc-update 时,使用此 origin 标记,\n * 以便 server 端的 UndoManager 能正确追踪来自 iframe 的变更。\n */\nexport const IFRAME_ORIGIN: object = {};\n","import * as Y from \"yjs\";\nimport {\n Awareness,\n applyAwarenessUpdate,\n encodeAwarenessUpdate,\n} from \"y-protocols/awareness\";\nimport { IFRAME_ORIGIN } from \"./origin.js\";\n\nexport interface IframeBridgeServerOptions {\n undoManager?: Y.UndoManager;\n}\n\nexport interface IframeBridgeServer {\n addIframe: (iframe: HTMLIFrameElement, iframeId: string) => void;\n removeIframe: (iframeId: string) => void;\n destroy: () => void;\n}\n\nexport function createIframeBridgeServer(\n ydoc: Y.Doc,\n awareness: Awareness,\n options?: IframeBridgeServerOptions,\n): IframeBridgeServer {\n const { undoManager } = options ?? {};\n const iframes = new Map<string, HTMLIFrameElement>();\n const iframeReady = new Set<string>();\n\n const onYdocUpdate = (update: Uint8Array, origin: unknown) => {\n if (origin === IFRAME_ORIGIN) return;\n broadcastToAll(\"ydoc-update\", update);\n };\n\n const onAwarenessUpdate = ({\n added,\n updated,\n removed,\n }: {\n added: number[];\n updated: number[];\n removed: number[];\n }) => {\n const changes = [...added, ...updated, ...removed];\n if (changes.length === 0) return;\n const update = encodeAwarenessUpdate(awareness, changes);\n broadcastToAll(\"awareness-update\", update);\n };\n\n function broadcastToAll(type: string, payload: Uint8Array, excludeSource?: Window) {\n for (const iframe of iframes.values()) {\n if (iframe.contentWindow && iframe.contentWindow !== excludeSource) {\n iframe.contentWindow.postMessage({ type, payload }, \"*\");\n }\n }\n }\n\n const onMessage = (event: MessageEvent) => {\n let iframeId: string | null = null;\n for (const [id, iframe] of iframes) {\n if (event.source === iframe.contentWindow) {\n iframeId = id;\n break;\n }\n }\n if (!iframeId) return;\n\n const { type: msgType, payload } = event.data;\n const sourceWindow = event.source as Window;\n\n if (msgType === \"init\") {\n if (!iframeReady.has(iframeId)) {\n iframeReady.add(iframeId);\n }\n const docState = Y.encodeStateAsUpdate(ydoc);\n const awarenessState = encodeAwarenessUpdate(\n awareness,\n Array.from(awareness.getStates().keys()),\n );\n sourceWindow.postMessage(\n { type: \"ydoc-sync\", payload: Array.from(docState) },\n \"*\",\n );\n sourceWindow.postMessage(\n {\n type: \"awareness-sync\",\n payload: Array.from(awarenessState),\n serverClientId: awareness.clientID,\n },\n \"*\",\n );\n } else if (msgType === \"ping\") {\n sourceWindow.postMessage(\n { type: \"pong\", serverClientId: awareness.clientID },\n \"*\",\n );\n } else if (msgType === \"ydoc-update\") {\n const update = new Uint8Array(payload);\n Y.applyUpdate(ydoc, update, IFRAME_ORIGIN);\n broadcastToAll(\"ydoc-update\", update, sourceWindow);\n } else if (msgType === \"awareness-update\") {\n applyAwarenessUpdate(awareness, new Uint8Array(payload), null);\n } else if (msgType === \"undo\" && undoManager) {\n undoManager.undo();\n } else if (msgType === \"redo\" && undoManager) {\n undoManager.redo();\n }\n };\n\n function addIframe(iframe: HTMLIFrameElement, iframeId: string) {\n iframes.set(iframeId, iframe);\n }\n\n function removeIframe(iframeId: string) {\n iframes.delete(iframeId);\n iframeReady.delete(iframeId);\n }\n\n const onUndoPopped = (e: { type?: string; reason?: string; kind?: string }) => {\n const t = e && (e.type || e.reason || e.kind);\n if (t === \"undo\") {\n broadcastToAll(\"undo\", new Uint8Array());\n } else if (t === \"redo\") {\n broadcastToAll(\"redo\", new Uint8Array());\n }\n };\n\n const onStackCleared = () => {\n broadcastToAll(\"clear\", new Uint8Array());\n };\n\n ydoc.on(\"update\", onYdocUpdate);\n awareness.on(\"update\", onAwarenessUpdate);\n window.addEventListener(\"message\", onMessage);\n if (undoManager) {\n undoManager.on(\"stack-item-popped\", onUndoPopped);\n undoManager.on(\"stack-cleared\", onStackCleared);\n }\n\n return {\n addIframe,\n removeIframe,\n destroy: () => {\n ydoc.off(\"update\", onYdocUpdate);\n awareness.off(\"update\", onAwarenessUpdate);\n window.removeEventListener(\"message\", onMessage);\n if (undoManager) {\n undoManager.off(\"stack-item-popped\", onUndoPopped);\n undoManager.off(\"stack-cleared\", onStackCleared);\n }\n iframes.clear();\n iframeReady.clear();\n },\n };\n}\n"],"names":["awareness","encodeAwarenessUpdate","Y","applyAwarenessUpdate"],"mappings":"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"}
1
+ {"version":3,"file":"server.cjs.js","sources":["../../../iframe-bridge/src/origin.ts","../../../iframe-bridge/src/server.ts"],"sourcesContent":["/**\n * iframe bridge 内部变更的 origin 标识。\n * 当 provider 端产生 ydoc-update 时,使用此 origin 标记,\n * 以便 server 端的 UndoManager 能正确追踪来自 iframe 的变更。\n */\nexport const IFRAME_ORIGIN: object = {};\n","import * as Y from \"yjs\";\nimport {\n Awareness,\n applyAwarenessUpdate,\n encodeAwarenessUpdate,\n} from \"y-protocols/awareness\";\nimport { IFRAME_ORIGIN } from \"./origin.js\";\n\nexport interface IframeBridgeServerOptions {\n undoManager?: Y.UndoManager;\n}\n\nexport interface IframeBridgeServer {\n destroy: () => void;\n}\n\nexport function createIframeBridgeServer(\n iframe: HTMLIFrameElement,\n ydoc: Y.Doc,\n awareness: Awareness,\n options?: IframeBridgeServerOptions,\n): IframeBridgeServer {\n const { undoManager } = options ?? {};\n let iframeReady = false;\n\n function postToIframe(type: string, payload: Uint8Array) {\n const cw = iframe.contentWindow;\n if (cw) {\n cw.postMessage({ type, payload }, \"*\");\n }\n }\n\n const onYdocUpdate = (update: Uint8Array, origin: unknown) => {\n if (origin === IFRAME_ORIGIN) return;\n postToIframe(\"ydoc-update\", update);\n };\n\n const onAwarenessUpdate = ({\n added,\n updated,\n removed,\n }: {\n added: number[];\n updated: number[];\n removed: number[];\n }) => {\n const changes = [...added, ...updated, ...removed];\n if (changes.length === 0) return;\n const update = encodeAwarenessUpdate(awareness, changes);\n postToIframe(\"awareness-update\", update);\n };\n\n const onMessage = (event: MessageEvent) => {\n if (event.source !== iframe.contentWindow) return;\n\n const { type: msgType, payload } = event.data;\n\n if (msgType === \"init\") {\n if (!iframeReady) {\n iframeReady = true;\n }\n const docState = Y.encodeStateAsUpdate(ydoc);\n const awarenessState = encodeAwarenessUpdate(\n awareness,\n Array.from(awareness.getStates().keys()),\n );\n postToIframe(\"ydoc-sync\", new Uint8Array(Array.from(docState)));\n postToIframe(\n \"awareness-sync\",\n new Uint8Array(Array.from(awarenessState)),\n );\n } else if (msgType === \"ping\") {\n const cw = iframe.contentWindow;\n if (cw) {\n cw.postMessage(\n { type: \"pong\", serverClientId: awareness.clientID },\n \"*\",\n );\n }\n } else if (msgType === \"ydoc-update\") {\n const update = new Uint8Array(payload);\n Y.applyUpdate(ydoc, update, IFRAME_ORIGIN);\n // 源 iframe 已经持有此 update,无需回传\n } else if (msgType === \"awareness-update\") {\n applyAwarenessUpdate(awareness, new Uint8Array(payload), null);\n } else if (msgType === \"undo\" && undoManager) {\n undoManager.undo();\n } else if (msgType === \"redo\" && undoManager) {\n undoManager.redo();\n }\n };\n\n const onUndoPopped = (e: {\n type?: string;\n reason?: string;\n kind?: string;\n }) => {\n const t = e && (e.type || e.reason || e.kind);\n if (t === \"undo\") {\n postToIframe(\"undo\", new Uint8Array());\n } else if (t === \"redo\") {\n postToIframe(\"redo\", new Uint8Array());\n }\n };\n\n const onStackCleared = () => {\n postToIframe(\"clear\", new Uint8Array());\n };\n\n const onStackItemAdded = () => {\n postToIframe(\"add\", new Uint8Array());\n };\n\n ydoc.on(\"update\", onYdocUpdate);\n awareness.on(\"update\", onAwarenessUpdate);\n window.addEventListener(\"message\", onMessage);\n if (undoManager) {\n undoManager.on(\"stack-item-popped\", onUndoPopped);\n undoManager.on(\"stack-cleared\", onStackCleared);\n undoManager.on(\"stack-item-added\", onStackItemAdded);\n }\n\n return {\n destroy: () => {\n ydoc.off(\"update\", onYdocUpdate);\n awareness.off(\"update\", onAwarenessUpdate);\n window.removeEventListener(\"message\", onMessage);\n if (undoManager) {\n undoManager.off(\"stack-item-popped\", onUndoPopped);\n undoManager.off(\"stack-cleared\", onStackCleared);\n undoManager.off(\"stack-item-added\", onStackItemAdded);\n }\n iframeReady = false;\n },\n };\n}\n"],"names":["awareness","encodeAwarenessUpdate","Y","applyAwarenessUpdate"],"mappings":"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"}
@@ -1,13 +1,17 @@
1
1
  import * as Y from "yjs";
2
2
  import { encodeAwarenessUpdate, applyAwarenessUpdate } from "y-protocols/awareness";
3
3
  const IFRAME_ORIGIN = {};
4
- function createIframeBridgeServer(ydoc, awareness, options) {
4
+ function createIframeBridgeServer(iframe, ydoc, awareness, options) {
5
5
  const { undoManager } = options ?? {};
6
- const iframes = /* @__PURE__ */ new Map();
7
- const iframeReady = /* @__PURE__ */ new Set();
6
+ function postToIframe(type, payload) {
7
+ const cw = iframe.contentWindow;
8
+ if (cw) {
9
+ cw.postMessage({ type, payload }, "*");
10
+ }
11
+ }
8
12
  const onYdocUpdate = (update, origin) => {
9
13
  if (origin === IFRAME_ORIGIN) return;
10
- broadcastToAll("ydoc-update", update);
14
+ postToIframe("ydoc-update", update);
11
15
  };
12
16
  const onAwarenessUpdate = ({
13
17
  added,
@@ -17,56 +21,33 @@ function createIframeBridgeServer(ydoc, awareness, options) {
17
21
  const changes = [...added, ...updated, ...removed];
18
22
  if (changes.length === 0) return;
19
23
  const update = encodeAwarenessUpdate(awareness, changes);
20
- broadcastToAll("awareness-update", update);
24
+ postToIframe("awareness-update", update);
21
25
  };
22
- function broadcastToAll(type, payload, excludeSource) {
23
- for (const iframe of iframes.values()) {
24
- if (iframe.contentWindow && iframe.contentWindow !== excludeSource) {
25
- iframe.contentWindow.postMessage({ type, payload }, "*");
26
- }
27
- }
28
- }
29
26
  const onMessage = (event) => {
30
- let iframeId = null;
31
- for (const [id, iframe] of iframes) {
32
- if (event.source === iframe.contentWindow) {
33
- iframeId = id;
34
- break;
35
- }
36
- }
37
- if (!iframeId) return;
27
+ if (event.source !== iframe.contentWindow) return;
38
28
  const { type: msgType, payload } = event.data;
39
- const sourceWindow = event.source;
40
29
  if (msgType === "init") {
41
- if (!iframeReady.has(iframeId)) {
42
- iframeReady.add(iframeId);
43
- }
44
30
  const docState = Y.encodeStateAsUpdate(ydoc);
45
31
  const awarenessState = encodeAwarenessUpdate(
46
32
  awareness,
47
33
  Array.from(awareness.getStates().keys())
48
34
  );
49
- sourceWindow.postMessage(
50
- { type: "ydoc-sync", payload: Array.from(docState) },
51
- "*"
52
- );
53
- sourceWindow.postMessage(
54
- {
55
- type: "awareness-sync",
56
- payload: Array.from(awarenessState),
57
- serverClientId: awareness.clientID
58
- },
59
- "*"
35
+ postToIframe("ydoc-sync", new Uint8Array(Array.from(docState)));
36
+ postToIframe(
37
+ "awareness-sync",
38
+ new Uint8Array(Array.from(awarenessState))
60
39
  );
61
40
  } else if (msgType === "ping") {
62
- sourceWindow.postMessage(
63
- { type: "pong", serverClientId: awareness.clientID },
64
- "*"
65
- );
41
+ const cw = iframe.contentWindow;
42
+ if (cw) {
43
+ cw.postMessage(
44
+ { type: "pong", serverClientId: awareness.clientID },
45
+ "*"
46
+ );
47
+ }
66
48
  } else if (msgType === "ydoc-update") {
67
49
  const update = new Uint8Array(payload);
68
50
  Y.applyUpdate(ydoc, update, IFRAME_ORIGIN);
69
- broadcastToAll("ydoc-update", update, sourceWindow);
70
51
  } else if (msgType === "awareness-update") {
71
52
  applyAwarenessUpdate(awareness, new Uint8Array(payload), null);
72
53
  } else if (msgType === "undo" && undoManager) {
@@ -75,23 +56,19 @@ function createIframeBridgeServer(ydoc, awareness, options) {
75
56
  undoManager.redo();
76
57
  }
77
58
  };
78
- function addIframe(iframe, iframeId) {
79
- iframes.set(iframeId, iframe);
80
- }
81
- function removeIframe(iframeId) {
82
- iframes.delete(iframeId);
83
- iframeReady.delete(iframeId);
84
- }
85
59
  const onUndoPopped = (e) => {
86
60
  const t = e && (e.type || e.reason || e.kind);
87
61
  if (t === "undo") {
88
- broadcastToAll("undo", new Uint8Array());
62
+ postToIframe("undo", new Uint8Array());
89
63
  } else if (t === "redo") {
90
- broadcastToAll("redo", new Uint8Array());
64
+ postToIframe("redo", new Uint8Array());
91
65
  }
92
66
  };
93
67
  const onStackCleared = () => {
94
- broadcastToAll("clear", new Uint8Array());
68
+ postToIframe("clear", new Uint8Array());
69
+ };
70
+ const onStackItemAdded = () => {
71
+ postToIframe("add", new Uint8Array());
95
72
  };
96
73
  ydoc.on("update", onYdocUpdate);
97
74
  awareness.on("update", onAwarenessUpdate);
@@ -99,10 +76,9 @@ function createIframeBridgeServer(ydoc, awareness, options) {
99
76
  if (undoManager) {
100
77
  undoManager.on("stack-item-popped", onUndoPopped);
101
78
  undoManager.on("stack-cleared", onStackCleared);
79
+ undoManager.on("stack-item-added", onStackItemAdded);
102
80
  }
103
81
  return {
104
- addIframe,
105
- removeIframe,
106
82
  destroy: () => {
107
83
  ydoc.off("update", onYdocUpdate);
108
84
  awareness.off("update", onAwarenessUpdate);
@@ -110,9 +86,8 @@ function createIframeBridgeServer(ydoc, awareness, options) {
110
86
  if (undoManager) {
111
87
  undoManager.off("stack-item-popped", onUndoPopped);
112
88
  undoManager.off("stack-cleared", onStackCleared);
89
+ undoManager.off("stack-item-added", onStackItemAdded);
113
90
  }
114
- iframes.clear();
115
- iframeReady.clear();
116
91
  }
117
92
  };
118
93
  }
@@ -1 +1 @@
1
- {"version":3,"file":"server.es.js","sources":["../../../iframe-bridge/src/origin.ts","../../../iframe-bridge/src/server.ts"],"sourcesContent":["/**\n * iframe bridge 内部变更的 origin 标识。\n * 当 provider 端产生 ydoc-update 时,使用此 origin 标记,\n * 以便 server 端的 UndoManager 能正确追踪来自 iframe 的变更。\n */\nexport const IFRAME_ORIGIN: object = {};\n","import * as Y from \"yjs\";\nimport {\n Awareness,\n applyAwarenessUpdate,\n encodeAwarenessUpdate,\n} from \"y-protocols/awareness\";\nimport { IFRAME_ORIGIN } from \"./origin.js\";\n\nexport interface IframeBridgeServerOptions {\n undoManager?: Y.UndoManager;\n}\n\nexport interface IframeBridgeServer {\n addIframe: (iframe: HTMLIFrameElement, iframeId: string) => void;\n removeIframe: (iframeId: string) => void;\n destroy: () => void;\n}\n\nexport function createIframeBridgeServer(\n ydoc: Y.Doc,\n awareness: Awareness,\n options?: IframeBridgeServerOptions,\n): IframeBridgeServer {\n const { undoManager } = options ?? {};\n const iframes = new Map<string, HTMLIFrameElement>();\n const iframeReady = new Set<string>();\n\n const onYdocUpdate = (update: Uint8Array, origin: unknown) => {\n if (origin === IFRAME_ORIGIN) return;\n broadcastToAll(\"ydoc-update\", update);\n };\n\n const onAwarenessUpdate = ({\n added,\n updated,\n removed,\n }: {\n added: number[];\n updated: number[];\n removed: number[];\n }) => {\n const changes = [...added, ...updated, ...removed];\n if (changes.length === 0) return;\n const update = encodeAwarenessUpdate(awareness, changes);\n broadcastToAll(\"awareness-update\", update);\n };\n\n function broadcastToAll(type: string, payload: Uint8Array, excludeSource?: Window) {\n for (const iframe of iframes.values()) {\n if (iframe.contentWindow && iframe.contentWindow !== excludeSource) {\n iframe.contentWindow.postMessage({ type, payload }, \"*\");\n }\n }\n }\n\n const onMessage = (event: MessageEvent) => {\n let iframeId: string | null = null;\n for (const [id, iframe] of iframes) {\n if (event.source === iframe.contentWindow) {\n iframeId = id;\n break;\n }\n }\n if (!iframeId) return;\n\n const { type: msgType, payload } = event.data;\n const sourceWindow = event.source as Window;\n\n if (msgType === \"init\") {\n if (!iframeReady.has(iframeId)) {\n iframeReady.add(iframeId);\n }\n const docState = Y.encodeStateAsUpdate(ydoc);\n const awarenessState = encodeAwarenessUpdate(\n awareness,\n Array.from(awareness.getStates().keys()),\n );\n sourceWindow.postMessage(\n { type: \"ydoc-sync\", payload: Array.from(docState) },\n \"*\",\n );\n sourceWindow.postMessage(\n {\n type: \"awareness-sync\",\n payload: Array.from(awarenessState),\n serverClientId: awareness.clientID,\n },\n \"*\",\n );\n } else if (msgType === \"ping\") {\n sourceWindow.postMessage(\n { type: \"pong\", serverClientId: awareness.clientID },\n \"*\",\n );\n } else if (msgType === \"ydoc-update\") {\n const update = new Uint8Array(payload);\n Y.applyUpdate(ydoc, update, IFRAME_ORIGIN);\n broadcastToAll(\"ydoc-update\", update, sourceWindow);\n } else if (msgType === \"awareness-update\") {\n applyAwarenessUpdate(awareness, new Uint8Array(payload), null);\n } else if (msgType === \"undo\" && undoManager) {\n undoManager.undo();\n } else if (msgType === \"redo\" && undoManager) {\n undoManager.redo();\n }\n };\n\n function addIframe(iframe: HTMLIFrameElement, iframeId: string) {\n iframes.set(iframeId, iframe);\n }\n\n function removeIframe(iframeId: string) {\n iframes.delete(iframeId);\n iframeReady.delete(iframeId);\n }\n\n const onUndoPopped = (e: { type?: string; reason?: string; kind?: string }) => {\n const t = e && (e.type || e.reason || e.kind);\n if (t === \"undo\") {\n broadcastToAll(\"undo\", new Uint8Array());\n } else if (t === \"redo\") {\n broadcastToAll(\"redo\", new Uint8Array());\n }\n };\n\n const onStackCleared = () => {\n broadcastToAll(\"clear\", new Uint8Array());\n };\n\n ydoc.on(\"update\", onYdocUpdate);\n awareness.on(\"update\", onAwarenessUpdate);\n window.addEventListener(\"message\", onMessage);\n if (undoManager) {\n undoManager.on(\"stack-item-popped\", onUndoPopped);\n undoManager.on(\"stack-cleared\", onStackCleared);\n }\n\n return {\n addIframe,\n removeIframe,\n destroy: () => {\n ydoc.off(\"update\", onYdocUpdate);\n awareness.off(\"update\", onAwarenessUpdate);\n window.removeEventListener(\"message\", onMessage);\n if (undoManager) {\n undoManager.off(\"stack-item-popped\", onUndoPopped);\n undoManager.off(\"stack-cleared\", onStackCleared);\n }\n iframes.clear();\n iframeReady.clear();\n },\n };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.es.js","sources":["../../../iframe-bridge/src/origin.ts","../../../iframe-bridge/src/server.ts"],"sourcesContent":["/**\n * iframe bridge 内部变更的 origin 标识。\n * 当 provider 端产生 ydoc-update 时,使用此 origin 标记,\n * 以便 server 端的 UndoManager 能正确追踪来自 iframe 的变更。\n */\nexport const IFRAME_ORIGIN: object = {};\n","import * as Y from \"yjs\";\nimport {\n Awareness,\n applyAwarenessUpdate,\n encodeAwarenessUpdate,\n} from \"y-protocols/awareness\";\nimport { IFRAME_ORIGIN } from \"./origin.js\";\n\nexport interface IframeBridgeServerOptions {\n undoManager?: Y.UndoManager;\n}\n\nexport interface IframeBridgeServer {\n destroy: () => void;\n}\n\nexport function createIframeBridgeServer(\n iframe: HTMLIFrameElement,\n ydoc: Y.Doc,\n awareness: Awareness,\n options?: IframeBridgeServerOptions,\n): IframeBridgeServer {\n const { undoManager } = options ?? {};\n let iframeReady = false;\n\n function postToIframe(type: string, payload: Uint8Array) {\n const cw = iframe.contentWindow;\n if (cw) {\n cw.postMessage({ type, payload }, \"*\");\n }\n }\n\n const onYdocUpdate = (update: Uint8Array, origin: unknown) => {\n if (origin === IFRAME_ORIGIN) return;\n postToIframe(\"ydoc-update\", update);\n };\n\n const onAwarenessUpdate = ({\n added,\n updated,\n removed,\n }: {\n added: number[];\n updated: number[];\n removed: number[];\n }) => {\n const changes = [...added, ...updated, ...removed];\n if (changes.length === 0) return;\n const update = encodeAwarenessUpdate(awareness, changes);\n postToIframe(\"awareness-update\", update);\n };\n\n const onMessage = (event: MessageEvent) => {\n if (event.source !== iframe.contentWindow) return;\n\n const { type: msgType, payload } = event.data;\n\n if (msgType === \"init\") {\n if (!iframeReady) {\n iframeReady = true;\n }\n const docState = Y.encodeStateAsUpdate(ydoc);\n const awarenessState = encodeAwarenessUpdate(\n awareness,\n Array.from(awareness.getStates().keys()),\n );\n postToIframe(\"ydoc-sync\", new Uint8Array(Array.from(docState)));\n postToIframe(\n \"awareness-sync\",\n new Uint8Array(Array.from(awarenessState)),\n );\n } else if (msgType === \"ping\") {\n const cw = iframe.contentWindow;\n if (cw) {\n cw.postMessage(\n { type: \"pong\", serverClientId: awareness.clientID },\n \"*\",\n );\n }\n } else if (msgType === \"ydoc-update\") {\n const update = new Uint8Array(payload);\n Y.applyUpdate(ydoc, update, IFRAME_ORIGIN);\n // 源 iframe 已经持有此 update,无需回传\n } else if (msgType === \"awareness-update\") {\n applyAwarenessUpdate(awareness, new Uint8Array(payload), null);\n } else if (msgType === \"undo\" && undoManager) {\n undoManager.undo();\n } else if (msgType === \"redo\" && undoManager) {\n undoManager.redo();\n }\n };\n\n const onUndoPopped = (e: {\n type?: string;\n reason?: string;\n kind?: string;\n }) => {\n const t = e && (e.type || e.reason || e.kind);\n if (t === \"undo\") {\n postToIframe(\"undo\", new Uint8Array());\n } else if (t === \"redo\") {\n postToIframe(\"redo\", new Uint8Array());\n }\n };\n\n const onStackCleared = () => {\n postToIframe(\"clear\", new Uint8Array());\n };\n\n const onStackItemAdded = () => {\n postToIframe(\"add\", new Uint8Array());\n };\n\n ydoc.on(\"update\", onYdocUpdate);\n awareness.on(\"update\", onAwarenessUpdate);\n window.addEventListener(\"message\", onMessage);\n if (undoManager) {\n undoManager.on(\"stack-item-popped\", onUndoPopped);\n undoManager.on(\"stack-cleared\", onStackCleared);\n undoManager.on(\"stack-item-added\", onStackItemAdded);\n }\n\n return {\n destroy: () => {\n ydoc.off(\"update\", onYdocUpdate);\n awareness.off(\"update\", onAwarenessUpdate);\n window.removeEventListener(\"message\", onMessage);\n if (undoManager) {\n undoManager.off(\"stack-item-popped\", onUndoPopped);\n undoManager.off(\"stack-cleared\", onStackCleared);\n undoManager.off(\"stack-item-added\", onStackItemAdded);\n }\n iframeReady = false;\n },\n };\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "y-mxgraph",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "description": "Yjs binding for draw.io (mxGraph) documents",
5
5
  "keywords": [
6
6
  "yjs",