loose_leaf 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 37fd14f6f259b07014bf83e22f256491738d6a44
4
+ data.tar.gz: 908f93f8a735d94a554933f1f0ba4696e1486c7b
5
+ SHA512:
6
+ metadata.gz: 7d7fded0b64c6e35b3942e76848f1f986d11e258455c33f0c2446911409a5ddb6bb54723bb6069a26e41272c5999b44cece90fdcb954b3aea9beae8f22f7dd8c
7
+ data.tar.gz: 039596f3ea7fbdc0cdaf948de57ed4c107c4dc2cc546c1ba915e3044702ee7fda9ae147f072f5706eedbfc37e8c603913f88af795d0d2e259753414deab89d57
data/MIT-LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright 2015 Hayden Ball
2
+ Copyright 2016 Akira Takahashi
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,136 @@
1
+ # LooseLeaf [![Build Status](https://travis-ci.org/rike422/loose-leaf.svg?branch=master)](https://travis-ci.org/rike422/loose-leaf) [![Coverage Status](https://coveralls.io/repos/github/rike422/loose-leaf/badge.svg?branch=master)](https://coveralls.io/github/rike422/loose-leaf?branch=master) [![Code Climate](https://codeclimate.com/github/rike422/loose-leaf/badges/gpa.svg)](https://codeclimate.com/github/rike422/loose-leaf) [![Standard - JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)
2
+
3
+
4
+ LooseLeaf is a Rails Engine that allows Real-Time collaboration between users.
5
+
6
+ LooseLeaf is still a work in progress, and currently only text attributes may
7
+ be collaboratively text editor.
8
+
9
+ This project inspired by [Collabrate](https://github.com/ball-hayden/Collaborate)
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'together'
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ $ bundle
22
+
23
+ ## Getting Started
24
+
25
+ ### Prerequisites
26
+
27
+ You will need to have ActionCable set up. In particular, you will need an
28
+ `ApplicationCable::Channel` and `ApplicationCable::Connection`.
29
+
30
+ More information about setting up ActionCable can be found in its README.
31
+
32
+ ### Model Setup
33
+
34
+ ```ruby
35
+ class Document < ActiveRecord::Base
36
+ # Include the LooseLeaf::Document concern
37
+ include LooseLeaf::Document
38
+
39
+ # Choose which attributes may be edited collaboratively
40
+ collaborative_attributes :body, :title
41
+ end
42
+ ```
43
+
44
+ Adding `collaborative_attributes` will define an extra attribute on the model
45
+ prefixed with `collaborative_` (e.g `collaborative_body`). We must use that
46
+ over `body` whenever we wish to allow realtime collaboration.
47
+
48
+ Bear in mind that the `collaborative_` attributes are stored only in the Rails
49
+ cache. You must save these attributes where appropriate:
50
+
51
+ ```ruby
52
+ document = Document.first
53
+ document.body = document.collaborative_body
54
+ document.save!
55
+
56
+ # Or, using the commit_collaborative_attributes convenience method:
57
+
58
+ document.commit_collaborative_attributes(:body)
59
+ document.commit_collaborative_attributes(:body, :title)
60
+
61
+ ```
62
+
63
+ ### Channel Setup
64
+
65
+ You will need to set up a collaboration channel for each model that is being
66
+ collaboratively edited.
67
+
68
+ ```ruby
69
+ class DocumentChannel < LooseLeaf::CollaborationChannel
70
+ private
71
+
72
+ # Set the Model class that we are editing.
73
+ def collaborative_model
74
+ Document
75
+ end
76
+ end
77
+ ```
78
+
79
+ ### View
80
+
81
+ As mentioned in Model Setup, we must use `collaborative_` attributes over normal
82
+ attributes when getting the values of collaborative attributes:
83
+
84
+ ```erb
85
+ <%# app/views/documents/show.html.erb %>
86
+
87
+ <input id="title" type="text" value="<%= @document.collaborative_title %>">
88
+
89
+ <textarea id="body" rows="8" cols="40"><%= @document.collaborative_body %></textarea>
90
+
91
+ <%= link_to 'Back', documents_path %>
92
+
93
+ <script>
94
+ var documentId = <%= @document.id %>
95
+ </script>
96
+ ```
97
+
98
+ ### JavaScript
99
+
100
+ [![Standard - JavaScript Style Guide](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard)
101
+
102
+ #### Sprockets
103
+
104
+ Add `loose-leaf` to your `application.coffee` asset, after actionable:
105
+
106
+ ```coffeescript
107
+ #= require cable
108
+ #= require loose-leaf
109
+ ```
110
+
111
+ Then, wherever appropriate:
112
+
113
+ ```js
114
+
115
+ // Create a new ActionCable consumer
116
+ const cable = Cable.createConsumer('ws://localhost:28080')
117
+
118
+ // Set up our collaboration object. `documentId` is (as you may expect) the ID
119
+ // of the document that is being edited.
120
+ const looseLeaf = new LooseLeaf(cable, 'DocumentChannel', documentId)
121
+
122
+ // We now specify the two attributes we are editing.
123
+ collaborativeTitle = looseLeaf.addAttribute('title')
124
+ collaborativeBody = looseLeaf.addAttribute('body')
125
+
126
+ new LooseLeaf.Adapters.TextAreaAdapter(collaborativeTitle, '#title')
127
+ new LooseLeaf.Adapters.TextAreaAdapter(collaborativeBody, '#body')
128
+
129
+ ```
130
+
131
+ #### npm or yuan
132
+
133
+ ```
134
+ npm install loose-leaf
135
+ ```
136
+
data/Rakefile ADDED
@@ -0,0 +1,29 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ APP_RAKEFILE = File.expand_path('../spec/dummy/Rakefile', __FILE__)
8
+
9
+ require 'rdoc/task'
10
+
11
+ RDoc::Task.new(:rdoc) do |rdoc|
12
+ rdoc.rdoc_dir = 'rdoc'
13
+ rdoc.title = 'LooseLeaf'
14
+ rdoc.options << '--line-numbers'
15
+ rdoc.rdoc_files.include('README.md')
16
+ rdoc.rdoc_files.include('lib/**/*.rb')
17
+ end
18
+
19
+ require 'bundler/gem_tasks'
20
+
21
+ require 'rspec/core/rake_task'
22
+
23
+ load 'rails/tasks/engine.rake'
24
+ load 'rails/tasks/statistics.rake'
25
+
26
+ Bundler::GemHelper.install_tasks
27
+
28
+ RSpec::Core::RakeTask.new(:spec)
29
+ task default: [:spec, :lint]
@@ -0,0 +1,3408 @@
1
+ (function webpackUniversalModuleDefinition(root, factory) {
2
+ if(typeof exports === 'object' && typeof module === 'object')
3
+ module.exports = factory();
4
+ else if(typeof define === 'function' && define.amd)
5
+ define([], factory);
6
+ else if(typeof exports === 'object')
7
+ exports["LooseLeaf"] = factory();
8
+ else
9
+ root["LooseLeaf"] = factory();
10
+ })(this, function() {
11
+ return /******/ (function(modules) { // webpackBootstrap
12
+ /******/ // The module cache
13
+ /******/ var installedModules = {};
14
+
15
+ /******/ // The require function
16
+ /******/ function __webpack_require__(moduleId) {
17
+
18
+ /******/ // Check if module is in cache
19
+ /******/ if(installedModules[moduleId])
20
+ /******/ return installedModules[moduleId].exports;
21
+
22
+ /******/ // Create a new module (and put it into the cache)
23
+ /******/ var module = installedModules[moduleId] = {
24
+ /******/ exports: {},
25
+ /******/ id: moduleId,
26
+ /******/ loaded: false
27
+ /******/ };
28
+
29
+ /******/ // Execute the module function
30
+ /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
31
+
32
+ /******/ // Flag the module as loaded
33
+ /******/ module.loaded = true;
34
+
35
+ /******/ // Return the exports of the module
36
+ /******/ return module.exports;
37
+ /******/ }
38
+
39
+
40
+ /******/ // expose the modules object (__webpack_modules__)
41
+ /******/ __webpack_require__.m = modules;
42
+
43
+ /******/ // expose the module cache
44
+ /******/ __webpack_require__.c = installedModules;
45
+
46
+ /******/ // __webpack_public_path__
47
+ /******/ __webpack_require__.p = "";
48
+
49
+ /******/ // Load entry module and return exports
50
+ /******/ return __webpack_require__(0);
51
+ /******/ })
52
+ /************************************************************************/
53
+ /******/ ([
54
+ /* 0 */
55
+ /***/ function(module, exports, __webpack_require__) {
56
+
57
+ 'use strict';
58
+
59
+ var _looseLeaf = __webpack_require__(1);
60
+
61
+ var _looseLeaf2 = _interopRequireDefault(_looseLeaf);
62
+
63
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
64
+
65
+ module.exports = _looseLeaf2.default; // weak
66
+
67
+ /***/ },
68
+ /* 1 */
69
+ /***/ function(module, exports, __webpack_require__) {
70
+
71
+ 'use strict';
72
+
73
+ Object.defineProperty(exports, "__esModule", {
74
+ value: true
75
+ });
76
+ exports.default = undefined;
77
+
78
+ 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; }; }();
79
+
80
+ var _class, _temp; // weak
81
+
82
+ var _attributeCable = __webpack_require__(2);
83
+
84
+ var _attributeCable2 = _interopRequireDefault(_attributeCable);
85
+
86
+ var _index = __webpack_require__(23);
87
+
88
+ var _index2 = _interopRequireDefault(_index);
89
+
90
+ var _cable = __webpack_require__(22);
91
+
92
+ var _cable2 = _interopRequireDefault(_cable);
93
+
94
+ var _collaborativeAttribute = __webpack_require__(16);
95
+
96
+ var _collaborativeAttribute2 = _interopRequireDefault(_collaborativeAttribute);
97
+
98
+ var _events = __webpack_require__(25);
99
+
100
+ var _events2 = _interopRequireDefault(_events);
101
+
102
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
103
+
104
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
105
+
106
+ var LooseLeaf = (_temp = _class = function () {
107
+ function LooseLeaf(cable, channel, documentId) {
108
+ _classCallCheck(this, LooseLeaf);
109
+
110
+ this.documentId = documentId;
111
+ this.cable = new _cable2.default(this, cable, channel);
112
+ this.attributes = {};
113
+ }
114
+
115
+ _createClass(LooseLeaf, [{
116
+ key: 'addAttribute',
117
+ value: function addAttribute(attribute) {
118
+ this.attributes[attribute] = new _collaborativeAttribute2.default(this, attribute);
119
+ return this.attributes[attribute];
120
+ }
121
+ }, {
122
+ key: 'destroy',
123
+ value: function destroy() {
124
+ Object.values(this.attributes).forEach(function (attribute) {
125
+ return attribute.destroy();
126
+ });
127
+ this.cable.destroy();
128
+ }
129
+ }]);
130
+
131
+ return LooseLeaf;
132
+ }(), _class.AttributeCable = _attributeCable2.default, _class.Adapters = _index2.default, _class.Cable = _cable2.default, _class.CollaborativeAttribute = _collaborativeAttribute2.default, _class.Events = _events2.default, _temp);
133
+ exports.default = LooseLeaf;
134
+ ;
135
+
136
+ /***/ },
137
+ /* 2 */
138
+ /***/ function(module, exports, __webpack_require__) {
139
+
140
+ 'use strict';
141
+
142
+ Object.defineProperty(exports, "__esModule", {
143
+ value: true
144
+ });
145
+ exports.default = undefined;
146
+
147
+ 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; }; }(); // weak
148
+
149
+ var _ot = __webpack_require__(3);
150
+
151
+ var _ot2 = _interopRequireDefault(_ot);
152
+
153
+ var _collaborativeAttribute = __webpack_require__(16);
154
+
155
+ var _collaborativeAttribute2 = _interopRequireDefault(_collaborativeAttribute);
156
+
157
+ var _cable = __webpack_require__(22);
158
+
159
+ var _cable2 = _interopRequireDefault(_cable);
160
+
161
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
162
+
163
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
164
+
165
+ var AttributeCable = function () {
166
+ function AttributeCable(collaborativeAttribute, cable, attribute) {
167
+ _classCallCheck(this, AttributeCable);
168
+
169
+ this.collaborativeAttribute = collaborativeAttribute;
170
+ this.cable = cable;
171
+ this.attribute = attribute;
172
+ this.unackedOps = [];
173
+ this.version = 0;
174
+ this.cable.addAttribute(this.attribute, this);
175
+ }
176
+
177
+ _createClass(AttributeCable, [{
178
+ key: 'destroy',
179
+ value: function destroy() {
180
+ this.cable.removeAttribute(this.attribute);
181
+ true;
182
+ }
183
+ }, {
184
+ key: 'receiveAttribute',
185
+ value: function receiveAttribute(data) {
186
+ this.version = data.version;
187
+ }
188
+ }, {
189
+ key: 'sendOperation',
190
+ value: function sendOperation(data) {
191
+ this.version++;
192
+ data.attribute = this.attribute;
193
+ data.version = this.version;
194
+
195
+ console.log('Send ' + this.attribute + ' version ' + data.version + ': ' + data.operation.toString());
196
+
197
+ this.unackedOps.push(data.version);
198
+ return this.cable.sendOperation(data);
199
+ }
200
+ }, {
201
+ key: 'receiveOperation',
202
+ value: function receiveOperation(data) {
203
+ data.operation = _ot2.default.TextOperation.fromJSON(data.operation);
204
+ this.version = data.version;
205
+
206
+ console.log('Receive ' + this.attribute + ' version ' + data.version + ': ' + data.operation.toString() + ' from ' + data.client_id);
207
+
208
+ if (data.client_id === this.cable.clientId) {
209
+ return this.receiveAck(data);
210
+ } else {
211
+ return this.receiveRemoteOperation(data);
212
+ }
213
+ }
214
+ }, {
215
+ key: 'receiveAck',
216
+ value: function receiveAck(data) {
217
+ var ackIndex = this.unackedOps.indexOf(data.sent_version);
218
+
219
+ if (ackIndex > -1) {
220
+ this.unackedOps.splice(ackIndex, 1);
221
+ this.collaborativeAttribute.receiveAck(data);
222
+ } else {
223
+ console.warn('Operation ' + data.sent_version + ' reAcked');
224
+ }
225
+ }
226
+ }, {
227
+ key: 'receiveRemoteOperation',
228
+ value: function receiveRemoteOperation(data) {
229
+ return this.collaborativeAttribute.remoteOperation(data);
230
+ }
231
+ }]);
232
+
233
+ return AttributeCable;
234
+ }();
235
+
236
+ exports.default = AttributeCable;
237
+ ;
238
+
239
+ /***/ },
240
+ /* 3 */
241
+ /***/ function(module, exports, __webpack_require__) {
242
+
243
+ exports.version = '0.0.15';
244
+
245
+ exports.TextOperation = __webpack_require__(4);
246
+ exports.SimpleTextOperation = __webpack_require__(5);
247
+ exports.Client = __webpack_require__(6);
248
+ exports.Server = __webpack_require__(7);
249
+ exports.Selection = __webpack_require__(8);
250
+ exports.EditorSocketIOServer = __webpack_require__(9);
251
+
252
+
253
+ /***/ },
254
+ /* 4 */
255
+ /***/ function(module, exports, __webpack_require__) {
256
+
257
+ if (typeof ot === 'undefined') {
258
+ // Export for browsers
259
+ var ot = {};
260
+ }
261
+
262
+ ot.TextOperation = (function () {
263
+ 'use strict';
264
+
265
+ // Constructor for new operations.
266
+ function TextOperation () {
267
+ if (!this || this.constructor !== TextOperation) {
268
+ // => function was called without 'new'
269
+ return new TextOperation();
270
+ }
271
+
272
+ // When an operation is applied to an input string, you can think of this as
273
+ // if an imaginary cursor runs over the entire string and skips over some
274
+ // parts, deletes some parts and inserts characters at some positions. These
275
+ // actions (skip/delete/insert) are stored as an array in the "ops" property.
276
+ this.ops = [];
277
+ // An operation's baseLength is the length of every string the operation
278
+ // can be applied to.
279
+ this.baseLength = 0;
280
+ // The targetLength is the length of every string that results from applying
281
+ // the operation on a valid input string.
282
+ this.targetLength = 0;
283
+ }
284
+
285
+ TextOperation.prototype.equals = function (other) {
286
+ if (this.baseLength !== other.baseLength) { return false; }
287
+ if (this.targetLength !== other.targetLength) { return false; }
288
+ if (this.ops.length !== other.ops.length) { return false; }
289
+ for (var i = 0; i < this.ops.length; i++) {
290
+ if (this.ops[i] !== other.ops[i]) { return false; }
291
+ }
292
+ return true;
293
+ };
294
+
295
+ // Operation are essentially lists of ops. There are three types of ops:
296
+ //
297
+ // * Retain ops: Advance the cursor position by a given number of characters.
298
+ // Represented by positive ints.
299
+ // * Insert ops: Insert a given string at the current cursor position.
300
+ // Represented by strings.
301
+ // * Delete ops: Delete the next n characters. Represented by negative ints.
302
+
303
+ var isRetain = TextOperation.isRetain = function (op) {
304
+ return typeof op === 'number' && op > 0;
305
+ };
306
+
307
+ var isInsert = TextOperation.isInsert = function (op) {
308
+ return typeof op === 'string';
309
+ };
310
+
311
+ var isDelete = TextOperation.isDelete = function (op) {
312
+ return typeof op === 'number' && op < 0;
313
+ };
314
+
315
+
316
+ // After an operation is constructed, the user of the library can specify the
317
+ // actions of an operation (skip/insert/delete) with these three builder
318
+ // methods. They all return the operation for convenient chaining.
319
+
320
+ // Skip over a given number of characters.
321
+ TextOperation.prototype.retain = function (n) {
322
+ if (typeof n !== 'number') {
323
+ throw new Error("retain expects an integer");
324
+ }
325
+ if (n === 0) { return this; }
326
+ this.baseLength += n;
327
+ this.targetLength += n;
328
+ if (isRetain(this.ops[this.ops.length-1])) {
329
+ // The last op is a retain op => we can merge them into one op.
330
+ this.ops[this.ops.length-1] += n;
331
+ } else {
332
+ // Create a new op.
333
+ this.ops.push(n);
334
+ }
335
+ return this;
336
+ };
337
+
338
+ // Insert a string at the current position.
339
+ TextOperation.prototype.insert = function (str) {
340
+ if (typeof str !== 'string') {
341
+ throw new Error("insert expects a string");
342
+ }
343
+ if (str === '') { return this; }
344
+ this.targetLength += str.length;
345
+ var ops = this.ops;
346
+ if (isInsert(ops[ops.length-1])) {
347
+ // Merge insert op.
348
+ ops[ops.length-1] += str;
349
+ } else if (isDelete(ops[ops.length-1])) {
350
+ // It doesn't matter when an operation is applied whether the operation
351
+ // is delete(3), insert("something") or insert("something"), delete(3).
352
+ // Here we enforce that in this case, the insert op always comes first.
353
+ // This makes all operations that have the same effect when applied to
354
+ // a document of the right length equal in respect to the `equals` method.
355
+ if (isInsert(ops[ops.length-2])) {
356
+ ops[ops.length-2] += str;
357
+ } else {
358
+ ops[ops.length] = ops[ops.length-1];
359
+ ops[ops.length-2] = str;
360
+ }
361
+ } else {
362
+ ops.push(str);
363
+ }
364
+ return this;
365
+ };
366
+
367
+ // Delete a string at the current position.
368
+ TextOperation.prototype['delete'] = function (n) {
369
+ if (typeof n === 'string') { n = n.length; }
370
+ if (typeof n !== 'number') {
371
+ throw new Error("delete expects an integer or a string");
372
+ }
373
+ if (n === 0) { return this; }
374
+ if (n > 0) { n = -n; }
375
+ this.baseLength -= n;
376
+ if (isDelete(this.ops[this.ops.length-1])) {
377
+ this.ops[this.ops.length-1] += n;
378
+ } else {
379
+ this.ops.push(n);
380
+ }
381
+ return this;
382
+ };
383
+
384
+ // Tests whether this operation has no effect.
385
+ TextOperation.prototype.isNoop = function () {
386
+ return this.ops.length === 0 || (this.ops.length === 1 && isRetain(this.ops[0]));
387
+ };
388
+
389
+ // Pretty printing.
390
+ TextOperation.prototype.toString = function () {
391
+ // map: build a new array by applying a function to every element in an old
392
+ // array.
393
+ var map = Array.prototype.map || function (fn) {
394
+ var arr = this;
395
+ var newArr = [];
396
+ for (var i = 0, l = arr.length; i < l; i++) {
397
+ newArr[i] = fn(arr[i]);
398
+ }
399
+ return newArr;
400
+ };
401
+ return map.call(this.ops, function (op) {
402
+ if (isRetain(op)) {
403
+ return "retain " + op;
404
+ } else if (isInsert(op)) {
405
+ return "insert '" + op + "'";
406
+ } else {
407
+ return "delete " + (-op);
408
+ }
409
+ }).join(', ');
410
+ };
411
+
412
+ // Converts operation into a JSON value.
413
+ TextOperation.prototype.toJSON = function () {
414
+ return this.ops;
415
+ };
416
+
417
+ // Converts a plain JS object into an operation and validates it.
418
+ TextOperation.fromJSON = function (ops) {
419
+ var o = new TextOperation();
420
+ for (var i = 0, l = ops.length; i < l; i++) {
421
+ var op = ops[i];
422
+ if (isRetain(op)) {
423
+ o.retain(op);
424
+ } else if (isInsert(op)) {
425
+ o.insert(op);
426
+ } else if (isDelete(op)) {
427
+ o['delete'](op);
428
+ } else {
429
+ throw new Error("unknown operation: " + JSON.stringify(op));
430
+ }
431
+ }
432
+ return o;
433
+ };
434
+
435
+ // Apply an operation to a string, returning a new string. Throws an error if
436
+ // there's a mismatch between the input string and the operation.
437
+ TextOperation.prototype.apply = function (str) {
438
+ var operation = this;
439
+ if (str.length !== operation.baseLength) {
440
+ throw new Error("The operation's base length must be equal to the string's length.");
441
+ }
442
+ var newStr = [], j = 0;
443
+ var strIndex = 0;
444
+ var ops = this.ops;
445
+ for (var i = 0, l = ops.length; i < l; i++) {
446
+ var op = ops[i];
447
+ if (isRetain(op)) {
448
+ if (strIndex + op > str.length) {
449
+ throw new Error("Operation can't retain more characters than are left in the string.");
450
+ }
451
+ // Copy skipped part of the old string.
452
+ newStr[j++] = str.slice(strIndex, strIndex + op);
453
+ strIndex += op;
454
+ } else if (isInsert(op)) {
455
+ // Insert string.
456
+ newStr[j++] = op;
457
+ } else { // delete op
458
+ strIndex -= op;
459
+ }
460
+ }
461
+ if (strIndex !== str.length) {
462
+ throw new Error("The operation didn't operate on the whole string.");
463
+ }
464
+ return newStr.join('');
465
+ };
466
+
467
+ // Computes the inverse of an operation. The inverse of an operation is the
468
+ // operation that reverts the effects of the operation, e.g. when you have an
469
+ // operation 'insert("hello "); skip(6);' then the inverse is 'delete("hello ");
470
+ // skip(6);'. The inverse should be used for implementing undo.
471
+ TextOperation.prototype.invert = function (str) {
472
+ var strIndex = 0;
473
+ var inverse = new TextOperation();
474
+ var ops = this.ops;
475
+ for (var i = 0, l = ops.length; i < l; i++) {
476
+ var op = ops[i];
477
+ if (isRetain(op)) {
478
+ inverse.retain(op);
479
+ strIndex += op;
480
+ } else if (isInsert(op)) {
481
+ inverse['delete'](op.length);
482
+ } else { // delete op
483
+ inverse.insert(str.slice(strIndex, strIndex - op));
484
+ strIndex -= op;
485
+ }
486
+ }
487
+ return inverse;
488
+ };
489
+
490
+ // Compose merges two consecutive operations into one operation, that
491
+ // preserves the changes of both. Or, in other words, for each input string S
492
+ // and a pair of consecutive operations A and B,
493
+ // apply(apply(S, A), B) = apply(S, compose(A, B)) must hold.
494
+ TextOperation.prototype.compose = function (operation2) {
495
+ var operation1 = this;
496
+ if (operation1.targetLength !== operation2.baseLength) {
497
+ throw new Error("The base length of the second operation has to be the target length of the first operation");
498
+ }
499
+
500
+ var operation = new TextOperation(); // the combined operation
501
+ var ops1 = operation1.ops, ops2 = operation2.ops; // for fast access
502
+ var i1 = 0, i2 = 0; // current index into ops1 respectively ops2
503
+ var op1 = ops1[i1++], op2 = ops2[i2++]; // current ops
504
+ while (true) {
505
+ // Dispatch on the type of op1 and op2
506
+ if (typeof op1 === 'undefined' && typeof op2 === 'undefined') {
507
+ // end condition: both ops1 and ops2 have been processed
508
+ break;
509
+ }
510
+
511
+ if (isDelete(op1)) {
512
+ operation['delete'](op1);
513
+ op1 = ops1[i1++];
514
+ continue;
515
+ }
516
+ if (isInsert(op2)) {
517
+ operation.insert(op2);
518
+ op2 = ops2[i2++];
519
+ continue;
520
+ }
521
+
522
+ if (typeof op1 === 'undefined') {
523
+ throw new Error("Cannot compose operations: first operation is too short.");
524
+ }
525
+ if (typeof op2 === 'undefined') {
526
+ throw new Error("Cannot compose operations: first operation is too long.");
527
+ }
528
+
529
+ if (isRetain(op1) && isRetain(op2)) {
530
+ if (op1 > op2) {
531
+ operation.retain(op2);
532
+ op1 = op1 - op2;
533
+ op2 = ops2[i2++];
534
+ } else if (op1 === op2) {
535
+ operation.retain(op1);
536
+ op1 = ops1[i1++];
537
+ op2 = ops2[i2++];
538
+ } else {
539
+ operation.retain(op1);
540
+ op2 = op2 - op1;
541
+ op1 = ops1[i1++];
542
+ }
543
+ } else if (isInsert(op1) && isDelete(op2)) {
544
+ if (op1.length > -op2) {
545
+ op1 = op1.slice(-op2);
546
+ op2 = ops2[i2++];
547
+ } else if (op1.length === -op2) {
548
+ op1 = ops1[i1++];
549
+ op2 = ops2[i2++];
550
+ } else {
551
+ op2 = op2 + op1.length;
552
+ op1 = ops1[i1++];
553
+ }
554
+ } else if (isInsert(op1) && isRetain(op2)) {
555
+ if (op1.length > op2) {
556
+ operation.insert(op1.slice(0, op2));
557
+ op1 = op1.slice(op2);
558
+ op2 = ops2[i2++];
559
+ } else if (op1.length === op2) {
560
+ operation.insert(op1);
561
+ op1 = ops1[i1++];
562
+ op2 = ops2[i2++];
563
+ } else {
564
+ operation.insert(op1);
565
+ op2 = op2 - op1.length;
566
+ op1 = ops1[i1++];
567
+ }
568
+ } else if (isRetain(op1) && isDelete(op2)) {
569
+ if (op1 > -op2) {
570
+ operation['delete'](op2);
571
+ op1 = op1 + op2;
572
+ op2 = ops2[i2++];
573
+ } else if (op1 === -op2) {
574
+ operation['delete'](op2);
575
+ op1 = ops1[i1++];
576
+ op2 = ops2[i2++];
577
+ } else {
578
+ operation['delete'](op1);
579
+ op2 = op2 + op1;
580
+ op1 = ops1[i1++];
581
+ }
582
+ } else {
583
+ throw new Error(
584
+ "This shouldn't happen: op1: " +
585
+ JSON.stringify(op1) + ", op2: " +
586
+ JSON.stringify(op2)
587
+ );
588
+ }
589
+ }
590
+ return operation;
591
+ };
592
+
593
+ function getSimpleOp (operation, fn) {
594
+ var ops = operation.ops;
595
+ var isRetain = TextOperation.isRetain;
596
+ switch (ops.length) {
597
+ case 1:
598
+ return ops[0];
599
+ case 2:
600
+ return isRetain(ops[0]) ? ops[1] : (isRetain(ops[1]) ? ops[0] : null);
601
+ case 3:
602
+ if (isRetain(ops[0]) && isRetain(ops[2])) { return ops[1]; }
603
+ }
604
+ return null;
605
+ }
606
+
607
+ function getStartIndex (operation) {
608
+ if (isRetain(operation.ops[0])) { return operation.ops[0]; }
609
+ return 0;
610
+ }
611
+
612
+ // When you use ctrl-z to undo your latest changes, you expect the program not
613
+ // to undo every single keystroke but to undo your last sentence you wrote at
614
+ // a stretch or the deletion you did by holding the backspace key down. This
615
+ // This can be implemented by composing operations on the undo stack. This
616
+ // method can help decide whether two operations should be composed. It
617
+ // returns true if the operations are consecutive insert operations or both
618
+ // operations delete text at the same position. You may want to include other
619
+ // factors like the time since the last change in your decision.
620
+ TextOperation.prototype.shouldBeComposedWith = function (other) {
621
+ if (this.isNoop() || other.isNoop()) { return true; }
622
+
623
+ var startA = getStartIndex(this), startB = getStartIndex(other);
624
+ var simpleA = getSimpleOp(this), simpleB = getSimpleOp(other);
625
+ if (!simpleA || !simpleB) { return false; }
626
+
627
+ if (isInsert(simpleA) && isInsert(simpleB)) {
628
+ return startA + simpleA.length === startB;
629
+ }
630
+
631
+ if (isDelete(simpleA) && isDelete(simpleB)) {
632
+ // there are two possibilities to delete: with backspace and with the
633
+ // delete key.
634
+ return (startB - simpleB === startA) || startA === startB;
635
+ }
636
+
637
+ return false;
638
+ };
639
+
640
+ // Decides whether two operations should be composed with each other
641
+ // if they were inverted, that is
642
+ // `shouldBeComposedWith(a, b) = shouldBeComposedWithInverted(b^{-1}, a^{-1})`.
643
+ TextOperation.prototype.shouldBeComposedWithInverted = function (other) {
644
+ if (this.isNoop() || other.isNoop()) { return true; }
645
+
646
+ var startA = getStartIndex(this), startB = getStartIndex(other);
647
+ var simpleA = getSimpleOp(this), simpleB = getSimpleOp(other);
648
+ if (!simpleA || !simpleB) { return false; }
649
+
650
+ if (isInsert(simpleA) && isInsert(simpleB)) {
651
+ return startA + simpleA.length === startB || startA === startB;
652
+ }
653
+
654
+ if (isDelete(simpleA) && isDelete(simpleB)) {
655
+ return startB - simpleB === startA;
656
+ }
657
+
658
+ return false;
659
+ };
660
+
661
+ // Transform takes two operations A and B that happened concurrently and
662
+ // produces two operations A' and B' (in an array) such that
663
+ // `apply(apply(S, A), B') = apply(apply(S, B), A')`. This function is the
664
+ // heart of OT.
665
+ TextOperation.transform = function (operation1, operation2) {
666
+ if (operation1.baseLength !== operation2.baseLength) {
667
+ throw new Error("Both operations have to have the same base length");
668
+ }
669
+
670
+ var operation1prime = new TextOperation();
671
+ var operation2prime = new TextOperation();
672
+ var ops1 = operation1.ops, ops2 = operation2.ops;
673
+ var i1 = 0, i2 = 0;
674
+ var op1 = ops1[i1++], op2 = ops2[i2++];
675
+ while (true) {
676
+ // At every iteration of the loop, the imaginary cursor that both
677
+ // operation1 and operation2 have that operates on the input string must
678
+ // have the same position in the input string.
679
+
680
+ if (typeof op1 === 'undefined' && typeof op2 === 'undefined') {
681
+ // end condition: both ops1 and ops2 have been processed
682
+ break;
683
+ }
684
+
685
+ // next two cases: one or both ops are insert ops
686
+ // => insert the string in the corresponding prime operation, skip it in
687
+ // the other one. If both op1 and op2 are insert ops, prefer op1.
688
+ if (isInsert(op1)) {
689
+ operation1prime.insert(op1);
690
+ operation2prime.retain(op1.length);
691
+ op1 = ops1[i1++];
692
+ continue;
693
+ }
694
+ if (isInsert(op2)) {
695
+ operation1prime.retain(op2.length);
696
+ operation2prime.insert(op2);
697
+ op2 = ops2[i2++];
698
+ continue;
699
+ }
700
+
701
+ if (typeof op1 === 'undefined') {
702
+ throw new Error("Cannot compose operations: first operation is too short.");
703
+ }
704
+ if (typeof op2 === 'undefined') {
705
+ throw new Error("Cannot compose operations: first operation is too long.");
706
+ }
707
+
708
+ var minl;
709
+ if (isRetain(op1) && isRetain(op2)) {
710
+ // Simple case: retain/retain
711
+ if (op1 > op2) {
712
+ minl = op2;
713
+ op1 = op1 - op2;
714
+ op2 = ops2[i2++];
715
+ } else if (op1 === op2) {
716
+ minl = op2;
717
+ op1 = ops1[i1++];
718
+ op2 = ops2[i2++];
719
+ } else {
720
+ minl = op1;
721
+ op2 = op2 - op1;
722
+ op1 = ops1[i1++];
723
+ }
724
+ operation1prime.retain(minl);
725
+ operation2prime.retain(minl);
726
+ } else if (isDelete(op1) && isDelete(op2)) {
727
+ // Both operations delete the same string at the same position. We don't
728
+ // need to produce any operations, we just skip over the delete ops and
729
+ // handle the case that one operation deletes more than the other.
730
+ if (-op1 > -op2) {
731
+ op1 = op1 - op2;
732
+ op2 = ops2[i2++];
733
+ } else if (op1 === op2) {
734
+ op1 = ops1[i1++];
735
+ op2 = ops2[i2++];
736
+ } else {
737
+ op2 = op2 - op1;
738
+ op1 = ops1[i1++];
739
+ }
740
+ // next two cases: delete/retain and retain/delete
741
+ } else if (isDelete(op1) && isRetain(op2)) {
742
+ if (-op1 > op2) {
743
+ minl = op2;
744
+ op1 = op1 + op2;
745
+ op2 = ops2[i2++];
746
+ } else if (-op1 === op2) {
747
+ minl = op2;
748
+ op1 = ops1[i1++];
749
+ op2 = ops2[i2++];
750
+ } else {
751
+ minl = -op1;
752
+ op2 = op2 + op1;
753
+ op1 = ops1[i1++];
754
+ }
755
+ operation1prime['delete'](minl);
756
+ } else if (isRetain(op1) && isDelete(op2)) {
757
+ if (op1 > -op2) {
758
+ minl = -op2;
759
+ op1 = op1 + op2;
760
+ op2 = ops2[i2++];
761
+ } else if (op1 === -op2) {
762
+ minl = op1;
763
+ op1 = ops1[i1++];
764
+ op2 = ops2[i2++];
765
+ } else {
766
+ minl = op1;
767
+ op2 = op2 + op1;
768
+ op1 = ops1[i1++];
769
+ }
770
+ operation2prime['delete'](minl);
771
+ } else {
772
+ throw new Error("The two operations aren't compatible");
773
+ }
774
+ }
775
+
776
+ return [operation1prime, operation2prime];
777
+ };
778
+
779
+ return TextOperation;
780
+
781
+ }());
782
+
783
+ // Export for CommonJS
784
+ if (true) {
785
+ module.exports = ot.TextOperation;
786
+ }
787
+
788
+ /***/ },
789
+ /* 5 */
790
+ /***/ function(module, exports, __webpack_require__) {
791
+
792
+ if (typeof ot === 'undefined') {
793
+ // Export for browsers
794
+ var ot = {};
795
+ }
796
+
797
+ ot.SimpleTextOperation = (function (global) {
798
+
799
+ var TextOperation = global.ot ? global.ot.TextOperation : __webpack_require__(4);
800
+
801
+ function SimpleTextOperation () {}
802
+
803
+
804
+ // Insert the string `str` at the zero-based `position` in the document.
805
+ function Insert (str, position) {
806
+ if (!this || this.constructor !== SimpleTextOperation) {
807
+ // => function was called without 'new'
808
+ return new Insert(str, position);
809
+ }
810
+ this.str = str;
811
+ this.position = position;
812
+ }
813
+
814
+ Insert.prototype = new SimpleTextOperation();
815
+ SimpleTextOperation.Insert = Insert;
816
+
817
+ Insert.prototype.toString = function () {
818
+ return 'Insert(' + JSON.stringify(this.str) + ', ' + this.position + ')';
819
+ };
820
+
821
+ Insert.prototype.equals = function (other) {
822
+ return other instanceof Insert &&
823
+ this.str === other.str &&
824
+ this.position === other.position;
825
+ };
826
+
827
+ Insert.prototype.apply = function (doc) {
828
+ return doc.slice(0, this.position) + this.str + doc.slice(this.position);
829
+ };
830
+
831
+
832
+ // Delete `count` many characters at the zero-based `position` in the document.
833
+ function Delete (count, position) {
834
+ if (!this || this.constructor !== SimpleTextOperation) {
835
+ return new Delete(count, position);
836
+ }
837
+ this.count = count;
838
+ this.position = position;
839
+ }
840
+
841
+ Delete.prototype = new SimpleTextOperation();
842
+ SimpleTextOperation.Delete = Delete;
843
+
844
+ Delete.prototype.toString = function () {
845
+ return 'Delete(' + this.count + ', ' + this.position + ')';
846
+ };
847
+
848
+ Delete.prototype.equals = function (other) {
849
+ return other instanceof Delete &&
850
+ this.count === other.count &&
851
+ this.position === other.position;
852
+ };
853
+
854
+ Delete.prototype.apply = function (doc) {
855
+ return doc.slice(0, this.position) + doc.slice(this.position + this.count);
856
+ };
857
+
858
+
859
+ // An operation that does nothing. This is needed for the result of the
860
+ // transformation of two deletions of the same character.
861
+ function Noop () {
862
+ if (!this || this.constructor !== SimpleTextOperation) { return new Noop(); }
863
+ }
864
+
865
+ Noop.prototype = new SimpleTextOperation();
866
+ SimpleTextOperation.Noop = Noop;
867
+
868
+ Noop.prototype.toString = function () {
869
+ return 'Noop()';
870
+ };
871
+
872
+ Noop.prototype.equals = function (other) { return other instanceof Noop; };
873
+
874
+ Noop.prototype.apply = function (doc) { return doc; };
875
+
876
+ var noop = new Noop();
877
+
878
+
879
+ SimpleTextOperation.transform = function (a, b) {
880
+ if (a instanceof Noop || b instanceof Noop) { return [a, b]; }
881
+
882
+ if (a instanceof Insert && b instanceof Insert) {
883
+ if (a.position < b.position || (a.position === b.position && a.str < b.str)) {
884
+ return [a, new Insert(b.str, b.position + a.str.length)];
885
+ }
886
+ if (a.position > b.position || (a.position === b.position && a.str > b.str)) {
887
+ return [new Insert(a.str, a.position + b.str.length), b];
888
+ }
889
+ return [noop, noop];
890
+ }
891
+
892
+ if (a instanceof Insert && b instanceof Delete) {
893
+ if (a.position <= b.position) {
894
+ return [a, new Delete(b.count, b.position + a.str.length)];
895
+ }
896
+ if (a.position >= b.position + b.count) {
897
+ return [new Insert(a.str, a.position - b.count), b];
898
+ }
899
+ // Here, we have to delete the inserted string of operation a.
900
+ // That doesn't preserve the intention of operation a, but it's the only
901
+ // thing we can do to get a valid transform function.
902
+ return [noop, new Delete(b.count + a.str.length, b.position)];
903
+ }
904
+
905
+ if (a instanceof Delete && b instanceof Insert) {
906
+ if (a.position >= b.position) {
907
+ return [new Delete(a.count, a.position + b.str.length), b];
908
+ }
909
+ if (a.position + a.count <= b.position) {
910
+ return [a, new Insert(b.str, b.position - a.count)];
911
+ }
912
+ // Same problem as above. We have to delete the string that was inserted
913
+ // in operation b.
914
+ return [new Delete(a.count + b.str.length, a.position), noop];
915
+ }
916
+
917
+ if (a instanceof Delete && b instanceof Delete) {
918
+ if (a.position === b.position) {
919
+ if (a.count === b.count) {
920
+ return [noop, noop];
921
+ } else if (a.count < b.count) {
922
+ return [noop, new Delete(b.count - a.count, b.position)];
923
+ }
924
+ return [new Delete(a.count - b.count, a.position), noop];
925
+ }
926
+ if (a.position < b.position) {
927
+ if (a.position + a.count <= b.position) {
928
+ return [a, new Delete(b.count, b.position - a.count)];
929
+ }
930
+ if (a.position + a.count >= b.position + b.count) {
931
+ return [new Delete(a.count - b.count, a.position), noop];
932
+ }
933
+ return [
934
+ new Delete(b.position - a.position, a.position),
935
+ new Delete(b.position + b.count - (a.position + a.count), a.position)
936
+ ];
937
+ }
938
+ if (a.position > b.position) {
939
+ if (a.position >= b.position + b.count) {
940
+ return [new Delete(a.count, a.position - b.count), b];
941
+ }
942
+ if (a.position + a.count <= b.position + b.count) {
943
+ return [noop, new Delete(b.count - a.count, b.position)];
944
+ }
945
+ return [
946
+ new Delete(a.position + a.count - (b.position + b.count), b.position),
947
+ new Delete(a.position - b.position, b.position)
948
+ ];
949
+ }
950
+ }
951
+ };
952
+
953
+ // Convert a normal, composable `TextOperation` into an array of
954
+ // `SimpleTextOperation`s.
955
+ SimpleTextOperation.fromTextOperation = function (operation) {
956
+ var simpleOperations = [];
957
+ var index = 0;
958
+ for (var i = 0; i < operation.ops.length; i++) {
959
+ var op = operation.ops[i];
960
+ if (TextOperation.isRetain(op)) {
961
+ index += op;
962
+ } else if (TextOperation.isInsert(op)) {
963
+ simpleOperations.push(new Insert(op, index));
964
+ index += op.length;
965
+ } else {
966
+ simpleOperations.push(new Delete(Math.abs(op), index));
967
+ }
968
+ }
969
+ return simpleOperations;
970
+ };
971
+
972
+
973
+ return SimpleTextOperation;
974
+ })(this);
975
+
976
+ // Export for CommonJS
977
+ if (true) {
978
+ module.exports = ot.SimpleTextOperation;
979
+ }
980
+
981
+ /***/ },
982
+ /* 6 */
983
+ /***/ function(module, exports, __webpack_require__) {
984
+
985
+ // translation of https://github.com/djspiewak/cccp/blob/master/agent/src/main/scala/com/codecommit/cccp/agent/state.scala
986
+
987
+ if (typeof ot === 'undefined') {
988
+ var ot = {};
989
+ }
990
+
991
+ ot.Client = (function (global) {
992
+ 'use strict';
993
+
994
+ // Client constructor
995
+ function Client (revision) {
996
+ this.revision = revision; // the next expected revision number
997
+ this.state = synchronized_; // start state
998
+ }
999
+
1000
+ Client.prototype.setState = function (state) {
1001
+ this.state = state;
1002
+ };
1003
+
1004
+ // Call this method when the user changes the document.
1005
+ Client.prototype.applyClient = function (operation) {
1006
+ this.setState(this.state.applyClient(this, operation));
1007
+ };
1008
+
1009
+ // Call this method with a new operation from the server
1010
+ Client.prototype.applyServer = function (operation) {
1011
+ this.revision++;
1012
+ this.setState(this.state.applyServer(this, operation));
1013
+ };
1014
+
1015
+ Client.prototype.serverAck = function () {
1016
+ this.revision++;
1017
+ this.setState(this.state.serverAck(this));
1018
+ };
1019
+
1020
+ Client.prototype.serverReconnect = function () {
1021
+ if (typeof this.state.resend === 'function') { this.state.resend(this); }
1022
+ };
1023
+
1024
+ // Transforms a selection from the latest known server state to the current
1025
+ // client state. For example, if we get from the server the information that
1026
+ // another user's cursor is at position 3, but the server hasn't yet received
1027
+ // our newest operation, an insertion of 5 characters at the beginning of the
1028
+ // document, the correct position of the other user's cursor in our current
1029
+ // document is 8.
1030
+ Client.prototype.transformSelection = function (selection) {
1031
+ return this.state.transformSelection(selection);
1032
+ };
1033
+
1034
+ // Override this method.
1035
+ Client.prototype.sendOperation = function (revision, operation) {
1036
+ throw new Error("sendOperation must be defined in child class");
1037
+ };
1038
+
1039
+ // Override this method.
1040
+ Client.prototype.applyOperation = function (operation) {
1041
+ throw new Error("applyOperation must be defined in child class");
1042
+ };
1043
+
1044
+
1045
+ // In the 'Synchronized' state, there is no pending operation that the client
1046
+ // has sent to the server.
1047
+ function Synchronized () {}
1048
+ Client.Synchronized = Synchronized;
1049
+
1050
+ Synchronized.prototype.applyClient = function (client, operation) {
1051
+ // When the user makes an edit, send the operation to the server and
1052
+ // switch to the 'AwaitingConfirm' state
1053
+ client.sendOperation(client.revision, operation);
1054
+ return new AwaitingConfirm(operation);
1055
+ };
1056
+
1057
+ Synchronized.prototype.applyServer = function (client, operation) {
1058
+ // When we receive a new operation from the server, the operation can be
1059
+ // simply applied to the current document
1060
+ client.applyOperation(operation);
1061
+ return this;
1062
+ };
1063
+
1064
+ Synchronized.prototype.serverAck = function (client) {
1065
+ throw new Error("There is no pending operation.");
1066
+ };
1067
+
1068
+ // Nothing to do because the latest server state and client state are the same.
1069
+ Synchronized.prototype.transformSelection = function (x) { return x; };
1070
+
1071
+ // Singleton
1072
+ var synchronized_ = new Synchronized();
1073
+
1074
+
1075
+ // In the 'AwaitingConfirm' state, there's one operation the client has sent
1076
+ // to the server and is still waiting for an acknowledgement.
1077
+ function AwaitingConfirm (outstanding) {
1078
+ // Save the pending operation
1079
+ this.outstanding = outstanding;
1080
+ }
1081
+ Client.AwaitingConfirm = AwaitingConfirm;
1082
+
1083
+ AwaitingConfirm.prototype.applyClient = function (client, operation) {
1084
+ // When the user makes an edit, don't send the operation immediately,
1085
+ // instead switch to 'AwaitingWithBuffer' state
1086
+ return new AwaitingWithBuffer(this.outstanding, operation);
1087
+ };
1088
+
1089
+ AwaitingConfirm.prototype.applyServer = function (client, operation) {
1090
+ // This is another client's operation. Visualization:
1091
+ //
1092
+ // /\
1093
+ // this.outstanding / \ operation
1094
+ // / \
1095
+ // \ /
1096
+ // pair[1] \ / pair[0] (new outstanding)
1097
+ // (can be applied \/
1098
+ // to the client's
1099
+ // current document)
1100
+ var pair = operation.constructor.transform(this.outstanding, operation);
1101
+ client.applyOperation(pair[1]);
1102
+ return new AwaitingConfirm(pair[0]);
1103
+ };
1104
+
1105
+ AwaitingConfirm.prototype.serverAck = function (client) {
1106
+ // The client's operation has been acknowledged
1107
+ // => switch to synchronized state
1108
+ return synchronized_;
1109
+ };
1110
+
1111
+ AwaitingConfirm.prototype.transformSelection = function (selection) {
1112
+ return selection.transform(this.outstanding);
1113
+ };
1114
+
1115
+ AwaitingConfirm.prototype.resend = function (client) {
1116
+ // The confirm didn't come because the client was disconnected.
1117
+ // Now that it has reconnected, we resend the outstanding operation.
1118
+ client.sendOperation(client.revision, this.outstanding);
1119
+ };
1120
+
1121
+
1122
+ // In the 'AwaitingWithBuffer' state, the client is waiting for an operation
1123
+ // to be acknowledged by the server while buffering the edits the user makes
1124
+ function AwaitingWithBuffer (outstanding, buffer) {
1125
+ // Save the pending operation and the user's edits since then
1126
+ this.outstanding = outstanding;
1127
+ this.buffer = buffer;
1128
+ }
1129
+ Client.AwaitingWithBuffer = AwaitingWithBuffer;
1130
+
1131
+ AwaitingWithBuffer.prototype.applyClient = function (client, operation) {
1132
+ // Compose the user's changes onto the buffer
1133
+ var newBuffer = this.buffer.compose(operation);
1134
+ return new AwaitingWithBuffer(this.outstanding, newBuffer);
1135
+ };
1136
+
1137
+ AwaitingWithBuffer.prototype.applyServer = function (client, operation) {
1138
+ // Operation comes from another client
1139
+ //
1140
+ // /\
1141
+ // this.outstanding / \ operation
1142
+ // / \
1143
+ // /\ /
1144
+ // this.buffer / \* / pair1[0] (new outstanding)
1145
+ // / \/
1146
+ // \ /
1147
+ // pair2[1] \ / pair2[0] (new buffer)
1148
+ // the transformed \/
1149
+ // operation -- can
1150
+ // be applied to the
1151
+ // client's current
1152
+ // document
1153
+ //
1154
+ // * pair1[1]
1155
+ var transform = operation.constructor.transform;
1156
+ var pair1 = transform(this.outstanding, operation);
1157
+ var pair2 = transform(this.buffer, pair1[1]);
1158
+ client.applyOperation(pair2[1]);
1159
+ return new AwaitingWithBuffer(pair1[0], pair2[0]);
1160
+ };
1161
+
1162
+ AwaitingWithBuffer.prototype.serverAck = function (client) {
1163
+ // The pending operation has been acknowledged
1164
+ // => send buffer
1165
+ client.sendOperation(client.revision, this.buffer);
1166
+ return new AwaitingConfirm(this.buffer);
1167
+ };
1168
+
1169
+ AwaitingWithBuffer.prototype.transformSelection = function (selection) {
1170
+ return selection.transform(this.outstanding).transform(this.buffer);
1171
+ };
1172
+
1173
+ AwaitingWithBuffer.prototype.resend = function (client) {
1174
+ // The confirm didn't come because the client was disconnected.
1175
+ // Now that it has reconnected, we resend the outstanding operation.
1176
+ client.sendOperation(client.revision, this.outstanding);
1177
+ };
1178
+
1179
+
1180
+ return Client;
1181
+
1182
+ }(this));
1183
+
1184
+ if (true) {
1185
+ module.exports = ot.Client;
1186
+ }
1187
+
1188
+
1189
+ /***/ },
1190
+ /* 7 */
1191
+ /***/ function(module, exports, __webpack_require__) {
1192
+
1193
+ if (typeof ot === 'undefined') {
1194
+ var ot = {};
1195
+ }
1196
+
1197
+ ot.Server = (function (global) {
1198
+ 'use strict';
1199
+
1200
+ // Constructor. Takes the current document as a string and optionally the array
1201
+ // of all operations.
1202
+ function Server (document, operations) {
1203
+ this.document = document;
1204
+ this.operations = operations || [];
1205
+ }
1206
+
1207
+ // Call this method whenever you receive an operation from a client.
1208
+ Server.prototype.receiveOperation = function (revision, operation) {
1209
+ if (revision < 0 || this.operations.length < revision) {
1210
+ throw new Error("operation revision not in history");
1211
+ }
1212
+ // Find all operations that the client didn't know of when it sent the
1213
+ // operation ...
1214
+ var concurrentOperations = this.operations.slice(revision);
1215
+
1216
+ // ... and transform the operation against all these operations ...
1217
+ var transform = operation.constructor.transform;
1218
+ for (var i = 0; i < concurrentOperations.length; i++) {
1219
+ operation = transform(operation, concurrentOperations[i])[0];
1220
+ }
1221
+
1222
+ // ... and apply that on the document.
1223
+ this.document = operation.apply(this.document);
1224
+ // Store operation in history.
1225
+ this.operations.push(operation);
1226
+
1227
+ // It's the caller's responsibility to send the operation to all connected
1228
+ // clients and an acknowledgement to the creator.
1229
+ return operation;
1230
+ };
1231
+
1232
+ return Server;
1233
+
1234
+ }(this));
1235
+
1236
+ if (true) {
1237
+ module.exports = ot.Server;
1238
+ }
1239
+
1240
+ /***/ },
1241
+ /* 8 */
1242
+ /***/ function(module, exports, __webpack_require__) {
1243
+
1244
+ if (typeof ot === 'undefined') {
1245
+ // Export for browsers
1246
+ var ot = {};
1247
+ }
1248
+
1249
+ ot.Selection = (function (global) {
1250
+ 'use strict';
1251
+
1252
+ var TextOperation = global.ot ? global.ot.TextOperation : __webpack_require__(4);
1253
+
1254
+ // Range has `anchor` and `head` properties, which are zero-based indices into
1255
+ // the document. The `anchor` is the side of the selection that stays fixed,
1256
+ // `head` is the side of the selection where the cursor is. When both are
1257
+ // equal, the range represents a cursor.
1258
+ function Range (anchor, head) {
1259
+ this.anchor = anchor;
1260
+ this.head = head;
1261
+ }
1262
+
1263
+ Range.fromJSON = function (obj) {
1264
+ return new Range(obj.anchor, obj.head);
1265
+ };
1266
+
1267
+ Range.prototype.equals = function (other) {
1268
+ return this.anchor === other.anchor && this.head === other.head;
1269
+ };
1270
+
1271
+ Range.prototype.isEmpty = function () {
1272
+ return this.anchor === this.head;
1273
+ };
1274
+
1275
+ Range.prototype.transform = function (other) {
1276
+ function transformIndex (index) {
1277
+ var newIndex = index;
1278
+ var ops = other.ops;
1279
+ for (var i = 0, l = other.ops.length; i < l; i++) {
1280
+ if (TextOperation.isRetain(ops[i])) {
1281
+ index -= ops[i];
1282
+ } else if (TextOperation.isInsert(ops[i])) {
1283
+ newIndex += ops[i].length;
1284
+ } else {
1285
+ newIndex -= Math.min(index, -ops[i]);
1286
+ index += ops[i];
1287
+ }
1288
+ if (index < 0) { break; }
1289
+ }
1290
+ return newIndex;
1291
+ }
1292
+
1293
+ var newAnchor = transformIndex(this.anchor);
1294
+ if (this.anchor === this.head) {
1295
+ return new Range(newAnchor, newAnchor);
1296
+ }
1297
+ return new Range(newAnchor, transformIndex(this.head));
1298
+ };
1299
+
1300
+ // A selection is basically an array of ranges. Every range represents a real
1301
+ // selection or a cursor in the document (when the start position equals the
1302
+ // end position of the range). The array must not be empty.
1303
+ function Selection (ranges) {
1304
+ this.ranges = ranges || [];
1305
+ }
1306
+
1307
+ Selection.Range = Range;
1308
+
1309
+ // Convenience method for creating selections only containing a single cursor
1310
+ // and no real selection range.
1311
+ Selection.createCursor = function (position) {
1312
+ return new Selection([new Range(position, position)]);
1313
+ };
1314
+
1315
+ Selection.fromJSON = function (obj) {
1316
+ var objRanges = obj.ranges || obj;
1317
+ for (var i = 0, ranges = []; i < objRanges.length; i++) {
1318
+ ranges[i] = Range.fromJSON(objRanges[i]);
1319
+ }
1320
+ return new Selection(ranges);
1321
+ };
1322
+
1323
+ Selection.prototype.equals = function (other) {
1324
+ if (this.position !== other.position) { return false; }
1325
+ if (this.ranges.length !== other.ranges.length) { return false; }
1326
+ // FIXME: Sort ranges before comparing them?
1327
+ for (var i = 0; i < this.ranges.length; i++) {
1328
+ if (!this.ranges[i].equals(other.ranges[i])) { return false; }
1329
+ }
1330
+ return true;
1331
+ };
1332
+
1333
+ Selection.prototype.somethingSelected = function () {
1334
+ for (var i = 0; i < this.ranges.length; i++) {
1335
+ if (!this.ranges[i].isEmpty()) { return true; }
1336
+ }
1337
+ return false;
1338
+ };
1339
+
1340
+ // Return the more current selection information.
1341
+ Selection.prototype.compose = function (other) {
1342
+ return other;
1343
+ };
1344
+
1345
+ // Update the selection with respect to an operation.
1346
+ Selection.prototype.transform = function (other) {
1347
+ for (var i = 0, newRanges = []; i < this.ranges.length; i++) {
1348
+ newRanges[i] = this.ranges[i].transform(other);
1349
+ }
1350
+ return new Selection(newRanges);
1351
+ };
1352
+
1353
+ return Selection;
1354
+
1355
+ }(this));
1356
+
1357
+ // Export for CommonJS
1358
+ if (true) {
1359
+ module.exports = ot.Selection;
1360
+ }
1361
+
1362
+
1363
+ /***/ },
1364
+ /* 9 */
1365
+ /***/ function(module, exports, __webpack_require__) {
1366
+
1367
+ 'use strict';
1368
+
1369
+ var EventEmitter = __webpack_require__(10).EventEmitter;
1370
+ var TextOperation = __webpack_require__(4);
1371
+ var WrappedOperation = __webpack_require__(11);
1372
+ var Server = __webpack_require__(7);
1373
+ var Selection = __webpack_require__(8);
1374
+ var util = __webpack_require__(12);
1375
+
1376
+ function EditorSocketIOServer (document, operations, docId, mayWrite) {
1377
+ EventEmitter.call(this);
1378
+ Server.call(this, document, operations);
1379
+ this.users = {};
1380
+ this.docId = docId;
1381
+ this.mayWrite = mayWrite || function (_, cb) { cb(true); };
1382
+ }
1383
+
1384
+ util.inherits(EditorSocketIOServer, Server);
1385
+ extend(EditorSocketIOServer.prototype, EventEmitter.prototype);
1386
+
1387
+ function extend (target, source) {
1388
+ for (var key in source) {
1389
+ if (source.hasOwnProperty(key)) {
1390
+ target[key] = source[key];
1391
+ }
1392
+ }
1393
+ }
1394
+
1395
+ EditorSocketIOServer.prototype.addClient = function (socket) {
1396
+ var self = this;
1397
+ socket
1398
+ .join(this.docId)
1399
+ .emit('doc', {
1400
+ str: this.document,
1401
+ revision: this.operations.length,
1402
+ clients: this.users
1403
+ })
1404
+ .on('operation', function (revision, operation, selection) {
1405
+ self.mayWrite(socket, function (mayWrite) {
1406
+ if (!mayWrite) {
1407
+ console.log("User doesn't have the right to edit.");
1408
+ return;
1409
+ }
1410
+ self.onOperation(socket, revision, operation, selection);
1411
+ });
1412
+ })
1413
+ .on('selection', function (obj) {
1414
+ self.mayWrite(socket, function (mayWrite) {
1415
+ if (!mayWrite) {
1416
+ console.log("User doesn't have the right to edit.");
1417
+ return;
1418
+ }
1419
+ self.updateSelection(socket, obj && Selection.fromJSON(obj));
1420
+ });
1421
+ })
1422
+ .on('disconnect', function () {
1423
+ console.log("Disconnect");
1424
+ socket.leave(self.docId);
1425
+ self.onDisconnect(socket);
1426
+ if (socket.manager.sockets.clients(self.docId).length === 0) {
1427
+ self.emit('empty-room');
1428
+ }
1429
+ });
1430
+ };
1431
+
1432
+ EditorSocketIOServer.prototype.onOperation = function (socket, revision, operation, selection) {
1433
+ var wrapped;
1434
+ try {
1435
+ wrapped = new WrappedOperation(
1436
+ TextOperation.fromJSON(operation),
1437
+ selection && Selection.fromJSON(selection)
1438
+ );
1439
+ } catch (exc) {
1440
+ console.error("Invalid operation received: " + exc);
1441
+ return;
1442
+ }
1443
+
1444
+ try {
1445
+ var clientId = socket.id;
1446
+ var wrappedPrime = this.receiveOperation(revision, wrapped);
1447
+ console.log("new operation: " + wrapped);
1448
+ this.getClient(clientId).selection = wrappedPrime.meta;
1449
+ socket.emit('ack');
1450
+ socket.broadcast['in'](this.docId).emit(
1451
+ 'operation', clientId,
1452
+ wrappedPrime.wrapped.toJSON(), wrappedPrime.meta
1453
+ );
1454
+ } catch (exc) {
1455
+ console.error(exc);
1456
+ }
1457
+ };
1458
+
1459
+ EditorSocketIOServer.prototype.updateSelection = function (socket, selection) {
1460
+ var clientId = socket.id;
1461
+ if (selection) {
1462
+ this.getClient(clientId).selection = selection;
1463
+ } else {
1464
+ delete this.getClient(clientId).selection;
1465
+ }
1466
+ socket.broadcast['in'](this.docId).emit('selection', clientId, selection);
1467
+ };
1468
+
1469
+ EditorSocketIOServer.prototype.setName = function (socket, name) {
1470
+ var clientId = socket.id;
1471
+ this.getClient(clientId).name = name;
1472
+ socket.broadcast['in'](this.docId).emit('set_name', clientId, name);
1473
+ };
1474
+
1475
+ EditorSocketIOServer.prototype.getClient = function (clientId) {
1476
+ return this.users[clientId] || (this.users[clientId] = {});
1477
+ };
1478
+
1479
+ EditorSocketIOServer.prototype.onDisconnect = function (socket) {
1480
+ var clientId = socket.id;
1481
+ delete this.users[clientId];
1482
+ socket.broadcast['in'](this.docId).emit('client_left', clientId);
1483
+ };
1484
+
1485
+ module.exports = EditorSocketIOServer;
1486
+
1487
+ /***/ },
1488
+ /* 10 */
1489
+ /***/ function(module, exports) {
1490
+
1491
+ // Copyright Joyent, Inc. and other Node contributors.
1492
+ //
1493
+ // Permission is hereby granted, free of charge, to any person obtaining a
1494
+ // copy of this software and associated documentation files (the
1495
+ // "Software"), to deal in the Software without restriction, including
1496
+ // without limitation the rights to use, copy, modify, merge, publish,
1497
+ // distribute, sublicense, and/or sell copies of the Software, and to permit
1498
+ // persons to whom the Software is furnished to do so, subject to the
1499
+ // following conditions:
1500
+ //
1501
+ // The above copyright notice and this permission notice shall be included
1502
+ // in all copies or substantial portions of the Software.
1503
+ //
1504
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1505
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1506
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
1507
+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
1508
+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
1509
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
1510
+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
1511
+
1512
+ function EventEmitter() {
1513
+ this._events = this._events || {};
1514
+ this._maxListeners = this._maxListeners || undefined;
1515
+ }
1516
+ module.exports = EventEmitter;
1517
+
1518
+ // Backwards-compat with node 0.10.x
1519
+ EventEmitter.EventEmitter = EventEmitter;
1520
+
1521
+ EventEmitter.prototype._events = undefined;
1522
+ EventEmitter.prototype._maxListeners = undefined;
1523
+
1524
+ // By default EventEmitters will print a warning if more than 10 listeners are
1525
+ // added to it. This is a useful default which helps finding memory leaks.
1526
+ EventEmitter.defaultMaxListeners = 10;
1527
+
1528
+ // Obviously not all Emitters should be limited to 10. This function allows
1529
+ // that to be increased. Set to zero for unlimited.
1530
+ EventEmitter.prototype.setMaxListeners = function(n) {
1531
+ if (!isNumber(n) || n < 0 || isNaN(n))
1532
+ throw TypeError('n must be a positive number');
1533
+ this._maxListeners = n;
1534
+ return this;
1535
+ };
1536
+
1537
+ EventEmitter.prototype.emit = function(type) {
1538
+ var er, handler, len, args, i, listeners;
1539
+
1540
+ if (!this._events)
1541
+ this._events = {};
1542
+
1543
+ // If there is no 'error' event listener then throw.
1544
+ if (type === 'error') {
1545
+ if (!this._events.error ||
1546
+ (isObject(this._events.error) && !this._events.error.length)) {
1547
+ er = arguments[1];
1548
+ if (er instanceof Error) {
1549
+ throw er; // Unhandled 'error' event
1550
+ } else {
1551
+ // At least give some kind of context to the user
1552
+ var err = new Error('Uncaught, unspecified "error" event. (' + er + ')');
1553
+ err.context = er;
1554
+ throw err;
1555
+ }
1556
+ }
1557
+ }
1558
+
1559
+ handler = this._events[type];
1560
+
1561
+ if (isUndefined(handler))
1562
+ return false;
1563
+
1564
+ if (isFunction(handler)) {
1565
+ switch (arguments.length) {
1566
+ // fast cases
1567
+ case 1:
1568
+ handler.call(this);
1569
+ break;
1570
+ case 2:
1571
+ handler.call(this, arguments[1]);
1572
+ break;
1573
+ case 3:
1574
+ handler.call(this, arguments[1], arguments[2]);
1575
+ break;
1576
+ // slower
1577
+ default:
1578
+ args = Array.prototype.slice.call(arguments, 1);
1579
+ handler.apply(this, args);
1580
+ }
1581
+ } else if (isObject(handler)) {
1582
+ args = Array.prototype.slice.call(arguments, 1);
1583
+ listeners = handler.slice();
1584
+ len = listeners.length;
1585
+ for (i = 0; i < len; i++)
1586
+ listeners[i].apply(this, args);
1587
+ }
1588
+
1589
+ return true;
1590
+ };
1591
+
1592
+ EventEmitter.prototype.addListener = function(type, listener) {
1593
+ var m;
1594
+
1595
+ if (!isFunction(listener))
1596
+ throw TypeError('listener must be a function');
1597
+
1598
+ if (!this._events)
1599
+ this._events = {};
1600
+
1601
+ // To avoid recursion in the case that type === "newListener"! Before
1602
+ // adding it to the listeners, first emit "newListener".
1603
+ if (this._events.newListener)
1604
+ this.emit('newListener', type,
1605
+ isFunction(listener.listener) ?
1606
+ listener.listener : listener);
1607
+
1608
+ if (!this._events[type])
1609
+ // Optimize the case of one listener. Don't need the extra array object.
1610
+ this._events[type] = listener;
1611
+ else if (isObject(this._events[type]))
1612
+ // If we've already got an array, just append.
1613
+ this._events[type].push(listener);
1614
+ else
1615
+ // Adding the second element, need to change to array.
1616
+ this._events[type] = [this._events[type], listener];
1617
+
1618
+ // Check for listener leak
1619
+ if (isObject(this._events[type]) && !this._events[type].warned) {
1620
+ if (!isUndefined(this._maxListeners)) {
1621
+ m = this._maxListeners;
1622
+ } else {
1623
+ m = EventEmitter.defaultMaxListeners;
1624
+ }
1625
+
1626
+ if (m && m > 0 && this._events[type].length > m) {
1627
+ this._events[type].warned = true;
1628
+ console.error('(node) warning: possible EventEmitter memory ' +
1629
+ 'leak detected. %d listeners added. ' +
1630
+ 'Use emitter.setMaxListeners() to increase limit.',
1631
+ this._events[type].length);
1632
+ if (typeof console.trace === 'function') {
1633
+ // not supported in IE 10
1634
+ console.trace();
1635
+ }
1636
+ }
1637
+ }
1638
+
1639
+ return this;
1640
+ };
1641
+
1642
+ EventEmitter.prototype.on = EventEmitter.prototype.addListener;
1643
+
1644
+ EventEmitter.prototype.once = function(type, listener) {
1645
+ if (!isFunction(listener))
1646
+ throw TypeError('listener must be a function');
1647
+
1648
+ var fired = false;
1649
+
1650
+ function g() {
1651
+ this.removeListener(type, g);
1652
+
1653
+ if (!fired) {
1654
+ fired = true;
1655
+ listener.apply(this, arguments);
1656
+ }
1657
+ }
1658
+
1659
+ g.listener = listener;
1660
+ this.on(type, g);
1661
+
1662
+ return this;
1663
+ };
1664
+
1665
+ // emits a 'removeListener' event iff the listener was removed
1666
+ EventEmitter.prototype.removeListener = function(type, listener) {
1667
+ var list, position, length, i;
1668
+
1669
+ if (!isFunction(listener))
1670
+ throw TypeError('listener must be a function');
1671
+
1672
+ if (!this._events || !this._events[type])
1673
+ return this;
1674
+
1675
+ list = this._events[type];
1676
+ length = list.length;
1677
+ position = -1;
1678
+
1679
+ if (list === listener ||
1680
+ (isFunction(list.listener) && list.listener === listener)) {
1681
+ delete this._events[type];
1682
+ if (this._events.removeListener)
1683
+ this.emit('removeListener', type, listener);
1684
+
1685
+ } else if (isObject(list)) {
1686
+ for (i = length; i-- > 0;) {
1687
+ if (list[i] === listener ||
1688
+ (list[i].listener && list[i].listener === listener)) {
1689
+ position = i;
1690
+ break;
1691
+ }
1692
+ }
1693
+
1694
+ if (position < 0)
1695
+ return this;
1696
+
1697
+ if (list.length === 1) {
1698
+ list.length = 0;
1699
+ delete this._events[type];
1700
+ } else {
1701
+ list.splice(position, 1);
1702
+ }
1703
+
1704
+ if (this._events.removeListener)
1705
+ this.emit('removeListener', type, listener);
1706
+ }
1707
+
1708
+ return this;
1709
+ };
1710
+
1711
+ EventEmitter.prototype.removeAllListeners = function(type) {
1712
+ var key, listeners;
1713
+
1714
+ if (!this._events)
1715
+ return this;
1716
+
1717
+ // not listening for removeListener, no need to emit
1718
+ if (!this._events.removeListener) {
1719
+ if (arguments.length === 0)
1720
+ this._events = {};
1721
+ else if (this._events[type])
1722
+ delete this._events[type];
1723
+ return this;
1724
+ }
1725
+
1726
+ // emit removeListener for all listeners on all events
1727
+ if (arguments.length === 0) {
1728
+ for (key in this._events) {
1729
+ if (key === 'removeListener') continue;
1730
+ this.removeAllListeners(key);
1731
+ }
1732
+ this.removeAllListeners('removeListener');
1733
+ this._events = {};
1734
+ return this;
1735
+ }
1736
+
1737
+ listeners = this._events[type];
1738
+
1739
+ if (isFunction(listeners)) {
1740
+ this.removeListener(type, listeners);
1741
+ } else if (listeners) {
1742
+ // LIFO order
1743
+ while (listeners.length)
1744
+ this.removeListener(type, listeners[listeners.length - 1]);
1745
+ }
1746
+ delete this._events[type];
1747
+
1748
+ return this;
1749
+ };
1750
+
1751
+ EventEmitter.prototype.listeners = function(type) {
1752
+ var ret;
1753
+ if (!this._events || !this._events[type])
1754
+ ret = [];
1755
+ else if (isFunction(this._events[type]))
1756
+ ret = [this._events[type]];
1757
+ else
1758
+ ret = this._events[type].slice();
1759
+ return ret;
1760
+ };
1761
+
1762
+ EventEmitter.prototype.listenerCount = function(type) {
1763
+ if (this._events) {
1764
+ var evlistener = this._events[type];
1765
+
1766
+ if (isFunction(evlistener))
1767
+ return 1;
1768
+ else if (evlistener)
1769
+ return evlistener.length;
1770
+ }
1771
+ return 0;
1772
+ };
1773
+
1774
+ EventEmitter.listenerCount = function(emitter, type) {
1775
+ return emitter.listenerCount(type);
1776
+ };
1777
+
1778
+ function isFunction(arg) {
1779
+ return typeof arg === 'function';
1780
+ }
1781
+
1782
+ function isNumber(arg) {
1783
+ return typeof arg === 'number';
1784
+ }
1785
+
1786
+ function isObject(arg) {
1787
+ return typeof arg === 'object' && arg !== null;
1788
+ }
1789
+
1790
+ function isUndefined(arg) {
1791
+ return arg === void 0;
1792
+ }
1793
+
1794
+
1795
+ /***/ },
1796
+ /* 11 */
1797
+ /***/ function(module, exports, __webpack_require__) {
1798
+
1799
+ if (typeof ot === 'undefined') {
1800
+ // Export for browsers
1801
+ var ot = {};
1802
+ }
1803
+
1804
+ ot.WrappedOperation = (function (global) {
1805
+ 'use strict';
1806
+
1807
+ // A WrappedOperation contains an operation and corresponing metadata.
1808
+ function WrappedOperation (operation, meta) {
1809
+ this.wrapped = operation;
1810
+ this.meta = meta;
1811
+ }
1812
+
1813
+ WrappedOperation.prototype.apply = function () {
1814
+ return this.wrapped.apply.apply(this.wrapped, arguments);
1815
+ };
1816
+
1817
+ WrappedOperation.prototype.invert = function () {
1818
+ var meta = this.meta;
1819
+ return new WrappedOperation(
1820
+ this.wrapped.invert.apply(this.wrapped, arguments),
1821
+ meta && typeof meta === 'object' && typeof meta.invert === 'function' ?
1822
+ meta.invert.apply(meta, arguments) : meta
1823
+ );
1824
+ };
1825
+
1826
+ // Copy all properties from source to target.
1827
+ function copy (source, target) {
1828
+ for (var key in source) {
1829
+ if (source.hasOwnProperty(key)) {
1830
+ target[key] = source[key];
1831
+ }
1832
+ }
1833
+ }
1834
+
1835
+ function composeMeta (a, b) {
1836
+ if (a && typeof a === 'object') {
1837
+ if (typeof a.compose === 'function') { return a.compose(b); }
1838
+ var meta = {};
1839
+ copy(a, meta);
1840
+ copy(b, meta);
1841
+ return meta;
1842
+ }
1843
+ return b;
1844
+ }
1845
+
1846
+ WrappedOperation.prototype.compose = function (other) {
1847
+ return new WrappedOperation(
1848
+ this.wrapped.compose(other.wrapped),
1849
+ composeMeta(this.meta, other.meta)
1850
+ );
1851
+ };
1852
+
1853
+ function transformMeta (meta, operation) {
1854
+ if (meta && typeof meta === 'object') {
1855
+ if (typeof meta.transform === 'function') {
1856
+ return meta.transform(operation);
1857
+ }
1858
+ }
1859
+ return meta;
1860
+ }
1861
+
1862
+ WrappedOperation.transform = function (a, b) {
1863
+ var transform = a.wrapped.constructor.transform;
1864
+ var pair = transform(a.wrapped, b.wrapped);
1865
+ return [
1866
+ new WrappedOperation(pair[0], transformMeta(a.meta, b.wrapped)),
1867
+ new WrappedOperation(pair[1], transformMeta(b.meta, a.wrapped))
1868
+ ];
1869
+ };
1870
+
1871
+ return WrappedOperation;
1872
+
1873
+ }(this));
1874
+
1875
+ // Export for CommonJS
1876
+ if (true) {
1877
+ module.exports = ot.WrappedOperation;
1878
+ }
1879
+
1880
+ /***/ },
1881
+ /* 12 */
1882
+ /***/ function(module, exports, __webpack_require__) {
1883
+
1884
+ /* WEBPACK VAR INJECTION */(function(global, process) {// Copyright Joyent, Inc. and other Node contributors.
1885
+ //
1886
+ // Permission is hereby granted, free of charge, to any person obtaining a
1887
+ // copy of this software and associated documentation files (the
1888
+ // "Software"), to deal in the Software without restriction, including
1889
+ // without limitation the rights to use, copy, modify, merge, publish,
1890
+ // distribute, sublicense, and/or sell copies of the Software, and to permit
1891
+ // persons to whom the Software is furnished to do so, subject to the
1892
+ // following conditions:
1893
+ //
1894
+ // The above copyright notice and this permission notice shall be included
1895
+ // in all copies or substantial portions of the Software.
1896
+ //
1897
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1898
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1899
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
1900
+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
1901
+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
1902
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
1903
+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
1904
+
1905
+ var formatRegExp = /%[sdj%]/g;
1906
+ exports.format = function(f) {
1907
+ if (!isString(f)) {
1908
+ var objects = [];
1909
+ for (var i = 0; i < arguments.length; i++) {
1910
+ objects.push(inspect(arguments[i]));
1911
+ }
1912
+ return objects.join(' ');
1913
+ }
1914
+
1915
+ var i = 1;
1916
+ var args = arguments;
1917
+ var len = args.length;
1918
+ var str = String(f).replace(formatRegExp, function(x) {
1919
+ if (x === '%%') return '%';
1920
+ if (i >= len) return x;
1921
+ switch (x) {
1922
+ case '%s': return String(args[i++]);
1923
+ case '%d': return Number(args[i++]);
1924
+ case '%j':
1925
+ try {
1926
+ return JSON.stringify(args[i++]);
1927
+ } catch (_) {
1928
+ return '[Circular]';
1929
+ }
1930
+ default:
1931
+ return x;
1932
+ }
1933
+ });
1934
+ for (var x = args[i]; i < len; x = args[++i]) {
1935
+ if (isNull(x) || !isObject(x)) {
1936
+ str += ' ' + x;
1937
+ } else {
1938
+ str += ' ' + inspect(x);
1939
+ }
1940
+ }
1941
+ return str;
1942
+ };
1943
+
1944
+
1945
+ // Mark that a method should not be used.
1946
+ // Returns a modified function which warns once by default.
1947
+ // If --no-deprecation is set, then it is a no-op.
1948
+ exports.deprecate = function(fn, msg) {
1949
+ // Allow for deprecating things in the process of starting up.
1950
+ if (isUndefined(global.process)) {
1951
+ return function() {
1952
+ return exports.deprecate(fn, msg).apply(this, arguments);
1953
+ };
1954
+ }
1955
+
1956
+ if (process.noDeprecation === true) {
1957
+ return fn;
1958
+ }
1959
+
1960
+ var warned = false;
1961
+ function deprecated() {
1962
+ if (!warned) {
1963
+ if (process.throwDeprecation) {
1964
+ throw new Error(msg);
1965
+ } else if (process.traceDeprecation) {
1966
+ console.trace(msg);
1967
+ } else {
1968
+ console.error(msg);
1969
+ }
1970
+ warned = true;
1971
+ }
1972
+ return fn.apply(this, arguments);
1973
+ }
1974
+
1975
+ return deprecated;
1976
+ };
1977
+
1978
+
1979
+ var debugs = {};
1980
+ var debugEnviron;
1981
+ exports.debuglog = function(set) {
1982
+ if (isUndefined(debugEnviron))
1983
+ debugEnviron = process.env.NODE_DEBUG || '';
1984
+ set = set.toUpperCase();
1985
+ if (!debugs[set]) {
1986
+ if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
1987
+ var pid = process.pid;
1988
+ debugs[set] = function() {
1989
+ var msg = exports.format.apply(exports, arguments);
1990
+ console.error('%s %d: %s', set, pid, msg);
1991
+ };
1992
+ } else {
1993
+ debugs[set] = function() {};
1994
+ }
1995
+ }
1996
+ return debugs[set];
1997
+ };
1998
+
1999
+
2000
+ /**
2001
+ * Echos the value of a value. Trys to print the value out
2002
+ * in the best way possible given the different types.
2003
+ *
2004
+ * @param {Object} obj The object to print out.
2005
+ * @param {Object} opts Optional options object that alters the output.
2006
+ */
2007
+ /* legacy: obj, showHidden, depth, colors*/
2008
+ function inspect(obj, opts) {
2009
+ // default options
2010
+ var ctx = {
2011
+ seen: [],
2012
+ stylize: stylizeNoColor
2013
+ };
2014
+ // legacy...
2015
+ if (arguments.length >= 3) ctx.depth = arguments[2];
2016
+ if (arguments.length >= 4) ctx.colors = arguments[3];
2017
+ if (isBoolean(opts)) {
2018
+ // legacy...
2019
+ ctx.showHidden = opts;
2020
+ } else if (opts) {
2021
+ // got an "options" object
2022
+ exports._extend(ctx, opts);
2023
+ }
2024
+ // set default options
2025
+ if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
2026
+ if (isUndefined(ctx.depth)) ctx.depth = 2;
2027
+ if (isUndefined(ctx.colors)) ctx.colors = false;
2028
+ if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
2029
+ if (ctx.colors) ctx.stylize = stylizeWithColor;
2030
+ return formatValue(ctx, obj, ctx.depth);
2031
+ }
2032
+ exports.inspect = inspect;
2033
+
2034
+
2035
+ // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
2036
+ inspect.colors = {
2037
+ 'bold' : [1, 22],
2038
+ 'italic' : [3, 23],
2039
+ 'underline' : [4, 24],
2040
+ 'inverse' : [7, 27],
2041
+ 'white' : [37, 39],
2042
+ 'grey' : [90, 39],
2043
+ 'black' : [30, 39],
2044
+ 'blue' : [34, 39],
2045
+ 'cyan' : [36, 39],
2046
+ 'green' : [32, 39],
2047
+ 'magenta' : [35, 39],
2048
+ 'red' : [31, 39],
2049
+ 'yellow' : [33, 39]
2050
+ };
2051
+
2052
+ // Don't use 'blue' not visible on cmd.exe
2053
+ inspect.styles = {
2054
+ 'special': 'cyan',
2055
+ 'number': 'yellow',
2056
+ 'boolean': 'yellow',
2057
+ 'undefined': 'grey',
2058
+ 'null': 'bold',
2059
+ 'string': 'green',
2060
+ 'date': 'magenta',
2061
+ // "name": intentionally not styling
2062
+ 'regexp': 'red'
2063
+ };
2064
+
2065
+
2066
+ function stylizeWithColor(str, styleType) {
2067
+ var style = inspect.styles[styleType];
2068
+
2069
+ if (style) {
2070
+ return '\u001b[' + inspect.colors[style][0] + 'm' + str +
2071
+ '\u001b[' + inspect.colors[style][1] + 'm';
2072
+ } else {
2073
+ return str;
2074
+ }
2075
+ }
2076
+
2077
+
2078
+ function stylizeNoColor(str, styleType) {
2079
+ return str;
2080
+ }
2081
+
2082
+
2083
+ function arrayToHash(array) {
2084
+ var hash = {};
2085
+
2086
+ array.forEach(function(val, idx) {
2087
+ hash[val] = true;
2088
+ });
2089
+
2090
+ return hash;
2091
+ }
2092
+
2093
+
2094
+ function formatValue(ctx, value, recurseTimes) {
2095
+ // Provide a hook for user-specified inspect functions.
2096
+ // Check that value is an object with an inspect function on it
2097
+ if (ctx.customInspect &&
2098
+ value &&
2099
+ isFunction(value.inspect) &&
2100
+ // Filter out the util module, it's inspect function is special
2101
+ value.inspect !== exports.inspect &&
2102
+ // Also filter out any prototype objects using the circular check.
2103
+ !(value.constructor && value.constructor.prototype === value)) {
2104
+ var ret = value.inspect(recurseTimes, ctx);
2105
+ if (!isString(ret)) {
2106
+ ret = formatValue(ctx, ret, recurseTimes);
2107
+ }
2108
+ return ret;
2109
+ }
2110
+
2111
+ // Primitive types cannot have properties
2112
+ var primitive = formatPrimitive(ctx, value);
2113
+ if (primitive) {
2114
+ return primitive;
2115
+ }
2116
+
2117
+ // Look up the keys of the object.
2118
+ var keys = Object.keys(value);
2119
+ var visibleKeys = arrayToHash(keys);
2120
+
2121
+ if (ctx.showHidden) {
2122
+ keys = Object.getOwnPropertyNames(value);
2123
+ }
2124
+
2125
+ // IE doesn't make error fields non-enumerable
2126
+ // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
2127
+ if (isError(value)
2128
+ && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
2129
+ return formatError(value);
2130
+ }
2131
+
2132
+ // Some type of object without properties can be shortcutted.
2133
+ if (keys.length === 0) {
2134
+ if (isFunction(value)) {
2135
+ var name = value.name ? ': ' + value.name : '';
2136
+ return ctx.stylize('[Function' + name + ']', 'special');
2137
+ }
2138
+ if (isRegExp(value)) {
2139
+ return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
2140
+ }
2141
+ if (isDate(value)) {
2142
+ return ctx.stylize(Date.prototype.toString.call(value), 'date');
2143
+ }
2144
+ if (isError(value)) {
2145
+ return formatError(value);
2146
+ }
2147
+ }
2148
+
2149
+ var base = '', array = false, braces = ['{', '}'];
2150
+
2151
+ // Make Array say that they are Array
2152
+ if (isArray(value)) {
2153
+ array = true;
2154
+ braces = ['[', ']'];
2155
+ }
2156
+
2157
+ // Make functions say that they are functions
2158
+ if (isFunction(value)) {
2159
+ var n = value.name ? ': ' + value.name : '';
2160
+ base = ' [Function' + n + ']';
2161
+ }
2162
+
2163
+ // Make RegExps say that they are RegExps
2164
+ if (isRegExp(value)) {
2165
+ base = ' ' + RegExp.prototype.toString.call(value);
2166
+ }
2167
+
2168
+ // Make dates with properties first say the date
2169
+ if (isDate(value)) {
2170
+ base = ' ' + Date.prototype.toUTCString.call(value);
2171
+ }
2172
+
2173
+ // Make error with message first say the error
2174
+ if (isError(value)) {
2175
+ base = ' ' + formatError(value);
2176
+ }
2177
+
2178
+ if (keys.length === 0 && (!array || value.length == 0)) {
2179
+ return braces[0] + base + braces[1];
2180
+ }
2181
+
2182
+ if (recurseTimes < 0) {
2183
+ if (isRegExp(value)) {
2184
+ return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
2185
+ } else {
2186
+ return ctx.stylize('[Object]', 'special');
2187
+ }
2188
+ }
2189
+
2190
+ ctx.seen.push(value);
2191
+
2192
+ var output;
2193
+ if (array) {
2194
+ output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
2195
+ } else {
2196
+ output = keys.map(function(key) {
2197
+ return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
2198
+ });
2199
+ }
2200
+
2201
+ ctx.seen.pop();
2202
+
2203
+ return reduceToSingleString(output, base, braces);
2204
+ }
2205
+
2206
+
2207
+ function formatPrimitive(ctx, value) {
2208
+ if (isUndefined(value))
2209
+ return ctx.stylize('undefined', 'undefined');
2210
+ if (isString(value)) {
2211
+ var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
2212
+ .replace(/'/g, "\\'")
2213
+ .replace(/\\"/g, '"') + '\'';
2214
+ return ctx.stylize(simple, 'string');
2215
+ }
2216
+ if (isNumber(value))
2217
+ return ctx.stylize('' + value, 'number');
2218
+ if (isBoolean(value))
2219
+ return ctx.stylize('' + value, 'boolean');
2220
+ // For some reason typeof null is "object", so special case here.
2221
+ if (isNull(value))
2222
+ return ctx.stylize('null', 'null');
2223
+ }
2224
+
2225
+
2226
+ function formatError(value) {
2227
+ return '[' + Error.prototype.toString.call(value) + ']';
2228
+ }
2229
+
2230
+
2231
+ function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
2232
+ var output = [];
2233
+ for (var i = 0, l = value.length; i < l; ++i) {
2234
+ if (hasOwnProperty(value, String(i))) {
2235
+ output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
2236
+ String(i), true));
2237
+ } else {
2238
+ output.push('');
2239
+ }
2240
+ }
2241
+ keys.forEach(function(key) {
2242
+ if (!key.match(/^\d+$/)) {
2243
+ output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
2244
+ key, true));
2245
+ }
2246
+ });
2247
+ return output;
2248
+ }
2249
+
2250
+
2251
+ function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
2252
+ var name, str, desc;
2253
+ desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
2254
+ if (desc.get) {
2255
+ if (desc.set) {
2256
+ str = ctx.stylize('[Getter/Setter]', 'special');
2257
+ } else {
2258
+ str = ctx.stylize('[Getter]', 'special');
2259
+ }
2260
+ } else {
2261
+ if (desc.set) {
2262
+ str = ctx.stylize('[Setter]', 'special');
2263
+ }
2264
+ }
2265
+ if (!hasOwnProperty(visibleKeys, key)) {
2266
+ name = '[' + key + ']';
2267
+ }
2268
+ if (!str) {
2269
+ if (ctx.seen.indexOf(desc.value) < 0) {
2270
+ if (isNull(recurseTimes)) {
2271
+ str = formatValue(ctx, desc.value, null);
2272
+ } else {
2273
+ str = formatValue(ctx, desc.value, recurseTimes - 1);
2274
+ }
2275
+ if (str.indexOf('\n') > -1) {
2276
+ if (array) {
2277
+ str = str.split('\n').map(function(line) {
2278
+ return ' ' + line;
2279
+ }).join('\n').substr(2);
2280
+ } else {
2281
+ str = '\n' + str.split('\n').map(function(line) {
2282
+ return ' ' + line;
2283
+ }).join('\n');
2284
+ }
2285
+ }
2286
+ } else {
2287
+ str = ctx.stylize('[Circular]', 'special');
2288
+ }
2289
+ }
2290
+ if (isUndefined(name)) {
2291
+ if (array && key.match(/^\d+$/)) {
2292
+ return str;
2293
+ }
2294
+ name = JSON.stringify('' + key);
2295
+ if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
2296
+ name = name.substr(1, name.length - 2);
2297
+ name = ctx.stylize(name, 'name');
2298
+ } else {
2299
+ name = name.replace(/'/g, "\\'")
2300
+ .replace(/\\"/g, '"')
2301
+ .replace(/(^"|"$)/g, "'");
2302
+ name = ctx.stylize(name, 'string');
2303
+ }
2304
+ }
2305
+
2306
+ return name + ': ' + str;
2307
+ }
2308
+
2309
+
2310
+ function reduceToSingleString(output, base, braces) {
2311
+ var numLinesEst = 0;
2312
+ var length = output.reduce(function(prev, cur) {
2313
+ numLinesEst++;
2314
+ if (cur.indexOf('\n') >= 0) numLinesEst++;
2315
+ return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
2316
+ }, 0);
2317
+
2318
+ if (length > 60) {
2319
+ return braces[0] +
2320
+ (base === '' ? '' : base + '\n ') +
2321
+ ' ' +
2322
+ output.join(',\n ') +
2323
+ ' ' +
2324
+ braces[1];
2325
+ }
2326
+
2327
+ return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
2328
+ }
2329
+
2330
+
2331
+ // NOTE: These type checking functions intentionally don't use `instanceof`
2332
+ // because it is fragile and can be easily faked with `Object.create()`.
2333
+ function isArray(ar) {
2334
+ return Array.isArray(ar);
2335
+ }
2336
+ exports.isArray = isArray;
2337
+
2338
+ function isBoolean(arg) {
2339
+ return typeof arg === 'boolean';
2340
+ }
2341
+ exports.isBoolean = isBoolean;
2342
+
2343
+ function isNull(arg) {
2344
+ return arg === null;
2345
+ }
2346
+ exports.isNull = isNull;
2347
+
2348
+ function isNullOrUndefined(arg) {
2349
+ return arg == null;
2350
+ }
2351
+ exports.isNullOrUndefined = isNullOrUndefined;
2352
+
2353
+ function isNumber(arg) {
2354
+ return typeof arg === 'number';
2355
+ }
2356
+ exports.isNumber = isNumber;
2357
+
2358
+ function isString(arg) {
2359
+ return typeof arg === 'string';
2360
+ }
2361
+ exports.isString = isString;
2362
+
2363
+ function isSymbol(arg) {
2364
+ return typeof arg === 'symbol';
2365
+ }
2366
+ exports.isSymbol = isSymbol;
2367
+
2368
+ function isUndefined(arg) {
2369
+ return arg === void 0;
2370
+ }
2371
+ exports.isUndefined = isUndefined;
2372
+
2373
+ function isRegExp(re) {
2374
+ return isObject(re) && objectToString(re) === '[object RegExp]';
2375
+ }
2376
+ exports.isRegExp = isRegExp;
2377
+
2378
+ function isObject(arg) {
2379
+ return typeof arg === 'object' && arg !== null;
2380
+ }
2381
+ exports.isObject = isObject;
2382
+
2383
+ function isDate(d) {
2384
+ return isObject(d) && objectToString(d) === '[object Date]';
2385
+ }
2386
+ exports.isDate = isDate;
2387
+
2388
+ function isError(e) {
2389
+ return isObject(e) &&
2390
+ (objectToString(e) === '[object Error]' || e instanceof Error);
2391
+ }
2392
+ exports.isError = isError;
2393
+
2394
+ function isFunction(arg) {
2395
+ return typeof arg === 'function';
2396
+ }
2397
+ exports.isFunction = isFunction;
2398
+
2399
+ function isPrimitive(arg) {
2400
+ return arg === null ||
2401
+ typeof arg === 'boolean' ||
2402
+ typeof arg === 'number' ||
2403
+ typeof arg === 'string' ||
2404
+ typeof arg === 'symbol' || // ES6 symbol
2405
+ typeof arg === 'undefined';
2406
+ }
2407
+ exports.isPrimitive = isPrimitive;
2408
+
2409
+ exports.isBuffer = __webpack_require__(14);
2410
+
2411
+ function objectToString(o) {
2412
+ return Object.prototype.toString.call(o);
2413
+ }
2414
+
2415
+
2416
+ function pad(n) {
2417
+ return n < 10 ? '0' + n.toString(10) : n.toString(10);
2418
+ }
2419
+
2420
+
2421
+ var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
2422
+ 'Oct', 'Nov', 'Dec'];
2423
+
2424
+ // 26 Feb 16:19:34
2425
+ function timestamp() {
2426
+ var d = new Date();
2427
+ var time = [pad(d.getHours()),
2428
+ pad(d.getMinutes()),
2429
+ pad(d.getSeconds())].join(':');
2430
+ return [d.getDate(), months[d.getMonth()], time].join(' ');
2431
+ }
2432
+
2433
+
2434
+ // log is just a thin wrapper to console.log that prepends a timestamp
2435
+ exports.log = function() {
2436
+ console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
2437
+ };
2438
+
2439
+
2440
+ /**
2441
+ * Inherit the prototype methods from one constructor into another.
2442
+ *
2443
+ * The Function.prototype.inherits from lang.js rewritten as a standalone
2444
+ * function (not on Function.prototype). NOTE: If this file is to be loaded
2445
+ * during bootstrapping this function needs to be rewritten using some native
2446
+ * functions as prototype setup using normal JavaScript does not work as
2447
+ * expected during bootstrapping (see mirror.js in r114903).
2448
+ *
2449
+ * @param {function} ctor Constructor function which needs to inherit the
2450
+ * prototype.
2451
+ * @param {function} superCtor Constructor function to inherit prototype from.
2452
+ */
2453
+ exports.inherits = __webpack_require__(15);
2454
+
2455
+ exports._extend = function(origin, add) {
2456
+ // Don't do anything if add isn't an object
2457
+ if (!add || !isObject(add)) return origin;
2458
+
2459
+ var keys = Object.keys(add);
2460
+ var i = keys.length;
2461
+ while (i--) {
2462
+ origin[keys[i]] = add[keys[i]];
2463
+ }
2464
+ return origin;
2465
+ };
2466
+
2467
+ function hasOwnProperty(obj, prop) {
2468
+ return Object.prototype.hasOwnProperty.call(obj, prop);
2469
+ }
2470
+
2471
+ /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __webpack_require__(13)))
2472
+
2473
+ /***/ },
2474
+ /* 13 */
2475
+ /***/ function(module, exports) {
2476
+
2477
+ // shim for using process in browser
2478
+ var process = module.exports = {};
2479
+
2480
+ // cached from whatever global is present so that test runners that stub it
2481
+ // don't break things. But we need to wrap it in a try catch in case it is
2482
+ // wrapped in strict mode code which doesn't define any globals. It's inside a
2483
+ // function because try/catches deoptimize in certain engines.
2484
+
2485
+ var cachedSetTimeout;
2486
+ var cachedClearTimeout;
2487
+
2488
+ function defaultSetTimout() {
2489
+ throw new Error('setTimeout has not been defined');
2490
+ }
2491
+ function defaultClearTimeout () {
2492
+ throw new Error('clearTimeout has not been defined');
2493
+ }
2494
+ (function () {
2495
+ try {
2496
+ if (typeof setTimeout === 'function') {
2497
+ cachedSetTimeout = setTimeout;
2498
+ } else {
2499
+ cachedSetTimeout = defaultSetTimout;
2500
+ }
2501
+ } catch (e) {
2502
+ cachedSetTimeout = defaultSetTimout;
2503
+ }
2504
+ try {
2505
+ if (typeof clearTimeout === 'function') {
2506
+ cachedClearTimeout = clearTimeout;
2507
+ } else {
2508
+ cachedClearTimeout = defaultClearTimeout;
2509
+ }
2510
+ } catch (e) {
2511
+ cachedClearTimeout = defaultClearTimeout;
2512
+ }
2513
+ } ())
2514
+ function runTimeout(fun) {
2515
+ if (cachedSetTimeout === setTimeout) {
2516
+ //normal enviroments in sane situations
2517
+ return setTimeout(fun, 0);
2518
+ }
2519
+ // if setTimeout wasn't available but was latter defined
2520
+ if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
2521
+ cachedSetTimeout = setTimeout;
2522
+ return setTimeout(fun, 0);
2523
+ }
2524
+ try {
2525
+ // when when somebody has screwed with setTimeout but no I.E. maddness
2526
+ return cachedSetTimeout(fun, 0);
2527
+ } catch(e){
2528
+ try {
2529
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
2530
+ return cachedSetTimeout.call(null, fun, 0);
2531
+ } catch(e){
2532
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
2533
+ return cachedSetTimeout.call(this, fun, 0);
2534
+ }
2535
+ }
2536
+
2537
+
2538
+ }
2539
+ function runClearTimeout(marker) {
2540
+ if (cachedClearTimeout === clearTimeout) {
2541
+ //normal enviroments in sane situations
2542
+ return clearTimeout(marker);
2543
+ }
2544
+ // if clearTimeout wasn't available but was latter defined
2545
+ if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
2546
+ cachedClearTimeout = clearTimeout;
2547
+ return clearTimeout(marker);
2548
+ }
2549
+ try {
2550
+ // when when somebody has screwed with setTimeout but no I.E. maddness
2551
+ return cachedClearTimeout(marker);
2552
+ } catch (e){
2553
+ try {
2554
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
2555
+ return cachedClearTimeout.call(null, marker);
2556
+ } catch (e){
2557
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
2558
+ // Some versions of I.E. have different rules for clearTimeout vs setTimeout
2559
+ return cachedClearTimeout.call(this, marker);
2560
+ }
2561
+ }
2562
+
2563
+
2564
+
2565
+ }
2566
+ var queue = [];
2567
+ var draining = false;
2568
+ var currentQueue;
2569
+ var queueIndex = -1;
2570
+
2571
+ function cleanUpNextTick() {
2572
+ if (!draining || !currentQueue) {
2573
+ return;
2574
+ }
2575
+ draining = false;
2576
+ if (currentQueue.length) {
2577
+ queue = currentQueue.concat(queue);
2578
+ } else {
2579
+ queueIndex = -1;
2580
+ }
2581
+ if (queue.length) {
2582
+ drainQueue();
2583
+ }
2584
+ }
2585
+
2586
+ function drainQueue() {
2587
+ if (draining) {
2588
+ return;
2589
+ }
2590
+ var timeout = runTimeout(cleanUpNextTick);
2591
+ draining = true;
2592
+
2593
+ var len = queue.length;
2594
+ while(len) {
2595
+ currentQueue = queue;
2596
+ queue = [];
2597
+ while (++queueIndex < len) {
2598
+ if (currentQueue) {
2599
+ currentQueue[queueIndex].run();
2600
+ }
2601
+ }
2602
+ queueIndex = -1;
2603
+ len = queue.length;
2604
+ }
2605
+ currentQueue = null;
2606
+ draining = false;
2607
+ runClearTimeout(timeout);
2608
+ }
2609
+
2610
+ process.nextTick = function (fun) {
2611
+ var args = new Array(arguments.length - 1);
2612
+ if (arguments.length > 1) {
2613
+ for (var i = 1; i < arguments.length; i++) {
2614
+ args[i - 1] = arguments[i];
2615
+ }
2616
+ }
2617
+ queue.push(new Item(fun, args));
2618
+ if (queue.length === 1 && !draining) {
2619
+ runTimeout(drainQueue);
2620
+ }
2621
+ };
2622
+
2623
+ // v8 likes predictible objects
2624
+ function Item(fun, array) {
2625
+ this.fun = fun;
2626
+ this.array = array;
2627
+ }
2628
+ Item.prototype.run = function () {
2629
+ this.fun.apply(null, this.array);
2630
+ };
2631
+ process.title = 'browser';
2632
+ process.browser = true;
2633
+ process.env = {};
2634
+ process.argv = [];
2635
+ process.version = ''; // empty string to avoid regexp issues
2636
+ process.versions = {};
2637
+
2638
+ function noop() {}
2639
+
2640
+ process.on = noop;
2641
+ process.addListener = noop;
2642
+ process.once = noop;
2643
+ process.off = noop;
2644
+ process.removeListener = noop;
2645
+ process.removeAllListeners = noop;
2646
+ process.emit = noop;
2647
+
2648
+ process.binding = function (name) {
2649
+ throw new Error('process.binding is not supported');
2650
+ };
2651
+
2652
+ process.cwd = function () { return '/' };
2653
+ process.chdir = function (dir) {
2654
+ throw new Error('process.chdir is not supported');
2655
+ };
2656
+ process.umask = function() { return 0; };
2657
+
2658
+
2659
+ /***/ },
2660
+ /* 14 */
2661
+ /***/ function(module, exports) {
2662
+
2663
+ module.exports = function isBuffer(arg) {
2664
+ return arg && typeof arg === 'object'
2665
+ && typeof arg.copy === 'function'
2666
+ && typeof arg.fill === 'function'
2667
+ && typeof arg.readUInt8 === 'function';
2668
+ }
2669
+
2670
+ /***/ },
2671
+ /* 15 */
2672
+ /***/ function(module, exports) {
2673
+
2674
+ if (typeof Object.create === 'function') {
2675
+ // implementation from standard node.js 'util' module
2676
+ module.exports = function inherits(ctor, superCtor) {
2677
+ ctor.super_ = superCtor
2678
+ ctor.prototype = Object.create(superCtor.prototype, {
2679
+ constructor: {
2680
+ value: ctor,
2681
+ enumerable: false,
2682
+ writable: true,
2683
+ configurable: true
2684
+ }
2685
+ });
2686
+ };
2687
+ } else {
2688
+ // old school shim for old browsers
2689
+ module.exports = function inherits(ctor, superCtor) {
2690
+ ctor.super_ = superCtor
2691
+ var TempCtor = function () {}
2692
+ TempCtor.prototype = superCtor.prototype
2693
+ ctor.prototype = new TempCtor()
2694
+ ctor.prototype.constructor = ctor
2695
+ }
2696
+ }
2697
+
2698
+
2699
+ /***/ },
2700
+ /* 16 */
2701
+ /***/ function(module, exports, __webpack_require__) {
2702
+
2703
+ 'use strict';
2704
+
2705
+ Object.defineProperty(exports, "__esModule", {
2706
+ value: true
2707
+ });
2708
+
2709
+ 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; }; }();
2710
+
2711
+ var _class, _temp; // weak
2712
+
2713
+ var _looseLeaf = __webpack_require__(1);
2714
+
2715
+ var _looseLeaf2 = _interopRequireDefault(_looseLeaf);
2716
+
2717
+ var _attributeCable = __webpack_require__(2);
2718
+
2719
+ var _attributeCable2 = _interopRequireDefault(_attributeCable);
2720
+
2721
+ var _awaitingAck = __webpack_require__(17);
2722
+
2723
+ var _awaitingAck2 = _interopRequireDefault(_awaitingAck);
2724
+
2725
+ var _awaitingWithBuffer = __webpack_require__(19);
2726
+
2727
+ var _awaitingWithBuffer2 = _interopRequireDefault(_awaitingWithBuffer);
2728
+
2729
+ var _synchronized = __webpack_require__(20);
2730
+
2731
+ var _synchronized2 = _interopRequireDefault(_synchronized);
2732
+
2733
+ var _types = __webpack_require__(21);
2734
+
2735
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
2736
+
2737
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
2738
+
2739
+ var CollaborativeAttribute = (_temp = _class = function () {
2740
+ function CollaborativeAttribute(collaborate, attribute) {
2741
+ _classCallCheck(this, CollaborativeAttribute);
2742
+
2743
+ this.collaborate = collaborate;
2744
+ this.attribute = attribute;
2745
+
2746
+ if (!this.attribute) {
2747
+ throw new Error('You must specify an attribute to collaboratively edit');
2748
+ }
2749
+
2750
+ var event = new _looseLeaf2.default.Events();
2751
+ event.attachHandlers(this);
2752
+ this.documentId = this.collaborate.documentId;
2753
+ this.cable = new _attributeCable2.default(this, this.collaborate.cable, this.attribute);
2754
+ this.state = new _synchronized2.default(this);
2755
+ }
2756
+
2757
+ _createClass(CollaborativeAttribute, [{
2758
+ key: 'destroy',
2759
+ value: function destroy() {
2760
+ return this.cable.destroy();
2761
+ }
2762
+ }, {
2763
+ key: 'localOperation',
2764
+ value: function localOperation(operation) {
2765
+ if (operation.isNoop()) {
2766
+ return;
2767
+ }
2768
+
2769
+ return this.state.localOperation(operation);
2770
+ }
2771
+ }, {
2772
+ key: 'remoteOperation',
2773
+ value: function remoteOperation(data) {
2774
+ this.state.transformRemoteOperation(data);
2775
+ return this.trigger('remoteOperation', data.operation);
2776
+ }
2777
+ }, {
2778
+ key: 'receiveAck',
2779
+ value: function receiveAck(data) {
2780
+ return this.state.receiveAck(data);
2781
+ }
2782
+ }]);
2783
+
2784
+ return CollaborativeAttribute;
2785
+ }(), _class.AwaitingAck = _awaitingAck2.default, _class.AwaitingWithBuffer = _awaitingWithBuffer2.default, _class.Synchronized = _synchronized2.default, _temp);
2786
+ exports.default = CollaborativeAttribute;
2787
+
2788
+ /***/ },
2789
+ /* 17 */
2790
+ /***/ function(module, exports, __webpack_require__) {
2791
+
2792
+ 'use strict';
2793
+
2794
+ Object.defineProperty(exports, "__esModule", {
2795
+ value: true
2796
+ });
2797
+ exports.default = undefined;
2798
+
2799
+ 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; }; }();
2800
+
2801
+ var _ot = __webpack_require__(3);
2802
+
2803
+ var _ot2 = _interopRequireDefault(_ot);
2804
+
2805
+ var _collaborativeAttribute = __webpack_require__(16);
2806
+
2807
+ var _collaborativeAttribute2 = _interopRequireDefault(_collaborativeAttribute);
2808
+
2809
+ var _state = __webpack_require__(18);
2810
+
2811
+ var _state2 = _interopRequireDefault(_state);
2812
+
2813
+ var _awaitingWithBuffer = __webpack_require__(19);
2814
+
2815
+ var _awaitingWithBuffer2 = _interopRequireDefault(_awaitingWithBuffer);
2816
+
2817
+ var _synchronized = __webpack_require__(20);
2818
+
2819
+ var _synchronized2 = _interopRequireDefault(_synchronized);
2820
+
2821
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
2822
+
2823
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
2824
+
2825
+ function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
2826
+
2827
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // weak
2828
+
2829
+
2830
+ var AwaitingAck = function (_State) {
2831
+ _inherits(AwaitingAck, _State);
2832
+
2833
+ function AwaitingAck(collaborativeAttribute, operation) {
2834
+ _classCallCheck(this, AwaitingAck);
2835
+
2836
+ var _this = _possibleConstructorReturn(this, (AwaitingAck.__proto__ || Object.getPrototypeOf(AwaitingAck)).apply(this, arguments));
2837
+
2838
+ _this.operation = operation;
2839
+ return _this;
2840
+ }
2841
+
2842
+ _createClass(AwaitingAck, [{
2843
+ key: 'localOperation',
2844
+ value: function localOperation(operation) {
2845
+ this.collaborativeAttribute.state = new _awaitingWithBuffer2.default(this.collaborativeAttribute, this.operation, operation);
2846
+ }
2847
+ }, {
2848
+ key: 'receiveAck',
2849
+ value: function receiveAck(data) {
2850
+ this.collaborativeAttribute.state = new _synchronized2.default(this.collaborativeAttribute);
2851
+ }
2852
+ }, {
2853
+ key: 'transformRemoteOperation',
2854
+ value: function transformRemoteOperation(data) {
2855
+ var pair = _ot2.default.TextOperation.transform(this.operation, data.operation);
2856
+ this.operation = pair[0];
2857
+ data.operation = pair[1];
2858
+ }
2859
+ }]);
2860
+
2861
+ return AwaitingAck;
2862
+ }(_state2.default);
2863
+
2864
+ exports.default = AwaitingAck;
2865
+ ;
2866
+
2867
+ /***/ },
2868
+ /* 18 */
2869
+ /***/ function(module, exports, __webpack_require__) {
2870
+
2871
+ 'use strict';
2872
+
2873
+ Object.defineProperty(exports, "__esModule", {
2874
+ value: true
2875
+ });
2876
+ exports.default = undefined;
2877
+
2878
+ var _collaborativeAttribute = __webpack_require__(16);
2879
+
2880
+ var _collaborativeAttribute2 = _interopRequireDefault(_collaborativeAttribute);
2881
+
2882
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
2883
+
2884
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } // weak
2885
+
2886
+ var State = function State(collaborativeAttribute) {
2887
+ _classCallCheck(this, State);
2888
+
2889
+ this.collaborativeAttribute = collaborativeAttribute;
2890
+ };
2891
+
2892
+ exports.default = State;
2893
+
2894
+ /***/ },
2895
+ /* 19 */
2896
+ /***/ function(module, exports, __webpack_require__) {
2897
+
2898
+ 'use strict';
2899
+
2900
+ Object.defineProperty(exports, "__esModule", {
2901
+ value: true
2902
+ });
2903
+ exports.default = undefined;
2904
+
2905
+ 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; }; }();
2906
+
2907
+ var _ot = __webpack_require__(3);
2908
+
2909
+ var _ot2 = _interopRequireDefault(_ot);
2910
+
2911
+ var _state = __webpack_require__(18);
2912
+
2913
+ var _state2 = _interopRequireDefault(_state);
2914
+
2915
+ var _awaitingAck = __webpack_require__(17);
2916
+
2917
+ var _awaitingAck2 = _interopRequireDefault(_awaitingAck);
2918
+
2919
+ var _collaborativeAttribute = __webpack_require__(16);
2920
+
2921
+ var _collaborativeAttribute2 = _interopRequireDefault(_collaborativeAttribute);
2922
+
2923
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
2924
+
2925
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
2926
+
2927
+ function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
2928
+
2929
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // weak
2930
+
2931
+ var AwaitingWithBuffer = function (_State) {
2932
+ _inherits(AwaitingWithBuffer, _State);
2933
+
2934
+ function AwaitingWithBuffer(collaborativeAttribute, operation, buffer) {
2935
+ _classCallCheck(this, AwaitingWithBuffer);
2936
+
2937
+ var _this = _possibleConstructorReturn(this, (AwaitingWithBuffer.__proto__ || Object.getPrototypeOf(AwaitingWithBuffer)).apply(this, arguments));
2938
+
2939
+ _this.operation = operation;
2940
+ _this.buffer = buffer;
2941
+ return _this;
2942
+ }
2943
+
2944
+ _createClass(AwaitingWithBuffer, [{
2945
+ key: 'localOperation',
2946
+ value: function localOperation(operation) {
2947
+ this.buffer = this.buffer.compose(operation);
2948
+ }
2949
+ }, {
2950
+ key: 'receiveAck',
2951
+ value: function receiveAck(data) {
2952
+ this.collaborativeAttribute.cable.sendOperation({
2953
+ operation: this.buffer
2954
+ });
2955
+
2956
+ this.collaborativeAttribute.state = new _awaitingAck2.default(this.collaborativeAttribute, this.buffer);
2957
+ }
2958
+ }, {
2959
+ key: 'transformRemoteOperation',
2960
+ value: function transformRemoteOperation(data) {
2961
+ var pair = _ot2.default.TextOperation.transform(this.operation, data.operation);
2962
+ this.operation = pair[0];
2963
+ data.operation = pair[1];
2964
+ pair = _ot2.default.TextOperation.transform(this.buffer, data.operation);
2965
+ this.buffer = pair[0];
2966
+ data.operation = pair[1];
2967
+ }
2968
+ }]);
2969
+
2970
+ return AwaitingWithBuffer;
2971
+ }(_state2.default);
2972
+
2973
+ exports.default = AwaitingWithBuffer;
2974
+
2975
+ /***/ },
2976
+ /* 20 */
2977
+ /***/ function(module, exports, __webpack_require__) {
2978
+
2979
+ 'use strict';
2980
+
2981
+ Object.defineProperty(exports, "__esModule", {
2982
+ value: true
2983
+ });
2984
+ exports.default = undefined;
2985
+
2986
+ 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; }; }();
2987
+
2988
+ var _state = __webpack_require__(18);
2989
+
2990
+ var _state2 = _interopRequireDefault(_state);
2991
+
2992
+ var _awaitingAck = __webpack_require__(17);
2993
+
2994
+ var _awaitingAck2 = _interopRequireDefault(_awaitingAck);
2995
+
2996
+ var _collaborativeAttribute = __webpack_require__(16);
2997
+
2998
+ var _collaborativeAttribute2 = _interopRequireDefault(_collaborativeAttribute);
2999
+
3000
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
3001
+
3002
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
3003
+
3004
+ function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
3005
+
3006
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // weak
3007
+
3008
+ var Synchronized = function (_State) {
3009
+ _inherits(Synchronized, _State);
3010
+
3011
+ function Synchronized() {
3012
+ _classCallCheck(this, Synchronized);
3013
+
3014
+ return _possibleConstructorReturn(this, (Synchronized.__proto__ || Object.getPrototypeOf(Synchronized)).apply(this, arguments));
3015
+ }
3016
+
3017
+ _createClass(Synchronized, [{
3018
+ key: 'localOperation',
3019
+ value: function localOperation(operation) {
3020
+ this.collaborativeAttribute.cable.sendOperation({
3021
+ operation: operation
3022
+ });
3023
+
3024
+ this.collaborativeAttribute.state = new _awaitingAck2.default(this.collaborativeAttribute, operation);
3025
+ }
3026
+ }, {
3027
+ key: 'receiveAck',
3028
+ value: function receiveAck(data) {
3029
+ console.error('Received an ack for version ' + data.version + ' whilst in Synchronized state.');
3030
+ }
3031
+ }, {
3032
+ key: 'transformRemoteOperation',
3033
+ value: function transformRemoteOperation(data) {}
3034
+ }]);
3035
+
3036
+ return Synchronized;
3037
+ }(_state2.default);
3038
+
3039
+ exports.default = Synchronized;
3040
+
3041
+ /***/ },
3042
+ /* 21 */
3043
+ /***/ function(module, exports) {
3044
+
3045
+ "use strict";
3046
+
3047
+ /***/ },
3048
+ /* 22 */
3049
+ /***/ function(module, exports, __webpack_require__) {
3050
+
3051
+ 'use strict';
3052
+
3053
+ Object.defineProperty(exports, "__esModule", {
3054
+ value: true
3055
+ });
3056
+ exports.default = undefined;
3057
+
3058
+ 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; }; }(); // weak
3059
+
3060
+
3061
+ var _looseLeaf = __webpack_require__(1);
3062
+
3063
+ var _looseLeaf2 = _interopRequireDefault(_looseLeaf);
3064
+
3065
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
3066
+
3067
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
3068
+
3069
+ var Cable = function () {
3070
+ function Cable(collaborate, cable, channel) {
3071
+ _classCallCheck(this, Cable);
3072
+
3073
+ this.collaborate = collaborate;
3074
+ this.unackedOps = [];
3075
+ this.attributeCables = {};
3076
+ this.documentId = this.collaborate.documentId;
3077
+
3078
+ this.subscription = cable.subscriptions.create({
3079
+ channel: channel,
3080
+ documentId: this.documentId
3081
+ }, {
3082
+ connected: this.connected.bind(this),
3083
+ received: this.received.bind(this)
3084
+ });
3085
+ }
3086
+
3087
+ _createClass(Cable, [{
3088
+ key: 'destroy',
3089
+ value: function destroy() {
3090
+ this.subscription.unsubscribe();
3091
+ }
3092
+ }, {
3093
+ key: 'addAttribute',
3094
+ value: function addAttribute(attribute, attributeCable) {
3095
+ this.attributeCables[attribute] = attributeCable;
3096
+ }
3097
+ }, {
3098
+ key: 'removeAttribute',
3099
+ value: function removeAttribute(attribute) {
3100
+ delete this.attributeCables[attribute];
3101
+ }
3102
+ }, {
3103
+ key: 'connected',
3104
+ value: function connected() {
3105
+ var _this = this;
3106
+
3107
+ return setTimeout(function () {
3108
+ _this.subscription.perform('document', {
3109
+ id: _this.documentId
3110
+ });
3111
+
3112
+ return console.info('Document Setup Complete');
3113
+ }, 200);
3114
+ }
3115
+ }, {
3116
+ key: 'received',
3117
+ value: function received(data) {
3118
+ switch (data.action) {
3119
+ case 'subscribed':
3120
+ return this.subscribed(data);
3121
+ case 'attribute':
3122
+ return this.receiveAttribute(data);
3123
+ case 'operation':
3124
+ return this.receiveOperation(data);
3125
+ default:
3126
+ console.warn(data.action + ' unhandled');
3127
+ return console.info(data);
3128
+ }
3129
+ }
3130
+ }, {
3131
+ key: 'sendOperation',
3132
+ value: function sendOperation(data) {
3133
+ data.client_id = this.clientId;
3134
+ data.document_id = this.documentId;
3135
+ return this.subscription.perform('operation', data);
3136
+ }
3137
+ }, {
3138
+ key: 'subscribed',
3139
+ value: function subscribed(data) {
3140
+ this.clientId = data.client_id;
3141
+ console.log('Set client ID as ' + this.clientId);
3142
+ }
3143
+ }, {
3144
+ key: 'receiveAttribute',
3145
+ value: function receiveAttribute(data) {
3146
+ if (data.document_id !== this.documentId) {
3147
+ return;
3148
+ }
3149
+
3150
+ var attributeCable = this.attributeCables[data.attribute];
3151
+
3152
+ if (!attributeCable) {
3153
+ console.warn('Received collaboration message for ' + data.attribute + ', but it has not been registered');
3154
+
3155
+ return;
3156
+ }
3157
+
3158
+ return attributeCable.receiveAttribute(data);
3159
+ }
3160
+ }, {
3161
+ key: 'receiveOperation',
3162
+ value: function receiveOperation(data) {
3163
+ if (data.document_id !== this.documentId) {
3164
+ return;
3165
+ }
3166
+
3167
+ var attributeCable = this.attributeCables[data.attribute];
3168
+
3169
+ if (!attributeCable) {
3170
+ console.warn('Received collaboration message for ' + data.attribute + ', but it has not been registered');
3171
+
3172
+ return;
3173
+ }
3174
+
3175
+ return attributeCable.receiveOperation(data);
3176
+ }
3177
+ }]);
3178
+
3179
+ return Cable;
3180
+ }();
3181
+
3182
+ exports.default = Cable;
3183
+ ;
3184
+
3185
+ /***/ },
3186
+ /* 23 */
3187
+ /***/ function(module, exports, __webpack_require__) {
3188
+
3189
+ 'use strict';
3190
+
3191
+ Object.defineProperty(exports, "__esModule", {
3192
+ value: true
3193
+ });
3194
+
3195
+ var _textareaAdapter = __webpack_require__(24);
3196
+
3197
+ var _textareaAdapter2 = _interopRequireDefault(_textareaAdapter);
3198
+
3199
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
3200
+
3201
+ exports.default = {
3202
+ TextAreaAdapter: _textareaAdapter2.default
3203
+ };
3204
+
3205
+ /***/ },
3206
+ /* 24 */
3207
+ /***/ function(module, exports, __webpack_require__) {
3208
+
3209
+ 'use strict';
3210
+
3211
+ Object.defineProperty(exports, "__esModule", {
3212
+ value: true
3213
+ });
3214
+ exports.default = undefined;
3215
+
3216
+ 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; }; }(); // weak
3217
+
3218
+ var _ot = __webpack_require__(3);
3219
+
3220
+ var _ot2 = _interopRequireDefault(_ot);
3221
+
3222
+ var _collaborativeAttribute = __webpack_require__(16);
3223
+
3224
+ var _collaborativeAttribute2 = _interopRequireDefault(_collaborativeAttribute);
3225
+
3226
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
3227
+
3228
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
3229
+
3230
+ var TextAreaAdapter = function () {
3231
+ function TextAreaAdapter(collaborativeAttribute, textarea) {
3232
+ _classCallCheck(this, TextAreaAdapter);
3233
+
3234
+ this.collaborativeAttribute = collaborativeAttribute;
3235
+ this.$textarea = textarea;
3236
+ this.oldContent = this.$textarea.value;
3237
+
3238
+ var _arr = ['keyup', 'cut', 'paste'];
3239
+ for (var _i = 0; _i < _arr.length; _i++) {
3240
+ var eventName = _arr[_i];
3241
+ this.$textarea.addEventListener(eventName, this.textChange.bind(this));
3242
+ }
3243
+
3244
+ this.collaborativeAttribute.on('remoteOperation', this.applyRemoteOperation.bind(this));
3245
+ }
3246
+
3247
+ _createClass(TextAreaAdapter, [{
3248
+ key: 'textChange',
3249
+ value: function textChange() {
3250
+ var newContent = this.$textarea.value;
3251
+ var operation = this.operationFromTextChange(this.oldContent, newContent);
3252
+ this.oldContent = newContent;
3253
+ return this.collaborativeAttribute.localOperation(operation);
3254
+ }
3255
+ }, {
3256
+ key: 'operationFromTextChange',
3257
+ value: function operationFromTextChange(oldContent, newContent) {
3258
+ var op = new _ot2.default.TextOperation();
3259
+
3260
+ if (oldContent === newContent) {
3261
+ return op;
3262
+ }
3263
+
3264
+ var commonStart = 0;
3265
+
3266
+ while (oldContent.charAt(commonStart) === newContent.charAt(commonStart)) {
3267
+ commonStart++;
3268
+ }
3269
+
3270
+ var commonEnd = 0;
3271
+
3272
+ while (oldContent.charAt(oldContent.length - 1 - commonEnd) === newContent.charAt(newContent.length - 1 - commonEnd)) {
3273
+ if (commonEnd + commonStart === oldContent.length) {
3274
+ break;
3275
+ }
3276
+
3277
+ if (commonEnd + commonStart === newContent.length) {
3278
+ break;
3279
+ }
3280
+
3281
+ commonEnd++;
3282
+ }
3283
+
3284
+ op.retain(commonStart);
3285
+
3286
+ if (oldContent.length !== commonStart + commonEnd) {
3287
+ op.delete(oldContent.length - commonStart - commonEnd);
3288
+ }
3289
+
3290
+ if (newContent.length !== commonStart + commonEnd) {
3291
+ op.insert(newContent.slice(commonStart, newContent.length - commonEnd));
3292
+ }
3293
+
3294
+ op.retain(commonEnd);
3295
+ return op;
3296
+ }
3297
+ }, {
3298
+ key: 'applyRemoteOperation',
3299
+ value: function applyRemoteOperation(operation) {
3300
+ var content = operation.apply(this.oldContent);
3301
+ var selectionStart = this.$textarea.selectionStart;
3302
+ var selectionEnd = this.$textarea.selectionEnd;
3303
+ this.$textarea.value = content;
3304
+ this.$textarea.setSelectionRange(selectionStart, selectionEnd);
3305
+ this.oldContent = content;
3306
+ }
3307
+ }]);
3308
+
3309
+ return TextAreaAdapter;
3310
+ }();
3311
+
3312
+ exports.default = TextAreaAdapter;
3313
+
3314
+ /***/ },
3315
+ /* 25 */
3316
+ /***/ function(module, exports) {
3317
+
3318
+ "use strict";
3319
+
3320
+ Object.defineProperty(exports, "__esModule", {
3321
+ value: true
3322
+ });
3323
+
3324
+ 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; }; }();
3325
+
3326
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
3327
+
3328
+ // weak
3329
+
3330
+ var Events = function () {
3331
+ function Events(object) {
3332
+ _classCallCheck(this, Events);
3333
+
3334
+ this._listeners = [];
3335
+ }
3336
+
3337
+ _createClass(Events, [{
3338
+ key: "attachHandlers",
3339
+ value: function attachHandlers(object) {
3340
+ object.on = this.on.bind(this);
3341
+ object.off = this.off.bind(this);
3342
+ object.trigger = this.trigger.bind(this);
3343
+ }
3344
+ }, {
3345
+ key: "on",
3346
+ value: function on(eventName, callback) {
3347
+ this._listeners[eventName] || (this._listeners[eventName] = []);
3348
+ return this._listeners[eventName].push(callback);
3349
+ }
3350
+ }, {
3351
+ key: "off",
3352
+ value: function off(eventName, callback) {
3353
+ if (!callback) {
3354
+ delete this._listeners[eventName];
3355
+ return;
3356
+ }
3357
+
3358
+ var index = this._listeners[eventName].indexOf(callback);
3359
+ return this._listeners.splice(index, 1);
3360
+ }
3361
+ }, {
3362
+ key: "trigger",
3363
+ value: function trigger(eventName) {
3364
+ for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
3365
+ args[_key - 1] = arguments[_key];
3366
+ }
3367
+
3368
+ var listeners = this._listeners[eventName] || [];
3369
+
3370
+ return function () {
3371
+ var _iteratorNormalCompletion = true;
3372
+ var _didIteratorError = false;
3373
+ var _iteratorError = undefined;
3374
+
3375
+ try {
3376
+ for (var _iterator = listeners[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
3377
+ var callback = _step.value;
3378
+
3379
+ callback.apply(undefined, args);
3380
+ }
3381
+ } catch (err) {
3382
+ _didIteratorError = true;
3383
+ _iteratorError = err;
3384
+ } finally {
3385
+ try {
3386
+ if (!_iteratorNormalCompletion && _iterator.return) {
3387
+ _iterator.return();
3388
+ }
3389
+ } finally {
3390
+ if (_didIteratorError) {
3391
+ throw _iteratorError;
3392
+ }
3393
+ }
3394
+ }
3395
+ }();
3396
+ }
3397
+ }]);
3398
+
3399
+ return Events;
3400
+ }();
3401
+
3402
+ exports.default = Events;
3403
+ ;
3404
+
3405
+ /***/ }
3406
+ /******/ ])
3407
+ });
3408
+ ;