997ea7850e1ff7400caa0cbe06e97374f432633090c8040b47f88fbb4c6e1512b55e7edcb50ad753d16c6c771fff0c4bb368f0b3dae722c3ca42f94b140fc2 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. import Delta, { OpIterator } from 'quill-delta';
  2. import Module from '../core/module.js';
  3. const parseCellIdentity = identity => {
  4. const parts = identity.split(':');
  5. return [Number(parts[0]) - 1, Number(parts[1]) - 1];
  6. };
  7. const stringifyCellIdentity = (row, column) => `${row + 1}:${column + 1}`;
  8. export const composePosition = (delta, index) => {
  9. let newIndex = index;
  10. const thisIter = new OpIterator(delta.ops);
  11. let offset = 0;
  12. while (thisIter.hasNext() && offset <= newIndex) {
  13. const length = thisIter.peekLength();
  14. const nextType = thisIter.peekType();
  15. thisIter.next();
  16. switch (nextType) {
  17. case 'delete':
  18. if (length > newIndex - offset) {
  19. return null;
  20. }
  21. newIndex -= length;
  22. break;
  23. case 'insert':
  24. newIndex += length;
  25. offset += length;
  26. break;
  27. default:
  28. offset += length;
  29. break;
  30. }
  31. }
  32. return newIndex;
  33. };
  34. const compactCellData = _ref => {
  35. let {
  36. content,
  37. attributes
  38. } = _ref;
  39. const data = {};
  40. if (content.length() > 0) {
  41. data.content = content.ops;
  42. }
  43. if (attributes && Object.keys(attributes).length > 0) {
  44. data.attributes = attributes;
  45. }
  46. return Object.keys(data).length > 0 ? data : null;
  47. };
  48. const compactTableData = _ref2 => {
  49. let {
  50. rows,
  51. columns,
  52. cells
  53. } = _ref2;
  54. const data = {};
  55. if (rows.length() > 0) {
  56. data.rows = rows.ops;
  57. }
  58. if (columns.length() > 0) {
  59. data.columns = columns.ops;
  60. }
  61. if (Object.keys(cells).length) {
  62. data.cells = cells;
  63. }
  64. return data;
  65. };
  66. const reindexCellIdentities = (cells, _ref3) => {
  67. let {
  68. rows,
  69. columns
  70. } = _ref3;
  71. const reindexedCells = {};
  72. Object.keys(cells).forEach(identity => {
  73. let [row, column] = parseCellIdentity(identity);
  74. // @ts-expect-error Fix me later
  75. row = composePosition(rows, row);
  76. // @ts-expect-error Fix me later
  77. column = composePosition(columns, column);
  78. if (row !== null && column !== null) {
  79. const newPosition = stringifyCellIdentity(row, column);
  80. reindexedCells[newPosition] = cells[identity];
  81. }
  82. }, false);
  83. return reindexedCells;
  84. };
  85. export const tableHandler = {
  86. compose(a, b, keepNull) {
  87. const rows = new Delta(a.rows || []).compose(new Delta(b.rows || []));
  88. const columns = new Delta(a.columns || []).compose(new Delta(b.columns || []));
  89. const cells = reindexCellIdentities(a.cells || {}, {
  90. rows: new Delta(b.rows || []),
  91. columns: new Delta(b.columns || [])
  92. });
  93. Object.keys(b.cells || {}).forEach(identity => {
  94. const aCell = cells[identity] || {};
  95. // @ts-expect-error Fix me later
  96. const bCell = b.cells[identity];
  97. const content = new Delta(aCell.content || []).compose(new Delta(bCell.content || []));
  98. const attributes = Delta.AttributeMap.compose(aCell.attributes, bCell.attributes, keepNull);
  99. const cell = compactCellData({
  100. content,
  101. attributes
  102. });
  103. if (cell) {
  104. cells[identity] = cell;
  105. } else {
  106. delete cells[identity];
  107. }
  108. });
  109. return compactTableData({
  110. rows,
  111. columns,
  112. cells
  113. });
  114. },
  115. transform(a, b, priority) {
  116. const aDeltas = {
  117. rows: new Delta(a.rows || []),
  118. columns: new Delta(a.columns || [])
  119. };
  120. const bDeltas = {
  121. rows: new Delta(b.rows || []),
  122. columns: new Delta(b.columns || [])
  123. };
  124. const rows = aDeltas.rows.transform(bDeltas.rows, priority);
  125. const columns = aDeltas.columns.transform(bDeltas.columns, priority);
  126. const cells = reindexCellIdentities(b.cells || {}, {
  127. rows: bDeltas.rows.transform(aDeltas.rows, !priority),
  128. columns: bDeltas.columns.transform(aDeltas.columns, !priority)
  129. });
  130. Object.keys(a.cells || {}).forEach(identity => {
  131. let [row, column] = parseCellIdentity(identity);
  132. // @ts-expect-error Fix me later
  133. row = composePosition(rows, row);
  134. // @ts-expect-error Fix me later
  135. column = composePosition(columns, column);
  136. if (row !== null && column !== null) {
  137. const newIdentity = stringifyCellIdentity(row, column);
  138. // @ts-expect-error Fix me later
  139. const aCell = a.cells[identity];
  140. const bCell = cells[newIdentity];
  141. if (bCell) {
  142. const content = new Delta(aCell.content || []).transform(new Delta(bCell.content || []), priority);
  143. const attributes = Delta.AttributeMap.transform(aCell.attributes, bCell.attributes, priority);
  144. const cell = compactCellData({
  145. content,
  146. attributes
  147. });
  148. if (cell) {
  149. cells[newIdentity] = cell;
  150. } else {
  151. delete cells[newIdentity];
  152. }
  153. }
  154. }
  155. });
  156. return compactTableData({
  157. rows,
  158. columns,
  159. cells
  160. });
  161. },
  162. invert(change, base) {
  163. const rows = new Delta(change.rows || []).invert(new Delta(base.rows || []));
  164. const columns = new Delta(change.columns || []).invert(new Delta(base.columns || []));
  165. const cells = reindexCellIdentities(change.cells || {}, {
  166. rows,
  167. columns
  168. });
  169. Object.keys(cells).forEach(identity => {
  170. const changeCell = cells[identity] || {};
  171. const baseCell = (base.cells || {})[identity] || {};
  172. const content = new Delta(changeCell.content || []).invert(new Delta(baseCell.content || []));
  173. const attributes = Delta.AttributeMap.invert(changeCell.attributes, baseCell.attributes);
  174. const cell = compactCellData({
  175. content,
  176. attributes
  177. });
  178. if (cell) {
  179. cells[identity] = cell;
  180. } else {
  181. delete cells[identity];
  182. }
  183. });
  184. // Cells may be removed when their row or column is removed
  185. // by row/column deltas. We should add them back.
  186. Object.keys(base.cells || {}).forEach(identity => {
  187. const [row, column] = parseCellIdentity(identity);
  188. if (composePosition(new Delta(change.rows || []), row) === null || composePosition(new Delta(change.columns || []), column) === null) {
  189. // @ts-expect-error Fix me later
  190. cells[identity] = base.cells[identity];
  191. }
  192. });
  193. return compactTableData({
  194. rows,
  195. columns,
  196. cells
  197. });
  198. }
  199. };
  200. class TableEmbed extends Module {
  201. static register() {
  202. Delta.registerEmbed('table-embed', tableHandler);
  203. }
  204. }
  205. export default TableEmbed;
  206. //# sourceMappingURL=tableEmbed.js.map