| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 | var equal = require('deep-equal');var extend = require('extend');var lib = {  attributes: {    compose: function (a, b, keepNull) {      if (typeof a !== 'object') a = {};      if (typeof b !== 'object') b = {};      var attributes = extend(true, {}, b);      if (!keepNull) {        attributes = Object.keys(attributes).reduce(function (copy, key) {          if (attributes[key] != null) {            copy[key] = attributes[key];          }          return copy;        }, {});      }      for (var key in a) {        if (a[key] !== undefined && b[key] === undefined) {          attributes[key] = a[key];        }      }      return Object.keys(attributes).length > 0 ? attributes : undefined;    },    diff: function(a, b) {      if (typeof a !== 'object') a = {};      if (typeof b !== 'object') b = {};      var attributes = Object.keys(a).concat(Object.keys(b)).reduce(function (attributes, key) {        if (!equal(a[key], b[key])) {          attributes[key] = b[key] === undefined ? null : b[key];        }        return attributes;      }, {});      return Object.keys(attributes).length > 0 ? attributes : undefined;    },    transform: function (a, b, priority) {      if (typeof a !== 'object') return b;      if (typeof b !== 'object') return undefined;      if (!priority) return b;  // b simply overwrites us without priority      var attributes = Object.keys(b).reduce(function (attributes, key) {        if (a[key] === undefined) attributes[key] = b[key];  // null is a valid value        return attributes;      }, {});      return Object.keys(attributes).length > 0 ? attributes : undefined;    }  },  iterator: function (ops) {    return new Iterator(ops);  },  length: function (op) {    if (typeof op['delete'] === 'number') {      return op['delete'];    } else if (typeof op.retain === 'number') {      return op.retain;    } else {      return typeof op.insert === 'string' ? op.insert.length : 1;    }  }};function Iterator(ops) {  this.ops = ops;  this.index = 0;  this.offset = 0;};Iterator.prototype.hasNext = function () {  return this.peekLength() < Infinity;};Iterator.prototype.next = function (length) {  if (!length) length = Infinity;  var nextOp = this.ops[this.index];  if (nextOp) {    var offset = this.offset;    var opLength = lib.length(nextOp)    if (length >= opLength - offset) {      length = opLength - offset;      this.index += 1;      this.offset = 0;    } else {      this.offset += length;    }    if (typeof nextOp['delete'] === 'number') {      return { 'delete': length };    } else {      var retOp = {};      if (nextOp.attributes) {        retOp.attributes = nextOp.attributes;      }      if (typeof nextOp.retain === 'number') {        retOp.retain = length;      } else if (typeof nextOp.insert === 'string') {        retOp.insert = nextOp.insert.substr(offset, length);      } else {        // offset should === 0, length should === 1        retOp.insert = nextOp.insert;      }      return retOp;    }  } else {    return { retain: Infinity };  }};Iterator.prototype.peek = function () {  return this.ops[this.index];};Iterator.prototype.peekLength = function () {  if (this.ops[this.index]) {    // Should never return 0 if our index is being managed correctly    return lib.length(this.ops[this.index]) - this.offset;  } else {    return Infinity;  }};Iterator.prototype.peekType = function () {  if (this.ops[this.index]) {    if (typeof this.ops[this.index]['delete'] === 'number') {      return 'delete';    } else if (typeof this.ops[this.index].retain === 'number') {      return 'retain';    } else {      return 'insert';    }  }  return 'retain';};Iterator.prototype.rest = function () {  if (!this.hasNext()) {    return [];  } else if (this.offset === 0) {    return this.ops.slice(this.index);  } else {    var offset = this.offset;    var index = this.index;    var next = this.next();    var rest = this.ops.slice(this.index);    this.offset = offset;    this.index = index;    return [next].concat(rest);  }};module.exports = lib;
 |