sharejs.js 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420
  1. import CryptoJSSHA1 from 'crypto-js/sha1'
  2. import { debugging, debugConsole } from '@/utils/debugging'
  3. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  4. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  5. var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
  6. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  7. /* eslint-disable
  8. camelcase,
  9. max-len,
  10. no-class-assign,
  11. no-return-assign,
  12. no-undef,
  13. no-unused-vars,
  14. no-use-before-define,
  15. standard/object-curly-even-spacing,
  16. */
  17. // TODO: This file was created by bulk-decaffeinate.
  18. // Fix any style issues and re-enable lint.
  19. /*
  20. * decaffeinate suggestions:
  21. * DS101: Remove unnecessary use of Array.from
  22. * DS102: Remove unnecessary code created because of implicit returns
  23. * DS205: Consider reworking code to avoid use of IIFEs
  24. * DS207: Consider shorter variations of null checks
  25. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  26. */
  27. export const { Doc } = (() => {
  28. var append = void 0,
  29. bootstrapTransform = void 0,
  30. exports = void 0,
  31. transformComponent = void 0;
  32. var WEB = true;
  33. window.sharejs = exports = {};
  34. var types = exports.types = {};
  35. // These methods let you build a transform function from a transformComponent function
  36. // for OT types like text and JSON in which operations are lists of components
  37. // and transforming them requires N^2 work.
  38. // Add transform and transformX functions for an OT type which has transformComponent defined.
  39. // transformComponent(destination array, component, other component, side)
  40. exports['_bt'] = bootstrapTransform = function bootstrapTransform(type, transformComponent, checkValidOp, append) {
  41. var _transformX = void 0;
  42. var transformComponentX = function transformComponentX(left, right, destLeft, destRight) {
  43. transformComponent(destLeft, left, right, 'left');
  44. return transformComponent(destRight, right, left, 'right');
  45. };
  46. // Transforms rightOp by leftOp. Returns ['rightOp', clientOp']
  47. type.transformX = type['transformX'] = _transformX = function transformX(leftOp, rightOp) {
  48. checkValidOp(leftOp);
  49. checkValidOp(rightOp);
  50. var newRightOp = [];
  51. var _iteratorNormalCompletion = true;
  52. var _didIteratorError = false;
  53. var _iteratorError = undefined;
  54. try {
  55. for (var _iterator = Array.from(rightOp)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
  56. var rightComponent = _step.value;
  57. // Generate newLeftOp by composing leftOp by rightComponent
  58. var newLeftOp = [];
  59. var k = 0;
  60. while (k < leftOp.length) {
  61. var l;
  62. var nextC = [];
  63. transformComponentX(leftOp[k], rightComponent, newLeftOp, nextC);
  64. k++;
  65. if (nextC.length === 1) {
  66. rightComponent = nextC[0];
  67. } else if (nextC.length === 0) {
  68. var _iteratorNormalCompletion2 = true;
  69. var _didIteratorError2 = false;
  70. var _iteratorError2 = undefined;
  71. try {
  72. for (var _iterator2 = Array.from(leftOp.slice(k))[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
  73. l = _step2.value;
  74. append(newLeftOp, l);
  75. }
  76. } catch (err) {
  77. _didIteratorError2 = true;
  78. _iteratorError2 = err;
  79. } finally {
  80. try {
  81. if (!_iteratorNormalCompletion2 && _iterator2.return) {
  82. _iterator2.return();
  83. }
  84. } finally {
  85. if (_didIteratorError2) {
  86. throw _iteratorError2;
  87. }
  88. }
  89. }
  90. rightComponent = null;
  91. break;
  92. } else {
  93. // Recurse.
  94. var _Array$from = Array.from(_transformX(leftOp.slice(k), nextC)),
  95. _Array$from2 = _slicedToArray(_Array$from, 2),
  96. l_ = _Array$from2[0],
  97. r_ = _Array$from2[1];
  98. var _iteratorNormalCompletion3 = true;
  99. var _didIteratorError3 = false;
  100. var _iteratorError3 = undefined;
  101. try {
  102. for (var _iterator3 = Array.from(l_)[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
  103. l = _step3.value;
  104. append(newLeftOp, l);
  105. }
  106. } catch (err) {
  107. _didIteratorError3 = true;
  108. _iteratorError3 = err;
  109. } finally {
  110. try {
  111. if (!_iteratorNormalCompletion3 && _iterator3.return) {
  112. _iterator3.return();
  113. }
  114. } finally {
  115. if (_didIteratorError3) {
  116. throw _iteratorError3;
  117. }
  118. }
  119. }
  120. var _iteratorNormalCompletion4 = true;
  121. var _didIteratorError4 = false;
  122. var _iteratorError4 = undefined;
  123. try {
  124. for (var _iterator4 = Array.from(r_)[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
  125. var r = _step4.value;
  126. append(newRightOp, r);
  127. }
  128. } catch (err) {
  129. _didIteratorError4 = true;
  130. _iteratorError4 = err;
  131. } finally {
  132. try {
  133. if (!_iteratorNormalCompletion4 && _iterator4.return) {
  134. _iterator4.return();
  135. }
  136. } finally {
  137. if (_didIteratorError4) {
  138. throw _iteratorError4;
  139. }
  140. }
  141. }
  142. rightComponent = null;
  143. break;
  144. }
  145. }
  146. if (rightComponent != null) {
  147. append(newRightOp, rightComponent);
  148. }
  149. leftOp = newLeftOp;
  150. }
  151. } catch (err) {
  152. _didIteratorError = true;
  153. _iteratorError = err;
  154. } finally {
  155. try {
  156. if (!_iteratorNormalCompletion && _iterator.return) {
  157. _iterator.return();
  158. }
  159. } finally {
  160. if (_didIteratorError) {
  161. throw _iteratorError;
  162. }
  163. }
  164. }
  165. return [leftOp, newRightOp];
  166. };
  167. // Transforms op with specified type ('left' or 'right') by otherOp.
  168. return type.transform = type['transform'] = function (op, otherOp, type) {
  169. var _ = void 0;
  170. if (type !== 'left' && type !== 'right') {
  171. throw new Error("type must be 'left' or 'right'");
  172. }
  173. if (otherOp.length === 0) {
  174. return op;
  175. }
  176. // TODO: Benchmark with and without this line. I _think_ it'll make a big difference...?
  177. if (op.length === 1 && otherOp.length === 1) {
  178. return transformComponent([], op[0], otherOp[0], type);
  179. }
  180. if (type === 'left') {
  181. var left = void 0;
  182. var _Array$from3 = Array.from(_transformX(op, otherOp));
  183. var _Array$from4 = _slicedToArray(_Array$from3, 2);
  184. left = _Array$from4[0];
  185. _ = _Array$from4[1];
  186. return left;
  187. } else {
  188. var right = void 0;
  189. var _Array$from5 = Array.from(_transformX(otherOp, op));
  190. var _Array$from6 = _slicedToArray(_Array$from5, 2);
  191. _ = _Array$from6[0];
  192. right = _Array$from6[1];
  193. return right;
  194. }
  195. };
  196. };
  197. // A simple text implementation
  198. //
  199. // Operations are lists of components.
  200. // Each component either inserts or deletes at a specified position in the document.
  201. //
  202. // Components are either:
  203. // {i:'str', p:100}: Insert 'str' at position 100 in the document
  204. // {d:'str', p:100}: Delete 'str' at position 100 in the document
  205. //
  206. // Components in an operation are executed sequentially, so the position of components
  207. // assumes previous components have already executed.
  208. //
  209. // Eg: This op:
  210. // [{i:'abc', p:0}]
  211. // is equivalent to this op:
  212. // [{i:'a', p:0}, {i:'b', p:1}, {i:'c', p:2}]
  213. // NOTE: The global scope here is shared with other sharejs files when built with closure.
  214. // Be careful what ends up in your namespace.
  215. var text = {};
  216. text.name = 'text';
  217. text.create = function () {
  218. return '';
  219. };
  220. var strInject = function strInject(s1, pos, s2) {
  221. return s1.slice(0, pos) + s2 + s1.slice(pos);
  222. };
  223. var checkValidComponent = function checkValidComponent(c) {
  224. if (typeof c.p !== 'number') {
  225. throw new Error('component missing position field');
  226. }
  227. var i_type = _typeof(c.i);
  228. var d_type = _typeof(c.d);
  229. var c_type = _typeof(c.c);
  230. if (!(i_type === 'string' ^ d_type === 'string' ^ c_type === 'string')) {
  231. throw new Error('component needs an i, d or c field');
  232. }
  233. if (!(c.p >= 0)) {
  234. throw new Error('position cannot be negative');
  235. }
  236. };
  237. var checkValidOp = function checkValidOp(op) {
  238. var _iteratorNormalCompletion5 = true;
  239. var _didIteratorError5 = false;
  240. var _iteratorError5 = undefined;
  241. try {
  242. for (var _iterator5 = Array.from(op)[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
  243. var c = _step5.value;
  244. checkValidComponent(c);
  245. }
  246. } catch (err) {
  247. _didIteratorError5 = true;
  248. _iteratorError5 = err;
  249. } finally {
  250. try {
  251. if (!_iteratorNormalCompletion5 && _iterator5.return) {
  252. _iterator5.return();
  253. }
  254. } finally {
  255. if (_didIteratorError5) {
  256. throw _iteratorError5;
  257. }
  258. }
  259. }
  260. return true;
  261. };
  262. text.apply = function (snapshot, op) {
  263. checkValidOp(op);
  264. var _iteratorNormalCompletion6 = true;
  265. var _didIteratorError6 = false;
  266. var _iteratorError6 = undefined;
  267. try {
  268. for (var _iterator6 = Array.from(op)[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
  269. var component = _step6.value;
  270. if (component.i != null) {
  271. snapshot = strInject(snapshot, component.p, component.i);
  272. } else if (component.d != null) {
  273. var deleted = snapshot.slice(component.p, component.p + component.d.length);
  274. if (component.d !== deleted) {
  275. throw new Error('Delete component \'' + component.d + '\' does not match deleted text \'' + deleted + '\'');
  276. }
  277. snapshot = snapshot.slice(0, component.p) + snapshot.slice(component.p + component.d.length);
  278. } else if (component.c != null) {
  279. var comment = snapshot.slice(component.p, component.p + component.c.length);
  280. if (component.c !== comment) {
  281. throw new Error('Comment component \'' + component.c + '\' does not match commented text \'' + comment + '\'');
  282. }
  283. } else {
  284. throw new Error('Unknown op type');
  285. }
  286. }
  287. } catch (err) {
  288. _didIteratorError6 = true;
  289. _iteratorError6 = err;
  290. } finally {
  291. try {
  292. if (!_iteratorNormalCompletion6 && _iterator6.return) {
  293. _iterator6.return();
  294. }
  295. } finally {
  296. if (_didIteratorError6) {
  297. throw _iteratorError6;
  298. }
  299. }
  300. }
  301. return snapshot;
  302. };
  303. var cloneAndModify = function cloneAndModify(op, modifications) {
  304. var v = void 0;
  305. var newOp = {};
  306. for (var k in op) {
  307. v = op[k];
  308. newOp[k] = v;
  309. }
  310. for (k in modifications) {
  311. v = modifications[k];
  312. newOp[k] = v;
  313. }
  314. return newOp;
  315. };
  316. // Exported for use by the random op generator.
  317. //
  318. // For simplicity, this version of append does not compress adjacent inserts and deletes of
  319. // the same text. It would be nice to change that at some stage.
  320. text._append = append = function append(newOp, c) {
  321. if (c.i === '' || c.d === '') {
  322. return;
  323. }
  324. if (newOp.length === 0) {
  325. return newOp.push(c);
  326. } else {
  327. var last = newOp[newOp.length - 1];
  328. // Compose the insert into the previous insert if possible
  329. if (last.i != null && c.i != null && last.p <= c.p && c.p <= last.p + last.i.length && last.u === c.u) {
  330. return newOp[newOp.length - 1] = cloneAndModify(last, { i: strInject(last.i, c.p - last.p, c.i) });
  331. } else if (last.d != null && c.d != null && c.p <= last.p && last.p <= c.p + c.d.length && last.u === c.u) {
  332. return newOp[newOp.length - 1] = cloneAndModify(last, { d: strInject(c.d, last.p - c.p, last.d), p: c.p });
  333. } else {
  334. return newOp.push(c);
  335. }
  336. }
  337. };
  338. text.compose = function (op1, op2) {
  339. checkValidOp(op1);
  340. checkValidOp(op2);
  341. var newOp = op1.slice();
  342. var _iteratorNormalCompletion7 = true;
  343. var _didIteratorError7 = false;
  344. var _iteratorError7 = undefined;
  345. try {
  346. for (var _iterator7 = Array.from(op2)[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {
  347. var c = _step7.value;
  348. append(newOp, c);
  349. }
  350. } catch (err) {
  351. _didIteratorError7 = true;
  352. _iteratorError7 = err;
  353. } finally {
  354. try {
  355. if (!_iteratorNormalCompletion7 && _iterator7.return) {
  356. _iterator7.return();
  357. }
  358. } finally {
  359. if (_didIteratorError7) {
  360. throw _iteratorError7;
  361. }
  362. }
  363. }
  364. return newOp;
  365. };
  366. // Attempt to compress the op components together 'as much as possible'.
  367. // This implementation preserves order and preserves create/delete pairs.
  368. text.compress = function (op) {
  369. return text.compose([], op);
  370. };
  371. text.normalize = function (op) {
  372. var newOp = [];
  373. // Normalize should allow ops which are a single (unwrapped) component:
  374. // {i:'asdf', p:23}.
  375. // There's no good way to test if something is an array:
  376. // http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/
  377. // so this is probably the least bad solution.
  378. if (op.i != null || op.p != null) {
  379. op = [op];
  380. }
  381. var _iteratorNormalCompletion8 = true;
  382. var _didIteratorError8 = false;
  383. var _iteratorError8 = undefined;
  384. try {
  385. for (var _iterator8 = Array.from(op)[Symbol.iterator](), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) {
  386. var c = _step8.value;
  387. if (c.p == null) {
  388. c.p = 0;
  389. }
  390. append(newOp, c);
  391. }
  392. } catch (err) {
  393. _didIteratorError8 = true;
  394. _iteratorError8 = err;
  395. } finally {
  396. try {
  397. if (!_iteratorNormalCompletion8 && _iterator8.return) {
  398. _iterator8.return();
  399. }
  400. } finally {
  401. if (_didIteratorError8) {
  402. throw _iteratorError8;
  403. }
  404. }
  405. }
  406. return newOp;
  407. };
  408. // This helper method transforms a position by an op component.
  409. //
  410. // If c is an insert, insertAfter specifies whether the transform
  411. // is pushed after the insert (true) or before it (false).
  412. //
  413. // insertAfter is optional for deletes.
  414. var transformPosition = function transformPosition(pos, c, insertAfter) {
  415. if (c.i != null) {
  416. if (c.p < pos || c.p === pos && insertAfter) {
  417. return pos + c.i.length;
  418. } else {
  419. return pos;
  420. }
  421. } else if (c.d != null) {
  422. // I think this could also be written as: Math.min(c.p, Math.min(c.p - otherC.p, otherC.d.length))
  423. // but I think its harder to read that way, and it compiles using ternary operators anyway
  424. // so its no slower written like this.
  425. if (pos <= c.p) {
  426. return pos;
  427. } else if (pos <= c.p + c.d.length) {
  428. return c.p;
  429. } else {
  430. return pos - c.d.length;
  431. }
  432. } else if (c.c != null) {
  433. return pos;
  434. } else {
  435. throw new Error('unknown op type');
  436. }
  437. };
  438. // Helper method to transform a cursor position as a result of an op.
  439. //
  440. // Like transformPosition above, if c is an insert, insertAfter specifies whether the cursor position
  441. // is pushed after an insert (true) or before it (false).
  442. text.transformCursor = function (position, op, side) {
  443. var insertAfter = side === 'right';
  444. var _iteratorNormalCompletion9 = true;
  445. var _didIteratorError9 = false;
  446. var _iteratorError9 = undefined;
  447. try {
  448. for (var _iterator9 = Array.from(op)[Symbol.iterator](), _step9; !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done); _iteratorNormalCompletion9 = true) {
  449. var c = _step9.value;
  450. position = transformPosition(position, c, insertAfter);
  451. }
  452. } catch (err) {
  453. _didIteratorError9 = true;
  454. _iteratorError9 = err;
  455. } finally {
  456. try {
  457. if (!_iteratorNormalCompletion9 && _iterator9.return) {
  458. _iterator9.return();
  459. }
  460. } finally {
  461. if (_didIteratorError9) {
  462. throw _iteratorError9;
  463. }
  464. }
  465. }
  466. return position;
  467. };
  468. // Transform an op component by another op component. Asymmetric.
  469. // The result will be appended to destination.
  470. //
  471. // exported for use in JSON type
  472. text._tc = transformComponent = function transformComponent(dest, c, otherC, side) {
  473. var cIntersect = void 0,
  474. intersectEnd = void 0,
  475. intersectStart = void 0,
  476. newC = void 0,
  477. otherIntersect = void 0;
  478. checkValidOp([c]);
  479. checkValidOp([otherC]);
  480. if (c.i != null) {
  481. append(dest, cloneAndModify(c, { p: transformPosition(c.p, otherC, side === 'right') }));
  482. } else if (c.d != null) {
  483. // Delete
  484. if (otherC.i != null) {
  485. // delete vs insert
  486. var s = c.d;
  487. if (c.p < otherC.p) {
  488. append(dest, cloneAndModify(c, { d: s.slice(0, otherC.p - c.p) }));
  489. s = s.slice(otherC.p - c.p);
  490. }
  491. if (s !== '') {
  492. append(dest, cloneAndModify(c, { d: s, p: c.p + otherC.i.length }));
  493. }
  494. } else if (otherC.d != null) {
  495. // Delete vs delete
  496. if (c.p >= otherC.p + otherC.d.length) {
  497. append(dest, cloneAndModify(c, { p: c.p - otherC.d.length }));
  498. } else if (c.p + c.d.length <= otherC.p) {
  499. append(dest, c);
  500. } else {
  501. // They overlap somewhere.
  502. newC = cloneAndModify(c, { d: '' });
  503. if (c.p < otherC.p) {
  504. newC.d = c.d.slice(0, otherC.p - c.p);
  505. }
  506. if (c.p + c.d.length > otherC.p + otherC.d.length) {
  507. newC.d += c.d.slice(otherC.p + otherC.d.length - c.p);
  508. }
  509. // This is entirely optional - just for a check that the deleted
  510. // text in the two ops matches
  511. intersectStart = Math.max(c.p, otherC.p);
  512. intersectEnd = Math.min(c.p + c.d.length, otherC.p + otherC.d.length);
  513. cIntersect = c.d.slice(intersectStart - c.p, intersectEnd - c.p);
  514. otherIntersect = otherC.d.slice(intersectStart - otherC.p, intersectEnd - otherC.p);
  515. if (cIntersect !== otherIntersect) {
  516. throw new Error('Delete ops delete different text in the same region of the document');
  517. }
  518. if (newC.d !== '') {
  519. // This could be rewritten similarly to insert v delete, above.
  520. newC.p = transformPosition(newC.p, otherC);
  521. append(dest, newC);
  522. }
  523. }
  524. } else if (otherC.c != null) {
  525. append(dest, c);
  526. } else {
  527. throw new Error('unknown op type');
  528. }
  529. } else if (c.c != null) {
  530. // Comment
  531. if (otherC.i != null) {
  532. if (c.p < otherC.p && otherC.p < c.p + c.c.length) {
  533. var offset = otherC.p - c.p;
  534. var new_c = c.c.slice(0, +(offset - 1) + 1 || undefined) + otherC.i + c.c.slice(offset);
  535. append(dest, cloneAndModify(c, { c: new_c }));
  536. } else {
  537. append(dest, cloneAndModify(c, { p: transformPosition(c.p, otherC, true) }));
  538. }
  539. } else if (otherC.d != null) {
  540. if (c.p >= otherC.p + otherC.d.length) {
  541. append(dest, cloneAndModify(c, { p: c.p - otherC.d.length }));
  542. } else if (c.p + c.c.length <= otherC.p) {
  543. append(dest, c);
  544. } else {
  545. // Delete overlaps comment
  546. // They overlap somewhere.
  547. newC = cloneAndModify(c, { c: '' });
  548. if (c.p < otherC.p) {
  549. newC.c = c.c.slice(0, otherC.p - c.p);
  550. }
  551. if (c.p + c.c.length > otherC.p + otherC.d.length) {
  552. newC.c += c.c.slice(otherC.p + otherC.d.length - c.p);
  553. }
  554. // This is entirely optional - just for a check that the deleted
  555. // text in the two ops matches
  556. intersectStart = Math.max(c.p, otherC.p);
  557. intersectEnd = Math.min(c.p + c.c.length, otherC.p + otherC.d.length);
  558. cIntersect = c.c.slice(intersectStart - c.p, intersectEnd - c.p);
  559. otherIntersect = otherC.d.slice(intersectStart - otherC.p, intersectEnd - otherC.p);
  560. if (cIntersect !== otherIntersect) {
  561. throw new Error('Delete ops delete different text in the same region of the document');
  562. }
  563. newC.p = transformPosition(newC.p, otherC);
  564. append(dest, newC);
  565. }
  566. } else if (otherC.c != null) {
  567. append(dest, c);
  568. } else {
  569. throw new Error('unknown op type');
  570. }
  571. }
  572. return dest;
  573. };
  574. var invertComponent = function invertComponent(c) {
  575. if (c.i != null) {
  576. return { d: c.i, p: c.p };
  577. } else {
  578. return { i: c.d, p: c.p };
  579. }
  580. };
  581. // No need to use append for invert, because the components won't be able to
  582. // cancel with one another.
  583. text.invert = function (op) {
  584. return Array.from(op.slice().reverse()).map(function (c) {
  585. return invertComponent(c);
  586. });
  587. };
  588. if (WEB != null) {
  589. if (!exports.types) {
  590. exports.types = {};
  591. }
  592. // This is kind of awful - come up with a better way to hook this helper code up.
  593. bootstrapTransform(text, transformComponent, checkValidOp, append);
  594. // [] is used to prevent closure from renaming types.text
  595. exports.types.text = text;
  596. }
  597. // Text document API for text
  598. text.api = {
  599. provides: { text: true },
  600. // The number of characters in the string
  601. getLength: function getLength() {
  602. return this.snapshot.length;
  603. },
  604. // Get the text contents of a document
  605. getText: function getText() {
  606. return this.snapshot;
  607. },
  608. insert: function insert(pos, text, fromUndo, callback) {
  609. var op = { p: pos, i: text };
  610. if (fromUndo) {
  611. op.u = true;
  612. }
  613. op = [op];
  614. this.submitOp(op, callback);
  615. return op;
  616. },
  617. del: function del(pos, length, fromUndo, callback) {
  618. var op = { p: pos, d: this.snapshot.slice(pos, pos + length) };
  619. if (fromUndo) {
  620. op.u = true;
  621. }
  622. op = [op];
  623. this.submitOp(op, callback);
  624. return op;
  625. },
  626. _register: function _register() {
  627. return this.on('remoteop', function (op) {
  628. var _this = this;
  629. return function () {
  630. var result = [];
  631. var _iteratorNormalCompletion10 = true;
  632. var _didIteratorError10 = false;
  633. var _iteratorError10 = undefined;
  634. try {
  635. for (var _iterator10 = Array.from(op)[Symbol.iterator](), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) {
  636. var component = _step10.value;
  637. if (component.i !== undefined) {
  638. result.push(_this.emit('insert', component.p, component.i));
  639. } else if (component.d !== undefined) {
  640. result.push(_this.emit('delete', component.p, component.d));
  641. } else {
  642. result.push(undefined);
  643. }
  644. }
  645. } catch (err) {
  646. _didIteratorError10 = true;
  647. _iteratorError10 = err;
  648. } finally {
  649. try {
  650. if (!_iteratorNormalCompletion10 && _iterator10.return) {
  651. _iterator10.return();
  652. }
  653. } finally {
  654. if (_didIteratorError10) {
  655. throw _iteratorError10;
  656. }
  657. }
  658. }
  659. return result;
  660. }();
  661. });
  662. }
  663. };
  664. // This is a simple port of microevent.js to Coffeescript. I've changed the
  665. // function names to be consistent with node.js EventEmitter.
  666. //
  667. // microevent.js is copyright Jerome Etienne, and licensed under the MIT license:
  668. // https://github.com/jeromeetienne/microevent.js
  669. var nextTick = WEB != null ? function (fn) {
  670. return setTimeout(fn, 0);
  671. } : process['nextTick'];
  672. var MicroEvent = function () {
  673. function MicroEvent() {
  674. _classCallCheck(this, MicroEvent);
  675. }
  676. _createClass(MicroEvent, [{
  677. key: 'on',
  678. value: function on(event, fct) {
  679. if (!this._events) {
  680. this._events = {};
  681. }
  682. if (!this._events[event]) {
  683. this._events[event] = [];
  684. }
  685. this._events[event].push(fct);
  686. return this;
  687. }
  688. }, {
  689. key: 'removeListener',
  690. value: function removeListener(event, fct) {
  691. var _this2 = this;
  692. if (!this._events) {
  693. this._events = {};
  694. }
  695. var listeners = this._events[event] || (this._events[event] = []);
  696. // Sadly, there's no IE8- support for indexOf.
  697. var i = 0;
  698. while (i < listeners.length) {
  699. if (listeners[i] === fct) {
  700. listeners[i] = undefined;
  701. }
  702. i++;
  703. }
  704. nextTick(function () {
  705. return _this2._events[event] = Array.from(_this2._events[event]).filter(function (x) {
  706. return x;
  707. });
  708. });
  709. return this;
  710. }
  711. }, {
  712. key: 'emit',
  713. value: function emit(event) {
  714. if (!(this._events != null ? this._events[event] : undefined)) {
  715. return this;
  716. }
  717. for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  718. args[_key - 1] = arguments[_key];
  719. }
  720. var _iteratorNormalCompletion11 = true;
  721. var _didIteratorError11 = false;
  722. var _iteratorError11 = undefined;
  723. try {
  724. for (var _iterator11 = Array.from(this._events[event])[Symbol.iterator](), _step11; !(_iteratorNormalCompletion11 = (_step11 = _iterator11.next()).done); _iteratorNormalCompletion11 = true) {
  725. var fn = _step11.value;
  726. if (fn) {
  727. fn.apply(this, args);
  728. }
  729. }
  730. } catch (err) {
  731. _didIteratorError11 = true;
  732. _iteratorError11 = err;
  733. } finally {
  734. try {
  735. if (!_iteratorNormalCompletion11 && _iterator11.return) {
  736. _iterator11.return();
  737. }
  738. } finally {
  739. if (_didIteratorError11) {
  740. throw _iteratorError11;
  741. }
  742. }
  743. }
  744. return this;
  745. }
  746. }]);
  747. return MicroEvent;
  748. }();
  749. // mixin will delegate all MicroEvent.js function in the destination object
  750. MicroEvent.mixin = function (obj) {
  751. var proto = obj.prototype || obj;
  752. // Damn closure compiler :/
  753. proto.on = MicroEvent.prototype.on;
  754. proto.removeListener = MicroEvent.prototype.removeListener;
  755. proto.emit = MicroEvent.prototype.emit;
  756. return obj;
  757. };
  758. if (WEB == null) {
  759. module.exports = MicroEvent;
  760. }
  761. if (WEB != null) {
  762. exports.extendDoc = function (name, fn) {
  763. return Doc.prototype[name] = fn;
  764. };
  765. }
  766. // A Doc is a client's view on a sharejs document.
  767. //
  768. // Documents are created by calling Connection.open().
  769. //
  770. // Documents are event emitters - use doc.on(eventname, fn) to subscribe.
  771. //
  772. // Documents get mixed in with their type's API methods. So, you can .insert('foo', 0) into
  773. // a text document and stuff like that.
  774. //
  775. // Events:
  776. // - remoteop (op)
  777. // - changed (op)
  778. // - acknowledge (op)
  779. // - error
  780. // - open, closing, closed. 'closing' is not guaranteed to fire before closed.
  781. var Doc = function () {
  782. // connection is a Connection object.
  783. // name is the documents' docName.
  784. // data can optionally contain known document data, and initial open() call arguments:
  785. // {v[erson], snapshot={...}, type, create=true/false/undefined}
  786. // callback will be called once the document is first opened.
  787. function Doc(connection, name, openData) {
  788. _classCallCheck(this, Doc);
  789. // Any of these can be null / undefined at this stage.
  790. this.flush = this.flush.bind(this);
  791. this.setFlushDelay = this.setFlushDelay.bind(this);
  792. this.shout = this.shout.bind(this);
  793. this.connection = connection;
  794. this.name = name;
  795. if (!openData) {
  796. openData = {};
  797. }
  798. this.version = openData.v;
  799. this.snapshot = openData.snaphot;
  800. if (openData.type) {
  801. this._setType(openData.type);
  802. }
  803. this.state = 'closed';
  804. this.autoOpen = false;
  805. // Has the document already been created?
  806. this._create = openData.create;
  807. // The op that is currently roundtripping to the server, or null.
  808. //
  809. // When the connection reconnects, the inflight op is resubmitted.
  810. this.inflightOp = null;
  811. this.inflightCallbacks = [];
  812. // The auth ids which the client has previously used to attempt to send inflightOp. This is
  813. // usually empty.
  814. this.inflightSubmittedIds = [];
  815. // All ops that are waiting for the server to acknowledge @inflightOp
  816. this.pendingOp = null;
  817. this.pendingCallbacks = [];
  818. }
  819. // Transform a server op by a client op, and vice versa.
  820. _createClass(Doc, [{
  821. key: '_xf',
  822. value: function _xf(client, server) {
  823. if (this.type.transformX) {
  824. return this.type.transformX(client, server);
  825. } else {
  826. var client_ = this.type.transform(client, server, 'left');
  827. var server_ = this.type.transform(server, client, 'right');
  828. return [client_, server_];
  829. }
  830. }
  831. }, {
  832. key: '_otApply',
  833. value: function _otApply(docOp, isRemote, msg) {
  834. var oldSnapshot = this.snapshot;
  835. this.snapshot = this.type.apply(this.snapshot, docOp);
  836. // Its important that these event handlers are called with oldSnapshot.
  837. // The reason is that the OT type APIs might need to access the snapshots to
  838. // determine information about the received op.
  839. this.emit('change', docOp, oldSnapshot, msg);
  840. if (isRemote) {
  841. return this.emit('remoteop', docOp, oldSnapshot, msg);
  842. }
  843. }
  844. }, {
  845. key: '_connectionStateChanged',
  846. value: function _connectionStateChanged(state, data) {
  847. switch (state) {
  848. case 'disconnected':
  849. this.state = 'closed';
  850. // This is used by the server to make sure that when an op is resubmitted it
  851. // doesn't end up getting applied twice.
  852. if (this.inflightOp) {
  853. this.inflightSubmittedIds.push(this.connection.id);
  854. }
  855. this.emit('closed');
  856. break;
  857. case 'ok':
  858. // Might be able to do this when we're connecting... that would save a roundtrip.
  859. if (this.autoOpen) {
  860. this.open();
  861. }
  862. break;
  863. case 'stopped':
  864. if (typeof this._openCallback === 'function') {
  865. this._openCallback(data);
  866. }
  867. break;
  868. }
  869. return this.emit(state, data);
  870. }
  871. }, {
  872. key: '_setType',
  873. value: function _setType(type) {
  874. if (typeof type === 'string') {
  875. type = types[type];
  876. }
  877. if (!type || !type.compose) {
  878. throw new Error('Support for types without compose() is not implemented');
  879. }
  880. this.type = type;
  881. if (type.api) {
  882. for (var k in type.api) {
  883. var v = type.api[k];this[k] = v;
  884. }
  885. return typeof this._register === 'function' ? this._register() : undefined;
  886. } else {
  887. return this.provides = {};
  888. }
  889. }
  890. }, {
  891. key: '_onMessage',
  892. value: function _onMessage(msg) {
  893. // debugConsole.warn('s->c', msg)
  894. if (msg.open === true) {
  895. // The document has been successfully opened.
  896. this.state = 'open';
  897. this._create = false; // Don't try and create the document again next time open() is called.
  898. if (this.created == null) {
  899. this.created = !!msg.create;
  900. }
  901. if (msg.type) {
  902. this._setType(msg.type);
  903. }
  904. if (msg.create) {
  905. this.created = true;
  906. this.snapshot = this.type.create();
  907. } else {
  908. if (this.created !== true) {
  909. this.created = false;
  910. }
  911. if (msg.snapshot !== undefined) {
  912. this.snapshot = msg.snapshot;
  913. }
  914. }
  915. if (msg.v != null) {
  916. this.version = msg.v;
  917. }
  918. // Resend any previously queued operation.
  919. if (this.inflightOp) {
  920. var response = {
  921. doc: this.name,
  922. op: this.inflightOp,
  923. v: this.version
  924. };
  925. if (this.inflightSubmittedIds.length) {
  926. response.dupIfSource = this.inflightSubmittedIds;
  927. }
  928. this.connection.send(response);
  929. } else {
  930. this.flush();
  931. }
  932. this.emit('open');
  933. return typeof this._openCallback === 'function' ? this._openCallback(null) : undefined;
  934. } else if (msg.open === false) {
  935. // The document has either been closed, or an open request has failed.
  936. if (msg.error) {
  937. // An error occurred opening the document.
  938. debugConsole.error('Could not open document: ' + msg.error);
  939. this.emit('error', msg.error);
  940. if (typeof this._openCallback === 'function') {
  941. this._openCallback(msg.error);
  942. }
  943. }
  944. this.state = 'closed';
  945. this.emit('closed');
  946. if (typeof this._closeCallback === 'function') {
  947. this._closeCallback();
  948. }
  949. return this._closeCallback = null;
  950. } else if (msg.op === null && error === 'Op already submitted') {
  951. // We've tried to resend an op to the server, which has already been received successfully. Do nothing.
  952. // The op will be confirmed normally when we get the op itself was echoed back from the server
  953. // (handled below).
  954. } else if (msg.op === undefined && msg.v !== undefined || msg.op && Array.from(this.inflightSubmittedIds).includes(msg.meta.source)) {
  955. // Our inflight op has been acknowledged.
  956. var callback = void 0;
  957. var oldInflightOp = this.inflightOp;
  958. this.inflightOp = null;
  959. this.inflightSubmittedIds.length = 0;
  960. if (this.pendingOp === null) {
  961. // All ops are acked
  962. this.emit('saved');
  963. }
  964. var error = msg.error;
  965. if (error) {
  966. // The server has rejected an op from the client for some reason.
  967. // We'll send the error message to the user and roll back the change.
  968. //
  969. // If the server isn't going to allow edits anyway, we should probably
  970. // figure out some way to flag that (readonly:true in the open request?)
  971. if (this.type.invert) {
  972. var undo = this.type.invert(oldInflightOp);
  973. // Now we have to transform the undo operation by any server ops & pending ops
  974. if (this.pendingOp) {
  975. var _Array$from7 = Array.from(this._xf(this.pendingOp, undo));
  976. var _Array$from8 = _slicedToArray(_Array$from7, 2);
  977. this.pendingOp = _Array$from8[0];
  978. undo = _Array$from8[1];
  979. }
  980. // ... and apply it locally, reverting the changes.
  981. //
  982. // This call will also call @emit 'remoteop'. I'm still not 100% sure about this
  983. // functionality, because its really a local op. Basically, the problem is that
  984. // if the client's op is rejected by the server, the editor window should update
  985. // to reflect the undo.
  986. this._otApply(undo, true, msg);
  987. } else {
  988. this.emit('error', 'Op apply failed (' + error + ') and the op could not be reverted');
  989. }
  990. var _iteratorNormalCompletion12 = true;
  991. var _didIteratorError12 = false;
  992. var _iteratorError12 = undefined;
  993. try {
  994. for (var _iterator12 = Array.from(this.inflightCallbacks)[Symbol.iterator](), _step12; !(_iteratorNormalCompletion12 = (_step12 = _iterator12.next()).done); _iteratorNormalCompletion12 = true) {
  995. callback = _step12.value;
  996. callback(error);
  997. }
  998. } catch (err) {
  999. _didIteratorError12 = true;
  1000. _iteratorError12 = err;
  1001. } finally {
  1002. try {
  1003. if (!_iteratorNormalCompletion12 && _iterator12.return) {
  1004. _iterator12.return();
  1005. }
  1006. } finally {
  1007. if (_didIteratorError12) {
  1008. throw _iteratorError12;
  1009. }
  1010. }
  1011. }
  1012. } else {
  1013. // The op applied successfully.
  1014. // We may get multiple acks of the same message if we retried it,
  1015. // so its ok if we receive an ack for a version that we've already gone past.
  1016. // If so, just ignore it
  1017. if (msg.v < this.version) {
  1018. return;
  1019. }
  1020. if (msg.v !== this.version) {
  1021. throw new Error('Invalid version from server');
  1022. }
  1023. this.version++;
  1024. this.emit('acknowledge', oldInflightOp);
  1025. var _iteratorNormalCompletion13 = true;
  1026. var _didIteratorError13 = false;
  1027. var _iteratorError13 = undefined;
  1028. try {
  1029. for (var _iterator13 = Array.from(this.inflightCallbacks)[Symbol.iterator](), _step13; !(_iteratorNormalCompletion13 = (_step13 = _iterator13.next()).done); _iteratorNormalCompletion13 = true) {
  1030. callback = _step13.value;
  1031. callback(null, oldInflightOp);
  1032. }
  1033. } catch (err) {
  1034. _didIteratorError13 = true;
  1035. _iteratorError13 = err;
  1036. } finally {
  1037. try {
  1038. if (!_iteratorNormalCompletion13 && _iterator13.return) {
  1039. _iterator13.return();
  1040. }
  1041. } finally {
  1042. if (_didIteratorError13) {
  1043. throw _iteratorError13;
  1044. }
  1045. }
  1046. }
  1047. }
  1048. // Send the next op.
  1049. return this.delayedFlush();
  1050. } else if (msg.op) {
  1051. // We got a new op from the server.
  1052. // msg is {doc:, op:, v:}
  1053. // There is a bug in socket.io (produced on firefox 3.6) which causes messages
  1054. // to be duplicated sometimes.
  1055. // We'll just silently drop subsequent messages.
  1056. if (msg.v < this.version) {
  1057. return;
  1058. }
  1059. if (msg.doc !== this.name) {
  1060. return this.emit('error', 'Expected docName \'' + this.name + '\' but got ' + msg.doc);
  1061. }
  1062. if (msg.v !== this.version) {
  1063. return this.emit('error', 'Expected version ' + this.version + ' but got ' + msg.v);
  1064. }
  1065. // p "if: #{i @inflightOp} pending: #{i @pendingOp} doc '#{@snapshot}' op: #{i msg.op}"
  1066. var docOp = msg.op;
  1067. if (this.inflightOp !== null) {
  1068. var _Array$from9 = Array.from(this._xf(this.inflightOp, docOp));
  1069. var _Array$from10 = _slicedToArray(_Array$from9, 2);
  1070. this.inflightOp = _Array$from10[0];
  1071. docOp = _Array$from10[1];
  1072. }
  1073. if (this.pendingOp !== null) {
  1074. var _Array$from11 = Array.from(this._xf(this.pendingOp, docOp));
  1075. var _Array$from12 = _slicedToArray(_Array$from11, 2);
  1076. this.pendingOp = _Array$from12[0];
  1077. docOp = _Array$from12[1];
  1078. }
  1079. this.version++;
  1080. // Finally, apply the op to @snapshot and trigger any event listeners
  1081. return this._otApply(docOp, true, msg);
  1082. } else if (msg.meta) {
  1083. var _msg$meta = msg.meta,
  1084. path = _msg$meta.path,
  1085. value = _msg$meta.value;
  1086. switch (path != null ? path[0] : undefined) {
  1087. case 'shout':
  1088. return this.emit('shout', value);
  1089. default:
  1090. return debugConsole.warn('Unhandled meta op:', msg);
  1091. }
  1092. } else {
  1093. return debugConsole.warn('Unhandled document message:', msg);
  1094. }
  1095. }
  1096. // Send ops to the server, if appropriate.
  1097. //
  1098. // Only one op can be in-flight at a time, so if an op is already on its way then
  1099. // this method does nothing.
  1100. }, {
  1101. key: 'flush',
  1102. value: function flush() {
  1103. this.flushTimeout = null;
  1104. // console.log "CALLED FLUSH"
  1105. if (this.connection.state !== 'ok' || this.inflightOp !== null || this.pendingOp === null) {
  1106. return;
  1107. }
  1108. // Rotate null -> pending -> inflight
  1109. this.inflightOp = this.pendingOp;
  1110. this.inflightCallbacks = this.pendingCallbacks;
  1111. this.pendingOp = null;
  1112. this.pendingCallbacks = [];
  1113. this.emit('flipped_pending_to_inflight');
  1114. if (window.useShareJsHash || debugging) {
  1115. var now = Date.now()
  1116. var age = this.__lastSubmitTimestamp && (now - this.__lastSubmitTimestamp)
  1117. var RECOMPUTE_HASH_INTERVAL = 5000
  1118. // check the document hash regularly (but not if we have checked in the last 5 seconds)
  1119. var needToRecomputeHash = !this.__lastSubmitTimestamp || (age > RECOMPUTE_HASH_INTERVAL) || (age < 0)
  1120. if (needToRecomputeHash || debugging) {
  1121. // send git hash of current snapshot
  1122. var sha1 = CryptoJSSHA1("blob " + this.snapshot.length + "\x00" + this.snapshot).toString()
  1123. this.__lastSubmitTimestamp = now;
  1124. }
  1125. }
  1126. // console.log "SENDING OP TO SERVER", @inflightOp, @version
  1127. var lastVersion = this.__lastVersion;
  1128. this.__lastVersion = this.version;
  1129. return this.connection.send({ doc: this.name, op: this.inflightOp, v: this.version, lastV: lastVersion, hash: sha1});
  1130. }
  1131. // Submit an op to the server. The op maybe held for a little while before being sent, as only one
  1132. // op can be inflight at any time.
  1133. }, {
  1134. key: 'submitOp',
  1135. value: function submitOp(op, callback) {
  1136. if (this.type.normalize != null) {
  1137. op = this.type.normalize(op);
  1138. }
  1139. var oldSnapshot = this.snapshot;
  1140. // If this throws an exception, no changes should have been made to the doc
  1141. this.snapshot = this.type.apply(this.snapshot, op);
  1142. if (this.pendingOp !== null) {
  1143. this.pendingOp = this.type.compose(this.pendingOp, op);
  1144. } else {
  1145. this.pendingOp = op;
  1146. }
  1147. if (callback) {
  1148. this.pendingCallbacks.push(callback);
  1149. }
  1150. this.emit('change', op, oldSnapshot);
  1151. return this.delayedFlush();
  1152. }
  1153. }, {
  1154. key: 'delayedFlush',
  1155. value: function delayedFlush() {
  1156. if (this.flushTimeout == null) {
  1157. return this.flushTimeout = setTimeout(this.flush, this._flushDelay || 0);
  1158. }
  1159. }
  1160. }, {
  1161. key: 'setFlushDelay',
  1162. value: function setFlushDelay(delay) {
  1163. return this._flushDelay = delay;
  1164. }
  1165. }, {
  1166. key: 'shout',
  1167. value: function shout(msg) {
  1168. // Meta ops don't have to queue, they can go direct. Good/bad idea?
  1169. return this.connection.send({ doc: this.name, meta: { path: ['shout'], value: msg } });
  1170. }
  1171. // Open a document. The document starts closed.
  1172. }, {
  1173. key: 'open',
  1174. value: function open(callback) {
  1175. var _this3 = this;
  1176. this.autoOpen = true;
  1177. if (this.state !== 'closed') {
  1178. return;
  1179. }
  1180. var message = {
  1181. doc: this.name,
  1182. open: true
  1183. };
  1184. if (this.snapshot === undefined) {
  1185. message.snapshot = null;
  1186. }
  1187. if (this.type) {
  1188. message.type = this.type.name;
  1189. }
  1190. if (this.version != null) {
  1191. message.v = this.version;
  1192. }
  1193. if (this._create) {
  1194. message.create = true;
  1195. }
  1196. this.connection.send(message);
  1197. this.state = 'opening';
  1198. return this._openCallback = function (error) {
  1199. _this3._openCallback = null;
  1200. return typeof callback === 'function' ? callback(error) : undefined;
  1201. };
  1202. }
  1203. // Close a document.
  1204. }, {
  1205. key: 'close',
  1206. value: function close(callback) {
  1207. this.autoOpen = false;
  1208. if (this.state === 'closed') {
  1209. return typeof callback === 'function' ? callback() : undefined;
  1210. }
  1211. this.connection.send({ doc: this.name, open: false });
  1212. // Should this happen immediately or when we get open:false back from the server?
  1213. this.state = 'closed';
  1214. this.emit('closing');
  1215. return this._closeCallback = callback;
  1216. }
  1217. }]);
  1218. return Doc;
  1219. }();
  1220. // Make documents event emitters
  1221. MicroEvent.mixin(Doc);
  1222. exports.Doc = Doc;
  1223. return exports;
  1224. })()
  1225. export default window.sharejs