Advertisement
Guest User

data.js

a guest
Feb 9th, 2016
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  2. (function (process){
  3. // Copyright Joyent, Inc. and other Node contributors.
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a
  6. // copy of this software and associated documentation files (the
  7. // "Software"), to deal in the Software without restriction, including
  8. // without limitation the rights to use, copy, modify, merge, publish,
  9. // distribute, sublicense, and/or sell copies of the Software, and to permit
  10. // persons to whom the Software is furnished to do so, subject to the
  11. // following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be included
  14. // in all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  17. // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  19. // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  20. // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  21. // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  22. // USE OR OTHER DEALINGS IN THE SOFTWARE.
  23.  
  24. // resolves . and .. elements in a path array with directory names there
  25. // must be no slashes, empty elements, or device names (c:\) in the array
  26. // (so also no leading and trailing slashes - it does not distinguish
  27. // relative and absolute paths)
  28. function normalizeArray(parts, allowAboveRoot) {
  29.   // if the path tries to go above the root, `up` ends up > 0
  30.   var up = 0;
  31.   for (var i = parts.length - 1; i >= 0; i--) {
  32.     var last = parts[i];
  33.     if (last === '.') {
  34.       parts.splice(i, 1);
  35.     } else if (last === '..') {
  36.       parts.splice(i, 1);
  37.       up++;
  38.     } else if (up) {
  39.       parts.splice(i, 1);
  40.       up--;
  41.     }
  42.   }
  43.  
  44.   // if the path is allowed to go above the root, restore leading ..s
  45.   if (allowAboveRoot) {
  46.     for (; up--; up) {
  47.       parts.unshift('..');
  48.     }
  49.   }
  50.  
  51.   return parts;
  52. }
  53.  
  54. // Split a filename into [root, dir, basename, ext], unix version
  55. // 'root' is just a slash, or nothing.
  56. var splitPathRe =
  57.     /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
  58. var splitPath = function(filename) {
  59.   return splitPathRe.exec(filename).slice(1);
  60. };
  61.  
  62. // path.resolve([from ...], to)
  63. // posix version
  64. exports.resolve = function() {
  65.   var resolvedPath = '',
  66.       resolvedAbsolute = false;
  67.  
  68.   for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
  69.     var path = (i >= 0) ? arguments[i] : process.cwd();
  70.  
  71.     // Skip empty and invalid entries
  72.     if (typeof path !== 'string') {
  73.       throw new TypeError('Arguments to path.resolve must be strings');
  74.     } else if (!path) {
  75.       continue;
  76.     }
  77.  
  78.     resolvedPath = path + '/' + resolvedPath;
  79.     resolvedAbsolute = path.charAt(0) === '/';
  80.   }
  81.  
  82.   // At this point the path should be resolved to a full absolute path, but
  83.   // handle relative paths to be safe (might happen when process.cwd() fails)
  84.  
  85.   // Normalize the path
  86.   resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
  87.     return !!p;
  88.   }), !resolvedAbsolute).join('/');
  89.  
  90.   return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
  91. };
  92.  
  93. // path.normalize(path)
  94. // posix version
  95. exports.normalize = function(path) {
  96.   var isAbsolute = exports.isAbsolute(path),
  97.       trailingSlash = substr(path, -1) === '/';
  98.  
  99.   // Normalize the path
  100.   path = normalizeArray(filter(path.split('/'), function(p) {
  101.     return !!p;
  102.   }), !isAbsolute).join('/');
  103.  
  104.   if (!path && !isAbsolute) {
  105.     path = '.';
  106.   }
  107.   if (path && trailingSlash) {
  108.     path += '/';
  109.   }
  110.  
  111.   return (isAbsolute ? '/' : '') + path;
  112. };
  113.  
  114. // posix version
  115. exports.isAbsolute = function(path) {
  116.   return path.charAt(0) === '/';
  117. };
  118.  
  119. // posix version
  120. exports.join = function() {
  121.   var paths = Array.prototype.slice.call(arguments, 0);
  122.   return exports.normalize(filter(paths, function(p, index) {
  123.     if (typeof p !== 'string') {
  124.       throw new TypeError('Arguments to path.join must be strings');
  125.     }
  126.     return p;
  127.   }).join('/'));
  128. };
  129.  
  130.  
  131. // path.relative(from, to)
  132. // posix version
  133. exports.relative = function(from, to) {
  134.   from = exports.resolve(from).substr(1);
  135.   to = exports.resolve(to).substr(1);
  136.  
  137.   function trim(arr) {
  138.     var start = 0;
  139.     for (; start < arr.length; start++) {
  140.       if (arr[start] !== '') break;
  141.     }
  142.  
  143.     var end = arr.length - 1;
  144.     for (; end >= 0; end--) {
  145.       if (arr[end] !== '') break;
  146.     }
  147.  
  148.     if (start > end) return [];
  149.     return arr.slice(start, end - start + 1);
  150.   }
  151.  
  152.   var fromParts = trim(from.split('/'));
  153.   var toParts = trim(to.split('/'));
  154.  
  155.   var length = Math.min(fromParts.length, toParts.length);
  156.   var samePartsLength = length;
  157.   for (var i = 0; i < length; i++) {
  158.     if (fromParts[i] !== toParts[i]) {
  159.       samePartsLength = i;
  160.       break;
  161.     }
  162.   }
  163.  
  164.   var outputParts = [];
  165.   for (var i = samePartsLength; i < fromParts.length; i++) {
  166.     outputParts.push('..');
  167.   }
  168.  
  169.   outputParts = outputParts.concat(toParts.slice(samePartsLength));
  170.  
  171.   return outputParts.join('/');
  172. };
  173.  
  174. exports.sep = '/';
  175. exports.delimiter = ':';
  176.  
  177. exports.dirname = function(path) {
  178.   var result = splitPath(path),
  179.       root = result[0],
  180.       dir = result[1];
  181.  
  182.   if (!root && !dir) {
  183.     // No dirname whatsoever
  184.     return '.';
  185.   }
  186.  
  187.   if (dir) {
  188.     // It has a dirname, strip trailing slash
  189.     dir = dir.substr(0, dir.length - 1);
  190.   }
  191.  
  192.   return root + dir;
  193. };
  194.  
  195.  
  196. exports.basename = function(path, ext) {
  197.   var f = splitPath(path)[2];
  198.   // TODO: make this comparison case-insensitive on windows?
  199.   if (ext && f.substr(-1 * ext.length) === ext) {
  200.     f = f.substr(0, f.length - ext.length);
  201.   }
  202.   return f;
  203. };
  204.  
  205.  
  206. exports.extname = function(path) {
  207.   return splitPath(path)[3];
  208. };
  209.  
  210. function filter (xs, f) {
  211.     if (xs.filter) return xs.filter(f);
  212.     var res = [];
  213.     for (var i = 0; i < xs.length; i++) {
  214.         if (f(xs[i], i, xs)) res.push(xs[i]);
  215.     }
  216.     return res;
  217. }
  218.  
  219. // String.prototype.substr - negative index don't work in IE8
  220. var substr = 'ab'.substr(-1) === 'b'
  221.     ? function (str, start, len) { return str.substr(start, len) }
  222.     : function (str, start, len) {
  223.         if (start < 0) start = str.length + start;
  224.         return str.substr(start, len);
  225.     }
  226. ;
  227.  
  228. }).call(this,require('_process'))
  229. },{"_process":2}],2:[function(require,module,exports){
  230. // shim for using process in browser
  231.  
  232. var process = module.exports = {};
  233. var queue = [];
  234. var draining = false;
  235. var currentQueue;
  236. var queueIndex = -1;
  237.  
  238. function cleanUpNextTick() {
  239.     draining = false;
  240.     if (currentQueue.length) {
  241.         queue = currentQueue.concat(queue);
  242.     } else {
  243.         queueIndex = -1;
  244.     }
  245.     if (queue.length) {
  246.         drainQueue();
  247.     }
  248. }
  249.  
  250. function drainQueue() {
  251.     if (draining) {
  252.         return;
  253.     }
  254.     var timeout = setTimeout(cleanUpNextTick);
  255.     draining = true;
  256.  
  257.     var len = queue.length;
  258.     while(len) {
  259.         currentQueue = queue;
  260.         queue = [];
  261.         while (++queueIndex < len) {
  262.             if (currentQueue) {
  263.                 currentQueue[queueIndex].run();
  264.             }
  265.         }
  266.         queueIndex = -1;
  267.         len = queue.length;
  268.     }
  269.     currentQueue = null;
  270.     draining = false;
  271.     clearTimeout(timeout);
  272. }
  273.  
  274. process.nextTick = function (fun) {
  275.     var args = new Array(arguments.length - 1);
  276.     if (arguments.length > 1) {
  277.         for (var i = 1; i < arguments.length; i++) {
  278.             args[i - 1] = arguments[i];
  279.         }
  280.     }
  281.     queue.push(new Item(fun, args));
  282.     if (queue.length === 1 && !draining) {
  283.         setTimeout(drainQueue, 0);
  284.     }
  285. };
  286.  
  287. // v8 likes predictible objects
  288. function Item(fun, array) {
  289.     this.fun = fun;
  290.     this.array = array;
  291. }
  292. Item.prototype.run = function () {
  293.     this.fun.apply(null, this.array);
  294. };
  295. process.title = 'browser';
  296. process.browser = true;
  297. process.env = {};
  298. process.argv = [];
  299. process.version = ''; // empty string to avoid regexp issues
  300. process.versions = {};
  301.  
  302. function noop() {}
  303.  
  304. process.on = noop;
  305. process.addListener = noop;
  306. process.once = noop;
  307. process.off = noop;
  308. process.removeListener = noop;
  309. process.removeAllListeners = noop;
  310. process.emit = noop;
  311.  
  312. process.binding = function (name) {
  313.     throw new Error('process.binding is not supported');
  314. };
  315.  
  316. process.cwd = function () { return '/' };
  317. process.chdir = function (dir) {
  318.     throw new Error('process.chdir is not supported');
  319. };
  320. process.umask = function() { return 0; };
  321.  
  322. },{}],3:[function(require,module,exports){
  323. var fTextSettingsResource = require("./fTextSettingsResource");
  324. var fTextAsset = require("./fTextAsset");
  325.  
  326. SupCore.system.data.registerResource("fTextSettings", fTextSettingsResource.default);
  327. SupCore.system.data.registerAssetClass("fText", fTextAsset.default);
  328.  
  329. },{"./fTextAsset":4,"./fTextSettingsResource":5}],4:[function(require,module,exports){
  330. var __extends = (this && this.__extends) || function (d, b) {
  331.     for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
  332.     function __() { this.constructor = d; }
  333.     d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  334. };
  335. var OT = require("operational-transform");
  336.  
  337. var path = require("path");
  338. var fTextAsset = (function (_super) {
  339.     __extends(fTextAsset, _super);
  340.     // called from the editor onAssetReceived() as well as on server startup
  341.     function fTextAsset(id, pub, serverData) {
  342.         _super.call(this, id, pub, fTextAsset.schema, serverData);
  343.     }
  344.     // called on asset creation
  345.     // options contain the asset's name
  346.     fTextAsset.prototype.init = function (options, callback) {
  347.         var defaultContent = "";
  348.         this.pub = {
  349.             text: defaultContent,
  350.             draft: defaultContent,
  351.             revisionId: 0,
  352.         };
  353.         _super.prototype.init.call(this, options, callback);
  354.     };
  355.     fTextAsset.prototype.setup = function () {
  356.         this.document = new OT.Document(this.pub.draft, this.pub.revisionId);
  357.         this.hasDraft = this.pub.text !== this.pub.draft;
  358.     };
  359.     fTextAsset.prototype.restore = function () {
  360.         if (this.hasDraft)
  361.             this.emit("setBadge", "draft", "info");
  362.     };
  363.     fTextAsset.prototype.destroy = function (callback) {
  364.         callback();
  365.     };
  366.     // called on server startup
  367.     fTextAsset.prototype.load = function (assetPath) {
  368.         // NOTE: We must not set this.pub with temporary values here, otherwise
  369.         // the asset will be considered loaded by Dictionary.acquire
  370.         // and the acquire callback will be called immediately
  371.         var _this = this;
  372.         fs.readFile(path.join(assetPath, "ftext.txt"), { encoding: "utf8" }, function (err, text) {
  373.             fs.readFile(path.join(assetPath, "draft.txt"), { encoding: "utf8" }, function (err, draft) {
  374.                 _this.pub = { revisionId: 0, text: text, draft: (draft != null) ? draft : text };
  375.                 _this.setup();
  376.                 _this.emit("load");
  377.             });
  378.         });
  379.     };
  380.     // called when it is time to write the asset on disk, not when the user save the asset from the editor
  381.     fTextAsset.prototype.save = function (assetPath, callback) {
  382.         var _this = this;
  383.         fs.writeFile(path.join(assetPath, "ftext.txt"), this.pub.text, { encoding: "utf8" }, function (err) {
  384.             if (err != null) {
  385.                 callback(err);
  386.                 return;
  387.             }
  388.             if (_this.hasDraft) {
  389.                 fs.writeFile(path.join(assetPath, "draft.txt"), _this.pub.draft, { encoding: "utf8" }, callback);
  390.             }
  391.             else {
  392.                 // delete the draft.txt file if there is no draft to save and the file exists
  393.                 fs.unlink(path.join(assetPath, "draft.txt"), function (err) {
  394.                     if (err != null && err.code !== "ENOENT") {
  395.                         callback(err);
  396.                         return;
  397.                     }
  398.                     callback(null);
  399.                 });
  400.             }
  401.         });
  402.     };
  403.     fTextAsset.prototype.server_editText = function (client, operationData, revisionIndex, callback) {
  404.         if (operationData.userId !== client.id) {
  405.             callback("Invalid client id");
  406.             return;
  407.         }
  408.         var operation = new OT.TextOperation();
  409.         if (!operation.deserialize(operationData)) {
  410.             callback("Invalid operation data");
  411.             return;
  412.         }
  413.         try {
  414.             operation = this.document.apply(operation, revisionIndex);
  415.         }
  416.         catch (err) {
  417.             callback("Operation can't be applied");
  418.             return;
  419.         }
  420.         this.pub.draft = this.document.text;
  421.         this.pub.revisionId++;
  422.         callback(null, operation.serialize(), this.document.getRevisionId() - 1);
  423.         if (!this.hasDraft) {
  424.             this.hasDraft = true;
  425.             this.emit("setBadge", "draft", "info");
  426.         }
  427.         this.emit("change");
  428.     };
  429.     fTextAsset.prototype.client_editText = function (operationData, revisionIndex) {
  430.         var operation = new OT.TextOperation();
  431.         operation.deserialize(operationData);
  432.         this.document.apply(operation, revisionIndex);
  433.         this.pub.draft = this.document.text;
  434.         this.pub.revisionId++;
  435.     };
  436.     fTextAsset.prototype.server_saveText = function (client, callback) {
  437.         this.pub.text = this.pub.draft;
  438.         callback(null);
  439.         if (this.hasDraft) {
  440.             this.hasDraft = false;
  441.             this.emit("clearBadge", "draft");
  442.         }
  443.         this.emit("change");
  444.     };
  445.     fTextAsset.prototype.client_saveText = function () { this.pub.text = this.pub.draft; };
  446.     fTextAsset.schema = {
  447.         text: { type: "string" },
  448.         draft: { type: "string" },
  449.         revisionId: { type: "integer" },
  450.     };
  451.     return fTextAsset;
  452. })(SupCore.Data.Base.Asset);
  453. Object.defineProperty(exports, "__esModule", { value: true });
  454. exports.default = fTextAsset;
  455.  
  456. },{"operational-transform":9,"path":1}],5:[function(require,module,exports){
  457. var __extends = (this && this.__extends) || function (d, b) {
  458.     for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
  459.     function __() { this.constructor = d; }
  460.     d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  461. };
  462. var fTextSettingsResource = (function (_super) {
  463.     __extends(fTextSettingsResource, _super);
  464.     function fTextSettingsResource(id, pub, serverData) {
  465.         _super.call(this, id, pub, fTextSettingsResource.schema, serverData);
  466.     }
  467.     fTextSettingsResource.prototype.init = function (callback) {
  468.         var pub = {};
  469.         for (var name_1 in fTextSettingsResource.defaultValues) {
  470.             pub[name_1] = fTextSettingsResource.defaultValues[name_1];
  471.         }
  472.         this.pub = pub;
  473.         _super.prototype.init.call(this, callback);
  474.     };
  475.     fTextSettingsResource.schema = {
  476.         theme: { type: "string", mutable: true },
  477.         customTheme: { type: "string", mutable: true },
  478.         tabSize: { type: "number", min: 1, max: 8, mutable: true },
  479.         indentWithTabs: { type: "boolean", mutable: true },
  480.         keyMap: { type: "enum", items: ["sublime", "vim", "emacs"], mutable: true },
  481.         styleActiveLine: { type: "boolean", mutable: true },
  482.         showTrailingSpace: { type: "boolean", mutable: true },
  483.         autoCloseBrackets: { type: "boolean", mutable: true },
  484.         matchTags: { type: "boolean", mutable: true },
  485.         highlightSelectionMatches: { type: "boolean", mutable: true },
  486.         lint_json: { type: "boolean", mutable: true },
  487.         lint_cson: { type: "boolean", mutable: true },
  488.         lint_javascript: { type: "boolean", mutable: true },
  489.         lint_jade: { type: "boolean", mutable: true },
  490.         lint_stylus: { type: "boolean", mutable: true },
  491.         lint_css: { type: "boolean", mutable: true },
  492.         lint_yaml: { type: "boolean", mutable: true },
  493.     };
  494.     fTextSettingsResource.defaultValues = {
  495.         theme: "default",
  496.         customTheme: "",
  497.         tabSize: 2,
  498.         indentWithTabs: true,
  499.         keyMap: "sublime",
  500.         styleActiveLine: true,
  501.         autoCloseBrackets: true,
  502.         showTrailingSpace: true,
  503.         matchTags: true,
  504.         highlightSelectionMatches: true,
  505.         lint_json: true,
  506.         lint_cson: true,
  507.         lint_javascript: true,
  508.         lint_jade: true,
  509.         lint_stylus: true,
  510.         lint_css: true,
  511.         lint_yaml: true,
  512.     }; // note 07/09/15 for some reason, not having a coma after the last entry would cause the defaultValues not to be read in the settings editor...
  513.     return fTextSettingsResource;
  514. })(SupCore.Data.Base.Resource);
  515. Object.defineProperty(exports, "__esModule", { value: true });
  516. exports.default = fTextSettingsResource;
  517.  
  518. },{}],6:[function(require,module,exports){
  519. var OT = require("./index");
  520. var Document = (function () {
  521.     function Document(text, revisionId) {
  522.         if (text === void 0) { text = ""; }
  523.         if (revisionId === void 0) { revisionId = 0; }
  524.         this.operations = [];
  525.         this.text = text;
  526.         this._refRevisionId = revisionId;
  527.     }
  528.     Document.prototype.apply = function (newOperation, revision) {
  529.         revision -= this._refRevisionId;
  530.         // Should't happen
  531.         if (revision > this.operations.length)
  532.             throw new Error("The operation base revision is greater than the document revision");
  533.         if (revision < this.operations.length) {
  534.             // Conflict!
  535.             var missedOperations = new OT.TextOperation(this.operations[revision].userId);
  536.             missedOperations.targetLength = this.operations[revision].baseLength;
  537.             for (var index = revision; index < this.operations.length; index++)
  538.                 missedOperations = missedOperations.compose(this.operations[index]);
  539.             newOperation = missedOperations.transform(newOperation)[1];
  540.         }
  541.         this.text = newOperation.apply(this.text);
  542.         this.operations.push(newOperation.clone());
  543.         return newOperation;
  544.     };
  545.     Document.prototype.getRevisionId = function () { return this.operations.length + this._refRevisionId; };
  546.     return Document;
  547. })();
  548. module.exports = Document;
  549.  
  550. },{"./index":9}],7:[function(require,module,exports){
  551. var TextOp = (function () {
  552.     function TextOp(type, attributes) {
  553.         this.type = type;
  554.         this.attributes = attributes;
  555.     }
  556.     return TextOp;
  557. })();
  558. module.exports = TextOp;
  559.  
  560. },{}],8:[function(require,module,exports){
  561. var OT = require("./index");
  562. var TextOperation = (function () {
  563.     function TextOperation(userId) {
  564.         this.ops = [];
  565.         // An operation's baseLength is the length of every string the operation
  566.         // can be applied to.
  567.         this.baseLength = 0;
  568.         // The targetLength is the length of every string that results from applying
  569.         // the operation on a valid input string.
  570.         this.targetLength = 0;
  571.         this.userId = userId;
  572.     }
  573.     TextOperation.prototype.serialize = function () {
  574.         var ops = [];
  575.         for (var _i = 0, _a = this.ops; _i < _a.length; _i++) {
  576.             var op = _a[_i];
  577.             ops.push({ type: op.type, attributes: op.attributes });
  578.         }
  579.         return { ops: ops, userId: this.userId };
  580.     };
  581.     TextOperation.prototype.deserialize = function (data) {
  582.         if (data == null)
  583.             return false;
  584.         this.userId = data.userId;
  585.         for (var _i = 0, _a = data.ops; _i < _a.length; _i++) {
  586.             var op = _a[_i];
  587.             switch (op.type) {
  588.                 case "retain":
  589.                     this.retain(op.attributes.amount);
  590.                     break;
  591.                 case "insert":
  592.                     this.insert(op.attributes.text);
  593.                     break;
  594.                 case "delete":
  595.                     this.delete(op.attributes.text);
  596.                     break;
  597.                 default: return false;
  598.             }
  599.         }
  600.         return true;
  601.     };
  602.     TextOperation.prototype.retain = function (amount) {
  603.         if (typeof (amount) !== "number" || amount <= 0)
  604.             return;
  605.         this.baseLength += amount;
  606.         this.targetLength += amount;
  607.         var prevOp = this.ops[this.ops.length - 1];
  608.         if (prevOp != null && prevOp.type === "retain") {
  609.             prevOp.attributes.amount += amount;
  610.         }
  611.         else {
  612.             this.ops.push(new OT.TextOp("retain", { amount: amount }));
  613.         }
  614.     };
  615.     TextOperation.prototype.insert = function (text) {
  616.         if (typeof (text) !== "string" || text === "")
  617.             return;
  618.         this.targetLength += text.length;
  619.         var prevOp = this.ops[this.ops.length - 1];
  620.         if (prevOp != null && prevOp.type === "insert") {
  621.             prevOp.attributes.text += text;
  622.         }
  623.         else {
  624.             this.ops.push(new OT.TextOp("insert", { text: text }));
  625.         }
  626.     };
  627.     TextOperation.prototype.delete = function (text) {
  628.         if (typeof (text) !== "string" || text === "")
  629.             return;
  630.         this.baseLength += text.length;
  631.         var prevOp = this.ops[this.ops.length - 1];
  632.         if (prevOp != null && prevOp.type === "delete") {
  633.             prevOp.attributes.text += text;
  634.         }
  635.         else {
  636.             this.ops.push(new OT.TextOp("delete", { text: text }));
  637.         }
  638.     };
  639.     TextOperation.prototype.apply = function (text) {
  640.         if (text.length !== this.baseLength)
  641.             throw new Error("The operation's base length must be equal to the string's length.");
  642.         var index = 0;
  643.         for (var _i = 0, _a = this.ops; _i < _a.length; _i++) {
  644.             var op = _a[_i];
  645.             switch (op.type) {
  646.                 case "retain":
  647.                     index += op.attributes.amount;
  648.                     break;
  649.                 case "insert":
  650.                     text = text.substring(0, index) + op.attributes.text + text.substring(index, text.length);
  651.                     index += op.attributes.text.length;
  652.                     break;
  653.                 case "delete":
  654.                     text = text.substring(0, index) + text.substring(index + op.attributes.text.length, text.length);
  655.                     break;
  656.             }
  657.         }
  658.         return text;
  659.     };
  660.     TextOperation.prototype.invert = function () {
  661.         var invertedOperation = new TextOperation(this.userId);
  662.         for (var _i = 0, _a = this.ops; _i < _a.length; _i++) {
  663.             var op = _a[_i];
  664.             switch (op.type) {
  665.                 case "retain":
  666.                     invertedOperation.retain(op.attributes.amount);
  667.                     break;
  668.                 case "insert":
  669.                     invertedOperation.delete(op.attributes.text);
  670.                     break;
  671.                 case "delete":
  672.                     invertedOperation.insert(op.attributes.text);
  673.                     break;
  674.             }
  675.         }
  676.         return invertedOperation;
  677.     };
  678.     TextOperation.prototype.clone = function () {
  679.         var operation = new TextOperation(this.userId);
  680.         for (var _i = 0, _a = this.ops; _i < _a.length; _i++) {
  681.             var op = _a[_i];
  682.             switch (op.type) {
  683.                 case "retain":
  684.                     operation.retain(op.attributes.amount);
  685.                     break;
  686.                 case "insert":
  687.                     operation.insert(op.attributes.text);
  688.                     break;
  689.                 case "delete":
  690.                     operation.delete(op.attributes.text);
  691.                     break;
  692.             }
  693.         }
  694.         return operation;
  695.     };
  696.     TextOperation.prototype.equal = function (otherOperation) {
  697.         // if (otherOperation.insertedLength !== this.insertedLength) return false;
  698.         if (otherOperation.ops.length !== this.ops.length)
  699.             return false;
  700.         for (var opIndex = 0; opIndex < this.ops.length; opIndex++) {
  701.             var op = this.ops[opIndex];
  702.             var otherOp = otherOperation.ops[opIndex];
  703.             if (otherOp.type !== op.type)
  704.                 return false;
  705.             for (var key in op.attributes) {
  706.                 var attribute = op.attributes[key];
  707.                 if (attribute !== otherOp.attributes[key])
  708.                     return false;
  709.             }
  710.         }
  711.         return true;
  712.     };
  713.     /*
  714.     Largely inspired from Firepad
  715.     Compose merges two consecutive operations into one operation, that
  716.     preserves the changes of both. Or, in other words, for each input string S
  717.     and a pair of consecutive operations A and B,
  718.     apply(apply(S, A), B) = apply(S, compose(A, B)) must hold.
  719.     */
  720.     TextOperation.prototype.compose = function (operation2) {
  721.         if (this.targetLength !== operation2.baseLength)
  722.             throw new Error("The base length of the second operation has to be the target length of the first operation");
  723.         // the combined operation
  724.         var composedOperation = new TextOperation(this.userId);
  725.         var ops1 = this.clone().ops;
  726.         var ops2 = operation2.clone().ops;
  727.         var i1 = 0; // current index into ops1 respectively ops2
  728.         var i2 = 0;
  729.         var op1 = ops1[i1++]; // current ops
  730.         var op2 = ops2[i2++];
  731.         while (true) {
  732.             // Dispatch on the type of op1 and op2
  733.             // end condition: both ops1 and ops2 have been processed
  734.             if (op1 == null && op2 == null)
  735.                 break;
  736.             if (op2 == null) {
  737.                 switch (op1.type) {
  738.                     case "retain":
  739.                         composedOperation.retain(op1.attributes.amount);
  740.                         break;
  741.                     case "insert":
  742.                         composedOperation.insert(op1.attributes.text);
  743.                         break;
  744.                     case "delete":
  745.                         composedOperation.delete(op1.attributes.text);
  746.                         break;
  747.                 }
  748.                 op1 = ops1[i1++];
  749.                 continue;
  750.             }
  751.             if (op1 == null) {
  752.                 switch (op2.type) {
  753.                     case "retain":
  754.                         composedOperation.retain(op2.attributes.amount);
  755.                         break;
  756.                     case "insert":
  757.                         composedOperation.insert(op2.attributes.text);
  758.                         break;
  759.                     case "delete":
  760.                         composedOperation.delete(op2.attributes.text);
  761.                         break;
  762.                 }
  763.                 op2 = ops2[i2++];
  764.                 continue;
  765.             }
  766.             if (op1 != null && op1.type === "delete") {
  767.                 composedOperation.delete(op1.attributes.text);
  768.                 op1 = ops1[i1++];
  769.                 continue;
  770.             }
  771.             if (op2 != null && op2.type === "insert") {
  772.                 composedOperation.insert(op2.attributes.text);
  773.                 op2 = ops2[i2++];
  774.                 continue;
  775.             }
  776.             if (op1 == null)
  777.                 throw new Error("Cannot transform operations: first operation is too short.");
  778.             if (op2 == null)
  779.                 throw new Error("Cannot transform operations: first operation is too long.");
  780.             if (op1.type === "retain" && op2.type === "retain") {
  781.                 if (op1.attributes.amount === op2.attributes.amount) {
  782.                     composedOperation.retain(op1.attributes.amount);
  783.                     op1 = ops1[i1++];
  784.                     op2 = ops2[i2++];
  785.                 }
  786.                 else if (op1.attributes.amount > op2.attributes.amount) {
  787.                     composedOperation.retain(op2.attributes.amount);
  788.                     op1.attributes.amount -= op2.attributes.amount;
  789.                     op2 = ops2[i2++];
  790.                 }
  791.                 else {
  792.                     composedOperation.retain(op1.attributes.amount);
  793.                     op2.attributes.amount -= op1.attributes.amount;
  794.                     op1 = ops1[i1++];
  795.                 }
  796.             }
  797.             else if (op1.type === "insert" && op2.type === "delete") {
  798.                 if (op1.attributes.text.length === op2.attributes.text) {
  799.                     op1 = ops1[i1++];
  800.                     op2 = ops2[i2++];
  801.                 }
  802.                 else if (op1.attributes.text.length > op2.attributes.text.length) {
  803.                     op1.attributes.text = op1.attributes.text.slice(op2.attributes.text.length);
  804.                     op2 = ops2[i2++];
  805.                 }
  806.                 else {
  807.                     op2.attributes.text = op2.attributes.text.slice(op1.attributes.text.length);
  808.                     op1 = ops1[i1++];
  809.                 }
  810.             }
  811.             else if (op1.type === "insert" && op2.type === "retain") {
  812.                 if (op1.attributes.text.length > op2.attributes.amount) {
  813.                     composedOperation.insert(op1.attributes.text.slice(0, op2.attributes.amount));
  814.                     op1.attributes.text = op1.attributes.text.slice(op2.attributes.amount);
  815.                     op2 = ops2[i2++];
  816.                 }
  817.                 else if (op1.attributes.text.length === op2.attributes.amount) {
  818.                     composedOperation.insert(op1.attributes.text);
  819.                     op1 = ops1[i1++];
  820.                     op2 = ops2[i2++];
  821.                 }
  822.                 else {
  823.                     composedOperation.insert(op1.attributes.text);
  824.                     op2.attributes.amount -= op1.attributes.text.length;
  825.                     op1 = ops1[i1++];
  826.                 }
  827.             }
  828.             else if (op1.type === "retain" && op2.type === "delete") {
  829.                 if (op1.attributes.amount === op2.attributes.text.length) {
  830.                     composedOperation.delete(op2.attributes.text);
  831.                     op1 = ops1[i1++];
  832.                     op2 = ops2[i2++];
  833.                 }
  834.                 else if (op1.attributes.amount > op2.attributes.text.length) {
  835.                     composedOperation.delete(op2.attributes.text);
  836.                     op1.attributes.amount -= op2.attributes.text.length;
  837.                     op2 = ops2[i2++];
  838.                 }
  839.                 else {
  840.                     composedOperation.delete(op2.attributes.text.slice(0, op1.attributes.amount));
  841.                     op2.attributes.text = op2.attributes.text.slice(op1.attributes.amount);
  842.                     op1 = ops1[i1++];
  843.                 }
  844.             }
  845.             else {
  846.                 throw new Error("This shouldn't happen: op1: " + JSON.stringify(op1) + ", op2: " + JSON.stringify(op2));
  847.             }
  848.         }
  849.         return composedOperation;
  850.     };
  851.     /*
  852.     Largely inspired from Firepad
  853.     Transform takes two operations A (this) and B (other) that happened concurrently and
  854.     produces two operations A' and B' (in an array) such that
  855.     `apply(apply(S, A), B') = apply(apply(S, B), A')`.
  856.     This function is the heart of OT.
  857.     */
  858.     TextOperation.prototype.transform = function (operation2) {
  859.         var operation1prime, operation2prime;
  860.         var ops1, ops2;
  861.         // Give priority with the user id
  862.         if (this.gotPriority(operation2.userId)) {
  863.             operation1prime = new TextOperation(this.userId);
  864.             operation2prime = new TextOperation(operation2.userId);
  865.             ops1 = this.clone().ops;
  866.             ops2 = operation2.clone().ops;
  867.         }
  868.         else {
  869.             operation1prime = new TextOperation(operation2.userId);
  870.             operation2prime = new TextOperation(this.userId);
  871.             ops1 = operation2.clone().ops;
  872.             ops2 = this.clone().ops;
  873.         }
  874.         var i1 = 0;
  875.         var i2 = 0;
  876.         var op1 = ops1[i1++];
  877.         var op2 = ops2[i2++];
  878.         while (true) {
  879.             // At every iteration of the loop, the imaginary cursor that both
  880.             // operation1 and operation2 have that operates on the input string must
  881.             // have the same position in the input string.
  882.             // end condition: both ops1 and ops2 have been processed
  883.             if (op1 == null && op2 == null)
  884.                 break;
  885.             // next two cases: one or both ops are insert ops
  886.             // => insert the string in the corresponding prime operation, skip it in
  887.             // the other one. If both op1 and op2 are insert ops, prefer op1.
  888.             if (op1 != null && op1.type === "insert") {
  889.                 operation1prime.insert(op1.attributes.text);
  890.                 operation2prime.retain(op1.attributes.text.length);
  891.                 op1 = ops1[i1++];
  892.                 continue;
  893.             }
  894.             if (op2 != null && op2.type === "insert") {
  895.                 operation1prime.retain(op2.attributes.text.length);
  896.                 operation2prime.insert(op2.attributes.text);
  897.                 op2 = ops2[i2++];
  898.                 continue;
  899.             }
  900.             if (op1 == null)
  901.                 throw new Error("Cannot transform operations: first operation is too short.");
  902.             if (op2 == null)
  903.                 throw new Error("Cannot transform operations: first operation is too long.");
  904.             if (op1.type === "retain" && op2.type === "retain") {
  905.                 // Simple case: retain/retain
  906.                 var minl = void 0;
  907.                 if (op1.attributes.amount === op2.attributes.amount) {
  908.                     minl = op2.attributes.amount;
  909.                     op1 = ops1[i1++];
  910.                     op2 = ops2[i2++];
  911.                 }
  912.                 else if (op1.attributes.amount > op2.attributes.amount) {
  913.                     minl = op2.attributes.amount;
  914.                     op1.attributes.amount -= op2.attributes.amount;
  915.                     op2 = ops2[i2++];
  916.                 }
  917.                 else {
  918.                     minl = op1.attributes.amount;
  919.                     op2.attributes.amount -= op1.attributes.amount;
  920.                     op1 = ops1[i1++];
  921.                 }
  922.                 operation1prime.retain(minl);
  923.                 operation2prime.retain(minl);
  924.             }
  925.             else if (op1.type === "delete" && op2.type === "delete") {
  926.                 // Both operations delete the same string at the same position. We don't
  927.                 // need to produce any operations, we just skip over the delete ops and
  928.                 // handle the case that one operation deletes more than the other.
  929.                 if (op1.attributes.text.length === op2.attributes.text.length) {
  930.                     op1 = ops1[i1++];
  931.                     op2 = ops2[i2++];
  932.                 }
  933.                 else if (op1.attributes.text.length > op2.attributes.text.length) {
  934.                     op1.attributes.text = op1.attributes.text.slice(op2.attributes.text.length);
  935.                     op2 = ops2[i2++];
  936.                 }
  937.                 else {
  938.                     op2.attributes.text = op1.attributes.text.slice(op1.attributes.text.length);
  939.                     op1 = ops1[i1++];
  940.                 }
  941.             }
  942.             else if (op1.type === "delete" && op2.type === "retain") {
  943.                 var text = void 0;
  944.                 if (op1.attributes.text.length === op2.attributes.amount) {
  945.                     text = op1.attributes.text;
  946.                     op1 = ops1[i1++];
  947.                     op2 = ops2[i2++];
  948.                 }
  949.                 else if (op1.attributes.text.length > op2.attributes.amount) {
  950.                     text = op1.attributes.text.slice(0, op2.attributes.amount);
  951.                     op1.attributes.text = op1.attributes.text.slice(op2.attributes.amount);
  952.                     op2 = ops2[i2++];
  953.                 }
  954.                 else {
  955.                     text = op1.attributes.text;
  956.                     op2.attributes.amount -= op1.attributes.text.length;
  957.                     op1 = ops1[i1++];
  958.                 }
  959.                 operation1prime.delete(text);
  960.             }
  961.             else if (op1.type === "retain" && op2.type === "delete") {
  962.                 var text = void 0;
  963.                 if (op1.attributes.amount === op2.attributes.text.length) {
  964.                     text = op2.attributes.text;
  965.                     op1 = ops1[i1++];
  966.                     op2 = ops2[i2++];
  967.                 }
  968.                 else if (op1.attributes.amount > op2.attributes.text.length) {
  969.                     text = op2.attributes.text;
  970.                     op1.attributes.amount -= op2.attributes.text.length;
  971.                     op2 = ops2[i2++];
  972.                 }
  973.                 else {
  974.                     text = op2.attributes.text.slice(0, op1.attributes.amount);
  975.                     op2.attributes.text = op2.attributes.text.slice(op1.attributes.amount);
  976.                     op1 = ops1[i1++];
  977.                 }
  978.                 operation2prime.delete(text);
  979.             }
  980.             else {
  981.                 throw new Error("The two operations aren't compatible");
  982.             }
  983.         }
  984.         if (this.gotPriority(operation2.userId))
  985.             return [operation1prime, operation2prime];
  986.         else
  987.             return [operation2prime, operation1prime];
  988.     };
  989.     TextOperation.prototype.gotPriority = function (id2) { return (this.userId <= id2); };
  990.     return TextOperation;
  991. })();
  992. module.exports = TextOperation;
  993.  
  994. },{"./index":9}],9:[function(require,module,exports){
  995. var TextOp = require("./TextOp");
  996. exports.TextOp = TextOp;
  997. var Document = require("./Document");
  998. exports.Document = Document;
  999. var TextOperation = require("./TextOperation");
  1000. exports.TextOperation = TextOperation;
  1001.  
  1002. },{"./Document":6,"./TextOp":7,"./TextOperation":8}]},{},[3]);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement