y-mxgraph 0.1.6 → 0.2.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.
package/y-mxgraph.umd.js CHANGED
@@ -1453,32 +1453,148 @@
1453
1453
  cleanupAwareness == null ? void 0 : cleanupAwareness();
1454
1454
  };
1455
1455
  }
1456
+ const defaultApplyFileData = (file, xml) => {
1457
+ file.ui.setFileData(xml);
1458
+ };
1459
+ function mergeFileIntoDoc(doc, fileXml, strategy) {
1460
+ let parsed;
1461
+ try {
1462
+ parsed = parse$4(fileXml);
1463
+ } catch (err) {
1464
+ console.warn(
1465
+ "[y-mxgraph] 合并失败,file XML 解析异常,回退到 replace:",
1466
+ err
1467
+ );
1468
+ return false;
1469
+ }
1470
+ const mxfileObj = parsed == null ? void 0 : parsed.mxfile;
1471
+ if (!mxfileObj || !Array.isArray(mxfileObj.diagram)) {
1472
+ console.warn(
1473
+ "[y-mxgraph] 合并失败,file XML 不是合法 mxfile,回退到 replace"
1474
+ );
1475
+ return false;
1476
+ }
1477
+ const mxfileMap = doc.getMap(key);
1478
+ const diagramMap = mxfileMap.get(key$1);
1479
+ const diagramOrder = mxfileMap.get(diagramOrderKey);
1480
+ if (!diagramMap || !diagramOrder) {
1481
+ console.warn("[y-mxgraph] 合并失败,doc 结构不完整,回退到 replace");
1482
+ return false;
1483
+ }
1484
+ doc.transact(() => {
1485
+ var _a;
1486
+ for (const diagram of mxfileObj.diagram) {
1487
+ const id = ((_a = diagram._attributes) == null ? void 0 : _a.id) || "";
1488
+ if (!id)
1489
+ continue;
1490
+ const docHas = diagramMap.has(id);
1491
+ if (docHas && strategy === "merge-remote") {
1492
+ continue;
1493
+ }
1494
+ const yDiagram = parse$1(
1495
+ diagram
1496
+ );
1497
+ diagramMap.set(id, yDiagram);
1498
+ if (!docHas) {
1499
+ diagramOrder.push([id]);
1500
+ }
1501
+ }
1502
+ });
1503
+ return true;
1504
+ }
1505
+ function reconcileInitialContent(doc, file, strategy, applyFileData) {
1506
+ const mxfileMap = doc.getMap(key);
1507
+ const docHasData = mxfileMap.size > 0;
1508
+ const fileHasAnyData = !!file.data;
1509
+ const fileHasDiagrams = fileHasAnyData && file.data.includes("<diagram");
1510
+ if (strategy === "replace") {
1511
+ if (docHasData) {
1512
+ const xml2 = doc2xml(doc);
1513
+ if (xml2 && xml2.includes("<diagram")) {
1514
+ applyFileData(file, xml2);
1515
+ } else if (!fileHasAnyData) {
1516
+ applyFileData(file, Binding.generateFileTemplate("diagram-0"));
1517
+ }
1518
+ } else if (!fileHasAnyData) {
1519
+ applyFileData(file, Binding.generateFileTemplate("diagram-0"));
1520
+ }
1521
+ return mxfileMap.size > 0;
1522
+ }
1523
+ if (!docHasData && !fileHasDiagrams) {
1524
+ if (!fileHasAnyData) {
1525
+ applyFileData(file, Binding.generateFileTemplate("diagram-0"));
1526
+ }
1527
+ return false;
1528
+ }
1529
+ if (!docHasData && fileHasDiagrams) {
1530
+ try {
1531
+ doc.transact(() => {
1532
+ xml2doc(file.data, doc);
1533
+ });
1534
+ return true;
1535
+ } catch (err) {
1536
+ console.warn(
1537
+ "[y-mxgraph] merge 模式下 xml2doc 失败,回退 replace:",
1538
+ err
1539
+ );
1540
+ applyFileData(file, Binding.generateFileTemplate("diagram-0"));
1541
+ return false;
1542
+ }
1543
+ }
1544
+ if (docHasData && !fileHasDiagrams) {
1545
+ const xml2 = doc2xml(doc);
1546
+ if (xml2 && xml2.includes("<diagram")) {
1547
+ applyFileData(file, xml2);
1548
+ } else if (!fileHasAnyData) {
1549
+ applyFileData(file, Binding.generateFileTemplate("diagram-0"));
1550
+ }
1551
+ return mxfileMap.size > 0;
1552
+ }
1553
+ const ok = mergeFileIntoDoc(doc, file.data, strategy);
1554
+ if (!ok) {
1555
+ const xml2 = doc2xml(doc);
1556
+ if (xml2 && xml2.includes("<diagram"))
1557
+ applyFileData(file, xml2);
1558
+ return mxfileMap.size > 0;
1559
+ }
1560
+ const xml = doc2xml(doc);
1561
+ if (xml && xml.includes("<diagram"))
1562
+ applyFileData(file, xml);
1563
+ return true;
1564
+ }
1456
1565
  class Binding {
1457
1566
  constructor(file, options) {
1458
1567
  this.suppressLocalApply = false;
1459
1568
  this.docInitialized = false;
1460
- const { doc, awareness, undoManager, mouseMoveThrottle, cursor } = options;
1569
+ const {
1570
+ doc,
1571
+ awareness,
1572
+ undoManager,
1573
+ mouseMoveThrottle,
1574
+ cursor,
1575
+ initialContent = "replace",
1576
+ applyFileData = defaultApplyFileData
1577
+ } = options;
1461
1578
  this.doc = doc;
1579
+ this.initialContentStrategy = initialContent;
1462
1580
  const ui = file.getUi();
1463
1581
  const graph = ui.editor.graph;
1464
1582
  this.mxGraphModel = graph.model;
1465
- const mxfileMap = doc.getMap(key);
1466
- const docHasData = mxfileMap.size > 0;
1467
- this.docInitialized = docHasData;
1468
- file.setShadowPages(file.ui.clonePages(file.ui.pages));
1469
- if (docHasData) {
1470
- initDocSnapshot(doc, false);
1471
- const fullPatch = generatePatch([], doc);
1472
- if (Object.keys(fullPatch).length > 0) {
1473
- this.suppressLocalApply = true;
1474
- try {
1475
- file.patch([fullPatch]);
1476
- } finally {
1477
- this.suppressLocalApply = false;
1478
- }
1583
+ this.suppressLocalApply = true;
1584
+ try {
1585
+ this.docInitialized = reconcileInitialContent(
1586
+ doc,
1587
+ file,
1588
+ initialContent,
1589
+ applyFileData
1590
+ );
1591
+ if (this.docInitialized) {
1592
+ initDocSnapshot(doc, false);
1479
1593
  }
1480
- file.setShadowPages(file.ui.clonePages(file.ui.pages));
1594
+ } finally {
1595
+ this.suppressLocalApply = false;
1481
1596
  }
1597
+ file.setShadowPages(file.ui.clonePages(file.ui.pages));
1482
1598
  this.mxListener = () => {
1483
1599
  if (this.suppressLocalApply)
1484
1600
  return;
@@ -1501,13 +1617,36 @@
1501
1617
  };
1502
1618
  this.mxGraphModel.addListener("change", this.mxListener);
1503
1619
  this.docObserver = (events, transaction) => {
1504
- if (!this.docInitialized) {
1505
- this.docInitialized = true;
1506
- }
1507
1620
  if (transaction.local && transaction.origin === LOCAL_ORIGIN) {
1508
1621
  generatePatch(events);
1509
1622
  return;
1510
1623
  }
1624
+ if (this.shouldReplaceWhenDocHasData) {
1625
+ const mxfileMap = doc.getMap(key);
1626
+ const diagramMap = mxfileMap.get(key$1);
1627
+ if (diagramMap && diagramMap.size > 0) {
1628
+ const xml = doc2xml(doc);
1629
+ if (xml && xml.includes("<diagram")) {
1630
+ this.suppressLocalApply = true;
1631
+ try {
1632
+ applyFileData(file, xml);
1633
+ file.setShadowPages(file.ui.clonePages(file.ui.pages));
1634
+ initDocSnapshot(doc, false);
1635
+ const ui2 = file.getUi();
1636
+ const editor = ui2.editor;
1637
+ editor.setStatus("");
1638
+ editor.setModified(false);
1639
+ } finally {
1640
+ this.suppressLocalApply = false;
1641
+ }
1642
+ this.docInitialized = true;
1643
+ return;
1644
+ }
1645
+ }
1646
+ }
1647
+ if (!this.docInitialized) {
1648
+ this.docInitialized = true;
1649
+ }
1511
1650
  const patch = generatePatch(events);
1512
1651
  if (Object.keys(patch).length === 0)
1513
1652
  return;
@@ -1519,7 +1658,7 @@
1519
1658
  this.suppressLocalApply = false;
1520
1659
  }
1521
1660
  };
1522
- mxfileMap.observeDeep(this.docObserver);
1661
+ doc.getMap(key).observeDeep(this.docObserver);
1523
1662
  if (awareness) {
1524
1663
  this.cleanupCollaborator = bindCollaborator(file, {
1525
1664
  awareness,
@@ -1532,6 +1671,10 @@
1532
1671
  this.cleanupUndoManager = bindUndoManager(doc, file, undoManager);
1533
1672
  }
1534
1673
  }
1674
+ /** replace 策略下,构造时 doc 为空,现在 doc 有数据时需要强制替换 */
1675
+ get shouldReplaceWhenDocHasData() {
1676
+ return this.initialContentStrategy === "replace" && !this.docInitialized;
1677
+ }
1535
1678
  /**
1536
1679
  * 销毁绑定,解除所有监听器
1537
1680
  * @param deep - 是否深度清理(包括 awareness/undoManager),默认 false