Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 

173 řádky
5.3 KiB

  1. "use strict";
  2. /**
  3. * Copyright (c) Facebook, Inc. and its affiliates.
  4. *
  5. * This source code is licensed under the MIT license found in the
  6. * LICENSE file in the root directory of this source tree.
  7. *
  8. * @format
  9. *
  10. * @emails oncall+draft_js
  11. *
  12. * This is unstable and not part of the public API and should not be used by
  13. * production systems. This file may be update/removed without notice.
  14. */
  15. var warning = require("fbjs/lib/warning");
  16. var DraftTreeInvariants = {
  17. /**
  18. * Check if the block is valid
  19. */
  20. isValidBlock: function isValidBlock(block, blockMap) {
  21. var key = block.getKey(); // is its parent's child
  22. var parentKey = block.getParentKey();
  23. if (parentKey != null) {
  24. var parent = blockMap.get(parentKey);
  25. if (!parent.getChildKeys().includes(key)) {
  26. process.env.NODE_ENV !== "production" ? warning(true, 'Tree is missing parent -> child pointer on %s', key) : void 0;
  27. return false;
  28. }
  29. } // is its children's parent
  30. var children = block.getChildKeys().map(function (k) {
  31. return blockMap.get(k);
  32. });
  33. if (!children.every(function (c) {
  34. return c.getParentKey() === key;
  35. })) {
  36. process.env.NODE_ENV !== "production" ? warning(true, 'Tree is missing child -> parent pointer on %s', key) : void 0;
  37. return false;
  38. } // is its previous sibling's next sibling
  39. var prevSiblingKey = block.getPrevSiblingKey();
  40. if (prevSiblingKey != null) {
  41. var prevSibling = blockMap.get(prevSiblingKey);
  42. if (prevSibling.getNextSiblingKey() !== key) {
  43. process.env.NODE_ENV !== "production" ? warning(true, "Tree is missing nextSibling pointer on %s's prevSibling", key) : void 0;
  44. return false;
  45. }
  46. } // is its next sibling's previous sibling
  47. var nextSiblingKey = block.getNextSiblingKey();
  48. if (nextSiblingKey != null) {
  49. var nextSibling = blockMap.get(nextSiblingKey);
  50. if (nextSibling.getPrevSiblingKey() !== key) {
  51. process.env.NODE_ENV !== "production" ? warning(true, "Tree is missing prevSibling pointer on %s's nextSibling", key) : void 0;
  52. return false;
  53. }
  54. } // no 2-node cycles
  55. if (nextSiblingKey !== null && prevSiblingKey !== null) {
  56. if (prevSiblingKey === nextSiblingKey) {
  57. process.env.NODE_ENV !== "production" ? warning(true, 'Tree has a two-node cycle at %s', key) : void 0;
  58. return false;
  59. }
  60. } // if it's a leaf node, it has text but no children
  61. if (block.text != '') {
  62. if (block.getChildKeys().size > 0) {
  63. process.env.NODE_ENV !== "production" ? warning(true, 'Leaf node %s has children', key) : void 0;
  64. return false;
  65. }
  66. }
  67. return true;
  68. },
  69. /**
  70. * Checks that this is a connected tree on all the blocks
  71. * starting from the first block, traversing nextSibling and child pointers
  72. * should be a tree (preorder traversal - parent, then children)
  73. * num of connected node === number of blocks
  74. */
  75. isConnectedTree: function isConnectedTree(blockMap) {
  76. // exactly one node has no previous sibling + no parent
  77. var eligibleFirstNodes = blockMap.toArray().filter(function (block) {
  78. return block.getParentKey() == null && block.getPrevSiblingKey() == null;
  79. });
  80. if (eligibleFirstNodes.length !== 1) {
  81. process.env.NODE_ENV !== "production" ? warning(true, 'Tree is not connected. More or less than one first node') : void 0;
  82. return false;
  83. }
  84. var firstNode = eligibleFirstNodes.shift();
  85. var nodesSeen = 0;
  86. var currentKey = firstNode.getKey();
  87. var visitedStack = [];
  88. while (currentKey != null) {
  89. var currentNode = blockMap.get(currentKey);
  90. var childKeys = currentNode.getChildKeys();
  91. var nextSiblingKey = currentNode.getNextSiblingKey(); // if the node has children, add parent's next sibling to stack and go to children
  92. if (childKeys.size > 0) {
  93. if (nextSiblingKey != null) {
  94. visitedStack.unshift(nextSiblingKey);
  95. }
  96. var children = childKeys.map(function (k) {
  97. return blockMap.get(k);
  98. });
  99. var _firstNode = children.find(function (block) {
  100. return block.getPrevSiblingKey() == null;
  101. });
  102. if (_firstNode == null) {
  103. process.env.NODE_ENV !== "production" ? warning(true, '%s has no first child', currentKey) : void 0;
  104. return false;
  105. }
  106. currentKey = _firstNode.getKey(); // TODO(T32490138): Deal with multi-node cycles here
  107. } else {
  108. if (currentNode.getNextSiblingKey() != null) {
  109. currentKey = currentNode.getNextSiblingKey();
  110. } else {
  111. currentKey = visitedStack.shift();
  112. }
  113. }
  114. nodesSeen++;
  115. }
  116. if (nodesSeen !== blockMap.size) {
  117. process.env.NODE_ENV !== "production" ? warning(true, 'Tree is not connected. %s nodes were seen instead of %s', nodesSeen, blockMap.size) : void 0;
  118. return false;
  119. }
  120. return true;
  121. },
  122. /**
  123. * Checks that the block map is a connected tree with valid blocks
  124. */
  125. isValidTree: function isValidTree(blockMap) {
  126. var _this = this;
  127. var blocks = blockMap.toArray();
  128. if (!blocks.every(function (block) {
  129. return _this.isValidBlock(block, blockMap);
  130. })) {
  131. return false;
  132. }
  133. return this.isConnectedTree(blockMap);
  134. }
  135. };
  136. module.exports = DraftTreeInvariants;