loose_leaf 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ ;