1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | var warning = require("fbjs/lib/warning");
|
17 |
|
18 | var DraftTreeInvariants = {
|
19 | |
20 |
|
21 |
|
22 | isValidBlock: function isValidBlock(block, blockMap) {
|
23 | var key = block.getKey();
|
24 |
|
25 | var parentKey = block.getParentKey();
|
26 |
|
27 | if (parentKey != null) {
|
28 | var parent = blockMap.get(parentKey);
|
29 |
|
30 | if (!parent.getChildKeys().includes(key)) {
|
31 | process.env.NODE_ENV !== "production" ? warning(true, 'Tree is missing parent -> child pointer on %s', key) : void 0;
|
32 | return false;
|
33 | }
|
34 | }
|
35 |
|
36 |
|
37 | var children = block.getChildKeys().map(function (k) {
|
38 | return blockMap.get(k);
|
39 | });
|
40 |
|
41 | if (!children.every(function (c) {
|
42 | return c.getParentKey() === key;
|
43 | })) {
|
44 | process.env.NODE_ENV !== "production" ? warning(true, 'Tree is missing child -> parent pointer on %s', key) : void 0;
|
45 | return false;
|
46 | }
|
47 |
|
48 |
|
49 | var prevSiblingKey = block.getPrevSiblingKey();
|
50 |
|
51 | if (prevSiblingKey != null) {
|
52 | var prevSibling = blockMap.get(prevSiblingKey);
|
53 |
|
54 | if (prevSibling.getNextSiblingKey() !== key) {
|
55 | process.env.NODE_ENV !== "production" ? warning(true, "Tree is missing nextSibling pointer on %s's prevSibling", key) : void 0;
|
56 | return false;
|
57 | }
|
58 | }
|
59 |
|
60 |
|
61 | var nextSiblingKey = block.getNextSiblingKey();
|
62 |
|
63 | if (nextSiblingKey != null) {
|
64 | var nextSibling = blockMap.get(nextSiblingKey);
|
65 |
|
66 | if (nextSibling.getPrevSiblingKey() !== key) {
|
67 | process.env.NODE_ENV !== "production" ? warning(true, "Tree is missing prevSibling pointer on %s's nextSibling", key) : void 0;
|
68 | return false;
|
69 | }
|
70 | }
|
71 |
|
72 |
|
73 | if (nextSiblingKey !== null && prevSiblingKey !== null) {
|
74 | if (prevSiblingKey === nextSiblingKey) {
|
75 | process.env.NODE_ENV !== "production" ? warning(true, 'Tree has a two-node cycle at %s', key) : void 0;
|
76 | return false;
|
77 | }
|
78 | }
|
79 |
|
80 |
|
81 | if (block.text != '') {
|
82 | if (block.getChildKeys().size > 0) {
|
83 | process.env.NODE_ENV !== "production" ? warning(true, 'Leaf node %s has children', key) : void 0;
|
84 | return false;
|
85 | }
|
86 | }
|
87 |
|
88 | return true;
|
89 | },
|
90 |
|
91 | |
92 |
|
93 |
|
94 |
|
95 |
|
96 |
|
97 | isConnectedTree: function isConnectedTree(blockMap) {
|
98 |
|
99 | var eligibleFirstNodes = blockMap.toArray().filter(function (block) {
|
100 | return block.getParentKey() == null && block.getPrevSiblingKey() == null;
|
101 | });
|
102 |
|
103 | if (eligibleFirstNodes.length !== 1) {
|
104 | process.env.NODE_ENV !== "production" ? warning(true, 'Tree is not connected. More or less than one first node') : void 0;
|
105 | return false;
|
106 | }
|
107 |
|
108 | var firstNode = eligibleFirstNodes.shift();
|
109 | var nodesSeen = 0;
|
110 | var currentKey = firstNode.getKey();
|
111 | var visitedStack = [];
|
112 |
|
113 | while (currentKey != null) {
|
114 | var currentNode = blockMap.get(currentKey);
|
115 | var childKeys = currentNode.getChildKeys();
|
116 | var nextSiblingKey = currentNode.getNextSiblingKey();
|
117 |
|
118 | if (childKeys.size > 0) {
|
119 | if (nextSiblingKey != null) {
|
120 | visitedStack.unshift(nextSiblingKey);
|
121 | }
|
122 |
|
123 | var children = childKeys.map(function (k) {
|
124 | return blockMap.get(k);
|
125 | });
|
126 |
|
127 | var _firstNode = children.find(function (block) {
|
128 | return block.getPrevSiblingKey() == null;
|
129 | });
|
130 |
|
131 | if (_firstNode == null) {
|
132 | process.env.NODE_ENV !== "production" ? warning(true, '%s has no first child', currentKey) : void 0;
|
133 | return false;
|
134 | }
|
135 |
|
136 | currentKey = _firstNode.getKey();
|
137 | } else {
|
138 | if (currentNode.getNextSiblingKey() != null) {
|
139 | currentKey = currentNode.getNextSiblingKey();
|
140 | } else {
|
141 | currentKey = visitedStack.shift();
|
142 | }
|
143 | }
|
144 |
|
145 | nodesSeen++;
|
146 | }
|
147 |
|
148 | if (nodesSeen !== blockMap.size) {
|
149 | process.env.NODE_ENV !== "production" ? warning(true, 'Tree is not connected. %s nodes were seen instead of %s', nodesSeen, blockMap.size) : void 0;
|
150 | return false;
|
151 | }
|
152 |
|
153 | return true;
|
154 | },
|
155 |
|
156 | |
157 |
|
158 |
|
159 | isValidTree: function isValidTree(blockMap) {
|
160 | var _this = this;
|
161 |
|
162 | var blocks = blockMap.toArray();
|
163 |
|
164 | if (!blocks.every(function (block) {
|
165 | return _this.isValidBlock(block, blockMap);
|
166 | })) {
|
167 | return false;
|
168 | }
|
169 |
|
170 | return this.isConnectedTree(blockMap);
|
171 | }
|
172 | };
|
173 | module.exports = DraftTreeInvariants; |
\ | No newline at end of file |