Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Built text2 for the web

  • Loading branch information...
commit 7fd4e4f4e2d9697e5adc5566da442ed75114d793 1 parent a0cbf9a
@josephg josephg authored
View
1  Cakefile
@@ -92,6 +92,7 @@ task 'webclient', 'Build the web client into one file', ->
compile client, 'webclient/share'
buildtype 'json'
buildtype 'text-tp2'
+ buildtype 'text2'
# TODO: This should also be closure compiled.
extrafiles = expandNames extras
View
22 src/types/text2.coffee
@@ -12,11 +12,11 @@
#
# Snapshots are strings.
-exports = if WEB? then {} else module.exports
+text2 = {}
-exports.name = 'text2'
+text2.name = 'text2'
-exports.create = -> ''
+text2.create = -> ''
# -------- Utility methods
@@ -113,7 +113,7 @@ trim = (op) ->
# Normalize an op, removing all empty skips and empty inserts / deletes. Concatenate
# adjacent inserts and deletes.
-exports.normalize = (op) ->
+text2.normalize = (op) ->
newOp = []
append = makeAppend newOp
append component for component in op
@@ -121,7 +121,7 @@ exports.normalize = (op) ->
trim newOp
# Apply the op to the string. Returns the new string.
-exports.apply = (str, op) ->
+text2.apply = (str, op) ->
throw new Error('Snapshot should be a string') unless typeof(str) == 'string'
checkOp op
@@ -143,7 +143,7 @@ exports.apply = (str, op) ->
# transform op1 by op2. Return transformed version of op1.
# op1 and op2 are unchanged by transform.
-exports.transform = (op, otherOp, side) ->
+text2.transform = (op, otherOp, side) ->
throw new Error "side (#{side}) must be 'left' or 'right'" unless side in ['left', 'right']
checkOp op
@@ -188,7 +188,7 @@ exports.transform = (op, otherOp, side) ->
# Compose 2 ops into 1 op.
-exports.compose = (op1, op2) ->
+text2.compose = (op1, op2) ->
checkOp op1
checkOp op2
@@ -231,8 +231,8 @@ exports.compose = (op1, op2) ->
trim result
-if window?
- window.ot ||= {}
- window.ot.types ||= {}
- window.ot.types.text2 = exports
+if WEB?
+ exports.types.text2 = text2
+else
+ module.exports = text2
View
1  webclient/text2.js
@@ -0,0 +1 @@
+(function(){var e,t,n,r,i,s,o=!0,u=window.sharejs,a={};a.name="text2",a.create=function(){return""},e=function(e){var t,n,r,i;if(!Array.isArray(e))throw new Error("Op must be an array of components");n=null;for(r=0,i=e.length;r<i;r++){t=e[r];switch(typeof t){case"object":if(!(typeof t.d=="number"&&t.d>0))throw new Error("Object components must be deletes of size > 0");break;case"string":if(!(t.length>0))throw new Error("Inserts cannot be empty");break;case"number":if(!(t>0))throw new Error("Skip components must be >0");if(typeof n=="number")throw new Error("Adjacent skip components should be combined")}n=t}if(typeof n=="number")throw new Error("Op has a trailing skip")},n=function(e){return function(t){if(!!t&&t.d!==0)return e.length===0?e.push(t):typeof t==typeof e[e.length-1]?typeof t=="object"?e[e.length-1].d+=t.d:e[e.length-1]+=t:e.push(t)}},r=function(e){var t=0,n=0,r=function(r,i){var s,o;return t===e.length?r===-1?null:r:(s=e[t],typeof s=="number"?r===-1||s-n<=r?(o=s-n,++t,n=0,o):(n+=r,r):typeof s=="string"?r===-1||i==="i"||s.length-n<=r?(o=s.slice(n),++t,n=0,o):(o=s.slice(n,n+r),n+=r,o):r===-1||i==="d"||s.d-n<=r?(o={d:s.d-n},++t,n=0,o):(n+=r,{d:r}))},i=function(){return e[t]};return[r,i]},t=function(e){return typeof e=="number"?e:e.length||e.d},i=function(e){return e.length>0&&typeof e[e.length-1]=="number"&&e.pop(),e},a.normalize=function(e){var t,r,s,o=[],u=n(o);for(r=0,s=e.length;r<s;r++)t=e[r],u(t);return i(o)},a.apply=function(t,n){var r,i,s,o,u;if(typeof t!="string")throw new Error("Snapshot should be a string");e(n),s=0,i=[];for(o=0,u=n.length;o<u;o++){r=n[o];switch(typeof r){case"number":if(r>t.length)throw new Error("The op is too long for this document");i.push(t.slice(0,r)),t=t.slice(r);break;case"string":i.push(r);break;case"object":t=t.slice(r.d)}}return i.join("")+t},a.transform=function(s,o,u){var a,f,l,c,h,p,d,v,m,g,y;if(u!=="left"&&u!=="right")throw new Error("side ("+u+") must be 'left' or 'right'");e(s),e(o),h=[],a=n(h),y=r(s),v=y[0],d=y[1];for(m=0,g=o.length;m<g;m++){l=o[m];switch(typeof l){case"number":c=l;while(c>0)f=v(c,"i"),a(f),typeof f!="string"&&(c-=t(f));break;case"string":u==="left"&&(p=d(),typeof p=="string"&&a(v(-1))),a(l.length);break;case"object":c=l.d;while(c>0){f=v(c,"i");switch(typeof f){case"number":c-=f;break;case"string":a(f);break;case"object":c-=f.d}}}}while(l=v(-1))a(l);return i(h)},a.compose=function(s,o){var u,a,f,l,c,h,p,d,v,m;e(s),e(o),c=[],u=n(c),m=r(s),h=m[0],p=m[1];for(d=0,v=o.length;d<v;d++){f=o[d];switch(typeof f){case"number":l=f;while(l>0)a=h(l,"d"),u(a),typeof a!="object"&&(l-=t(a));break;case"string":u(f);break;case"object":l=f.d;while(l>0){a=h(l,"d");switch(typeof a){case"number":u({d:a}),l-=a;break;case"string":l-=a.length;break;case"object":u(a)}}}}while(f=h(-1))u(f);return i(c)},typeof o!="undefined"&&o!==null?u.types.text2=a:module.exports=a,typeof o!="undefined"&&o!==null?s=u.types.text2:s=require("./text2"),s.api={provides:{text:!0},getLength:function(){return this.snapshot.length},getText:function(){return this.snapshot},insert:function(e,t,n){var r=s.normalize([e,t]);return this.submitOp(r,n),r},del:function(e,t,n){var r=s.normalize([e,{d:t}]);return this.submitOp(r,n),r},_register:function(){return this.on("remoteop",function(e,t){var n,r,i,s,o=r=0,u=[];for(i=0,s=e.length;i<s;i++){n=e[i];switch(typeof n){case"number":o+=n,u.push(r+=n);break;case"string":this.emit("insert",o,n),u.push(o+=n.length);break;case"object":this.emit("delete",o,t.slice(r,r+n.d)),u.push(r+=n.d);break;default:u.push(void 0)}}return u})}}}).call(this)
View
356 webclient/text2.uncompressed.js
@@ -0,0 +1,356 @@
+// Generated by CoffeeScript 1.4.0
+(function() {
+ /**
+ @const
+ @type {boolean}
+*/
+var WEB = true;
+;
+
+ var checkOp, componentLength, exports, makeAppend, makeTake, text2, trim, type;
+
+ exports = window['sharejs'];
+
+ text2 = {};
+
+ text2.name = 'text2';
+
+ text2.create = function() {
+ return '';
+ };
+
+ checkOp = function(op) {
+ var c, last, _i, _len;
+ if (!Array.isArray(op)) {
+ throw new Error('Op must be an array of components');
+ }
+ last = null;
+ for (_i = 0, _len = op.length; _i < _len; _i++) {
+ c = op[_i];
+ switch (typeof c) {
+ case 'object':
+ if (!(typeof c.d === 'number' && c.d > 0)) {
+ throw new Error('Object components must be deletes of size > 0');
+ }
+ break;
+ case 'string':
+ if (!(c.length > 0)) {
+ throw new Error('Inserts cannot be empty');
+ }
+ break;
+ case 'number':
+ if (!(c > 0)) {
+ throw new Error('Skip components must be >0');
+ }
+ if (typeof last === 'number') {
+ throw new Error('Adjacent skip components should be combined');
+ }
+ }
+ last = c;
+ }
+ if (typeof last === 'number') {
+ throw new Error('Op has a trailing skip');
+ }
+ };
+
+ makeAppend = function(op) {
+ return function(component) {
+ if (!component || component.d === 0) {
+
+ } else if (op.length === 0) {
+ return op.push(component);
+ } else if (typeof component === typeof op[op.length - 1]) {
+ if (typeof component === 'object') {
+ return op[op.length - 1].d += component.d;
+ } else {
+ return op[op.length - 1] += component;
+ }
+ } else {
+ return op.push(component);
+ }
+ };
+ };
+
+ makeTake = function(op) {
+ var idx, offset, peekType, take;
+ idx = 0;
+ offset = 0;
+ take = function(n, indivisableField) {
+ var c, part;
+ if (idx === op.length) {
+ if (n === -1) {
+ return null;
+ } else {
+ return n;
+ }
+ }
+ c = op[idx];
+ if (typeof c === 'number') {
+ if (n === -1 || c - offset <= n) {
+ part = c - offset;
+ ++idx;
+ offset = 0;
+ return part;
+ } else {
+ offset += n;
+ return n;
+ }
+ } else if (typeof c === 'string') {
+ if (n === -1 || indivisableField === 'i' || c.length - offset <= n) {
+ part = c.slice(offset);
+ ++idx;
+ offset = 0;
+ return part;
+ } else {
+ part = c.slice(offset, offset + n);
+ offset += n;
+ return part;
+ }
+ } else {
+ if (n === -1 || indivisableField === 'd' || c.d - offset <= n) {
+ part = {
+ d: c.d - offset
+ };
+ ++idx;
+ offset = 0;
+ return part;
+ } else {
+ offset += n;
+ return {
+ d: n
+ };
+ }
+ }
+ };
+ peekType = function() {
+ return op[idx];
+ };
+ return [take, peekType];
+ };
+
+ componentLength = function(c) {
+ if (typeof c === 'number') {
+ return c;
+ } else {
+ return c.length || c.d;
+ }
+ };
+
+ trim = function(op) {
+ if (op.length > 0 && typeof op[op.length - 1] === 'number') {
+ op.pop();
+ }
+ return op;
+ };
+
+ text2.normalize = function(op) {
+ var append, component, newOp, _i, _len;
+ newOp = [];
+ append = makeAppend(newOp);
+ for (_i = 0, _len = op.length; _i < _len; _i++) {
+ component = op[_i];
+ append(component);
+ }
+ return trim(newOp);
+ };
+
+ text2.apply = function(str, op) {
+ var component, newDoc, pos, _i, _len;
+ if (typeof str !== 'string') {
+ throw new Error('Snapshot should be a string');
+ }
+ checkOp(op);
+ pos = 0;
+ newDoc = [];
+ for (_i = 0, _len = op.length; _i < _len; _i++) {
+ component = op[_i];
+ switch (typeof component) {
+ case 'number':
+ if (component > str.length) {
+ throw new Error('The op is too long for this document');
+ }
+ newDoc.push(str.slice(0, component));
+ str = str.slice(component);
+ break;
+ case 'string':
+ newDoc.push(component);
+ break;
+ case 'object':
+ str = str.slice(component.d);
+ }
+ }
+ return newDoc.join('') + str;
+ };
+
+ text2.transform = function(op, otherOp, side) {
+ var append, chunk, component, length, newOp, o, peek, take, _i, _len, _ref;
+ if (side !== 'left' && side !== 'right') {
+ throw new Error("side (" + side + ") must be 'left' or 'right'");
+ }
+ checkOp(op);
+ checkOp(otherOp);
+ newOp = [];
+ append = makeAppend(newOp);
+ _ref = makeTake(op), take = _ref[0], peek = _ref[1];
+ for (_i = 0, _len = otherOp.length; _i < _len; _i++) {
+ component = otherOp[_i];
+ switch (typeof component) {
+ case 'number':
+ length = component;
+ while (length > 0) {
+ chunk = take(length, 'i');
+ append(chunk);
+ if (typeof chunk !== 'string') {
+ length -= componentLength(chunk);
+ }
+ }
+ break;
+ case 'string':
+ if (side === 'left') {
+ o = peek();
+ if (typeof o === 'string') {
+ append(take(-1));
+ }
+ }
+ append(component.length);
+ break;
+ case 'object':
+ length = component.d;
+ while (length > 0) {
+ chunk = take(length, 'i');
+ switch (typeof chunk) {
+ case 'number':
+ length -= chunk;
+ break;
+ case 'string':
+ append(chunk);
+ break;
+ case 'object':
+ length -= chunk.d;
+ }
+ }
+ }
+ }
+ while ((component = take(-1))) {
+ append(component);
+ }
+ return trim(newOp);
+ };
+
+ text2.compose = function(op1, op2) {
+ var append, chunk, component, length, result, take, _, _i, _len, _ref;
+ checkOp(op1);
+ checkOp(op2);
+ result = [];
+ append = makeAppend(result);
+ _ref = makeTake(op1), take = _ref[0], _ = _ref[1];
+ for (_i = 0, _len = op2.length; _i < _len; _i++) {
+ component = op2[_i];
+ switch (typeof component) {
+ case 'number':
+ length = component;
+ while (length > 0) {
+ chunk = take(length, 'd');
+ append(chunk);
+ if (typeof chunk !== 'object') {
+ length -= componentLength(chunk);
+ }
+ }
+ break;
+ case 'string':
+ append(component);
+ break;
+ case 'object':
+ length = component.d;
+ while (length > 0) {
+ chunk = take(length, 'd');
+ switch (typeof chunk) {
+ case 'number':
+ append({
+ d: chunk
+ });
+ length -= chunk;
+ break;
+ case 'string':
+ length -= chunk.length;
+ break;
+ case 'object':
+ append(chunk);
+ }
+ }
+ }
+ }
+ while ((component = take(-1))) {
+ append(component);
+ }
+ return trim(result);
+ };
+
+ if (typeof WEB !== "undefined" && WEB !== null) {
+ exports.types.text2 = text2;
+ } else {
+ module.exports = text2;
+ }
+
+ if (typeof WEB !== "undefined" && WEB !== null) {
+ type = exports.types.text2;
+ } else {
+ type = require('./text2');
+ }
+
+ type.api = {
+ provides: {
+ text: true
+ },
+ getLength: function() {
+ return this.snapshot.length;
+ },
+ getText: function() {
+ return this.snapshot;
+ },
+ insert: function(pos, text, callback) {
+ var op;
+ op = type.normalize([pos, text]);
+ this.submitOp(op, callback);
+ return op;
+ },
+ del: function(pos, length, callback) {
+ var op;
+ op = type.normalize([
+ pos, {
+ d: length
+ }
+ ]);
+ this.submitOp(op, callback);
+ return op;
+ },
+ _register: function() {
+ return this.on('remoteop', function(op, snapshot) {
+ var component, pos, spos, _i, _len, _results;
+ pos = spos = 0;
+ _results = [];
+ for (_i = 0, _len = op.length; _i < _len; _i++) {
+ component = op[_i];
+ switch (typeof component) {
+ case 'number':
+ pos += component;
+ _results.push(spos += component);
+ break;
+ case 'string':
+ this.emit('insert', pos, component);
+ _results.push(pos += component.length);
+ break;
+ case 'object':
+ this.emit('delete', pos, snapshot.slice(spos, spos + component.d));
+ _results.push(spos += component.d);
+ break;
+ default:
+ _results.push(void 0);
+ }
+ }
+ return _results;
+ });
+ }
+ };
+
+}).call(this);
Please sign in to comment.
Something went wrong with that request. Please try again.