<commit_before>import {
  isPlainObject
} from 'uni-shared'

const CLASS_RE = /^\s+|\s+$/g
const WXS_CLASS_RE = /\s+/

function getWxsClsArr (clsArr, classList, isAdd) {
  const wxsClsArr = []

  let checkClassList = function (cls) {
    if (isAdd) {
      checkClassList = function (cls) {
        return !classList.contains(cls)
      }
    } else {
      checkClassList = function (cls) {
        return classList.contains(cls)
      }
    }
    return checkClassList(cls)
  }

  clsArr.forEach(cls => {
    cls = cls.replace(CLASS_RE, '')
    checkClassList(cls) && wxsClsArr.push(cls)
  })
  return wxsClsArr
}

function parseStyleText (cssText) {
  const res = {}
  const listDelimiter = /;(?![^(]*\))/g
  const propertyDelimiter = /:(.+)/
  cssText.split(listDelimiter).forEach(function (item) {
    if (item) {
      const tmp = item.split(propertyDelimiter)
      tmp.length > 1 && (res[tmp[0].trim()] = tmp[1].trim())
    }
  })
  return res
}

class ComponentDescriptor {
  constructor (vm) {
    this.$vm = vm
    this.$el = vm.$el
  }

  selectComponent (selector) {
    if (!this.$el || !selector) {
      return
    }
    const el = this.$el.querySelector(selector)
    return el && el.__vue__ && createComponentDescriptor(el.__vue__, false)
  }

  selectAllComponents (selector) {
    if (!this.$el || !selector) {
      return []
    }
    const descriptors = []
    const els = this.$el.querySelectorAll(selector)
    for (let i = 0; i < els.length; i++) {
      const el = els[i]
      el.__vue__ && descriptors.push(createComponentDescriptor(el.__vue__, false))
    }
    return descriptors
  }

  setStyle (style) {
    if (!this.$el || !style) {
      return this
    }
    if (typeof style === 'string') {
      style = parseStyleText(style)
    }
    if (isPlainObject(style)) {
      this.$el.__wxsStyle = style
      this.$vm.$forceUpdate()
    }
    return this
  }

  addClass (...clsArr) {
    if (!this.$el || !clsArr.length) {
      return this
    }

    const wxsClsArr = getWxsClsArr(clsArr, this.$el.classList, true)
    if (wxsClsArr.length) {
      const wxsClass = this.$el.__wxsAddClass || ''
      this.$el.__wxsAddClass = wxsClass + (wxsClass ? ' ' : '') + wxsClsArr.join(' ')
      this.$vm.$forceUpdate()
    }

    return this
  }

  removeClass (...clsArr) {
    if (!this.$el || !clsArr.length) {
      return this
    }
    const classList = this.$el.classList
    const addWxsClsArr = this.$el.__wxsAddClass ? this.$el.__wxsAddClass.split(WXS_CLASS_RE) : []
    const wxsClsArr = getWxsClsArr(clsArr, classList, false)
    if (wxsClsArr.length) {
      const removeWxsClsArr = []
      wxsClsArr.forEach(cls => {
        const clsIndex = addWxsClsArr.findIndex(oldCls => oldCls === cls)
        if (clsIndex !== -1) { // 在 addWxsClass 中
          addWxsClsArr.splice(clsIndex, 1)
        }
        removeWxsClsArr.push(cls)
      })
      this.$el.__wxsRemoveClass = removeWxsClsArr
      this.$el.__wxsAddClass = addWxsClsArr.join(' ')
      this.$vm.$forceUpdate()
    }

    return this
  }

  hasClass (cls) {
    return this.$el && this.$el.classList.contains(cls)
  }

  getComputedStyle () {
    if (this.$el) {
      return window.getComputedStyle(this.$el)
    }
    return {}
  }

  getDataset () {
    return this.$el && this.$el.dataset
  }

  callMethod (funcName, args = {}) {
    if (this.$vm[funcName]) {
      this.$vm[funcName](JSON.parse(JSON.stringify(args)))
    } else if (this.$vm._$id) {
      UniViewJSBridge.publishHandler('onWxsInvokeCallMethod', {
        cid: this.$vm._$id,
        method: funcName,
        args
      })
    }
  }

  requestAnimationFrame (callback) {
    return (global.requestAnimationFrame(callback), this)
  }

  getState () {
    return this.$el && (this.$el.__wxsState || (this.$el.__wxsState = {}))
  }

  triggerEvent (eventName, detail = {}, options = {}) {
    // TODO options
    return (this.$vm.$emit(eventName, detail), this)
  }
}

export function createComponentDescriptor (vm, isOwnerInstance = true) {
  if (isOwnerInstance && vm && vm.$options.name && vm.$options.name.indexOf('VUni') === 0) {
    // ownerInstance 内置组件需要使用父 vm
    vm = vm.$parent
  }
  if (vm && vm.$el) {
    if (!vm.$el.__wxsComponentDescriptor) {
      vm.$el.__wxsComponentDescriptor = new ComponentDescriptor(vm)
    }
    return vm.$el.__wxsComponentDescriptor
  }
}
<commit_msg>fix: 修复部分情况下获取 wxs 实例错误的问题 question/117097<commit_after>import {
  isPlainObject
} from 'uni-shared'

const CLASS_RE = /^\s+|\s+$/g
const WXS_CLASS_RE = /\s+/

function getWxsClsArr (clsArr, classList, isAdd) {
  const wxsClsArr = []

  let checkClassList = function (cls) {
    if (isAdd) {
      checkClassList = function (cls) {
        return !classList.contains(cls)
      }
    } else {
      checkClassList = function (cls) {
        return classList.contains(cls)
      }
    }
    return checkClassList(cls)
  }

  clsArr.forEach(cls => {
    cls = cls.replace(CLASS_RE, '')
    checkClassList(cls) && wxsClsArr.push(cls)
  })
  return wxsClsArr
}

function parseStyleText (cssText) {
  const res = {}
  const listDelimiter = /;(?![^(]*\))/g
  const propertyDelimiter = /:(.+)/
  cssText.split(listDelimiter).forEach(function (item) {
    if (item) {
      const tmp = item.split(propertyDelimiter)
      tmp.length > 1 && (res[tmp[0].trim()] = tmp[1].trim())
    }
  })
  return res
}

class ComponentDescriptor {
  constructor (vm) {
    this.$vm = vm
    this.$el = vm.$el
  }

  selectComponent (selector) {
    if (!this.$el || !selector) {
      return
    }
    const el = this.$el.querySelector(selector)
    return el && el.__vue__ && createComponentDescriptor(el.__vue__, false)
  }

  selectAllComponents (selector) {
    if (!this.$el || !selector) {
      return []
    }
    const descriptors = []
    const els = this.$el.querySelectorAll(selector)
    for (let i = 0; i < els.length; i++) {
      const el = els[i]
      el.__vue__ && descriptors.push(createComponentDescriptor(el.__vue__, false))
    }
    return descriptors
  }

  setStyle (style) {
    if (!this.$el || !style) {
      return this
    }
    if (typeof style === 'string') {
      style = parseStyleText(style)
    }
    if (isPlainObject(style)) {
      this.$el.__wxsStyle = style
      this.$vm.$forceUpdate()
    }
    return this
  }

  addClass (...clsArr) {
    if (!this.$el || !clsArr.length) {
      return this
    }

    const wxsClsArr = getWxsClsArr(clsArr, this.$el.classList, true)
    if (wxsClsArr.length) {
      const wxsClass = this.$el.__wxsAddClass || ''
      this.$el.__wxsAddClass = wxsClass + (wxsClass ? ' ' : '') + wxsClsArr.join(' ')
      this.$vm.$forceUpdate()
    }

    return this
  }

  removeClass (...clsArr) {
    if (!this.$el || !clsArr.length) {
      return this
    }
    const classList = this.$el.classList
    const addWxsClsArr = this.$el.__wxsAddClass ? this.$el.__wxsAddClass.split(WXS_CLASS_RE) : []
    const wxsClsArr = getWxsClsArr(clsArr, classList, false)
    if (wxsClsArr.length) {
      const removeWxsClsArr = []
      wxsClsArr.forEach(cls => {
        const clsIndex = addWxsClsArr.findIndex(oldCls => oldCls === cls)
        if (clsIndex !== -1) { // 在 addWxsClass 中
          addWxsClsArr.splice(clsIndex, 1)
        }
        removeWxsClsArr.push(cls)
      })
      this.$el.__wxsRemoveClass = removeWxsClsArr
      this.$el.__wxsAddClass = addWxsClsArr.join(' ')
      this.$vm.$forceUpdate()
    }

    return this
  }

  hasClass (cls) {
    return this.$el && this.$el.classList.contains(cls)
  }

  getComputedStyle () {
    if (this.$el) {
      return window.getComputedStyle(this.$el)
    }
    return {}
  }

  getDataset () {
    return this.$el && this.$el.dataset
  }

  callMethod (funcName, args = {}) {
    if (funcName in this.$vm) {
      this.$vm[funcName](JSON.parse(JSON.stringify(args)))
    } else if (this.$vm._$id) {
      UniViewJSBridge.publishHandler('onWxsInvokeCallMethod', {
        cid: this.$vm._$id,
        method: funcName,
        args
      })
    }
  }

  requestAnimationFrame (callback) {
    return (global.requestAnimationFrame(callback), this)
  }

  getState () {
    return this.$el && (this.$el.__wxsState || (this.$el.__wxsState = {}))
  }

  triggerEvent (eventName, detail = {}, options = {}) {
    // TODO options
    return (this.$vm.$emit(eventName, detail), this)
  }
}

export function createComponentDescriptor (vm, isOwnerInstance = true) {
  if (isOwnerInstance && vm && vm.$options.name && vm.$options.name.indexOf('VUni') === 0) {
    // ownerInstance 内置组件需要使用父 vm
    vm = vm.$parent
  }
  // 改为挂载到 vm 实例，不同 vm 实例的 $el 可能重复
  if (vm) {
    if (!('__wxsComponentDescriptor' in vm)) {
      vm.__wxsComponentDescriptor = new ComponentDescriptor(vm)
    }
    return vm.__wxsComponentDescriptor
  }
}
<|endoftext|>


<commit_before>// adt.js
// ------
// Algebraic data types and immutable structures in Javascript
//
// version : 0.5.0
// author  : Nathan Faubion <nathan@n-son.com>
// license : MIT

;(function (adt) {
  // Cache some prototype methods for easy use.
  var slice = Array.prototype.slice;
  var funcApply = Function.prototype.apply;

  // Utility functions
  adt.util = {};

  // Return an array of the supplied argument. Used for `arguments` objects.
  adt.util.toArray = function (a) {
    var dest = [], i = 0, len = a.length;
    for (; i < len; i++) dest[i] = a[i];
    return dest;
  };

  // A basic extend method for copying attributes of on object into another.
  adt.util.extend = function (dest /*, sources... */) {
    var args = slice.call(arguments, 1);
    for (var i = 0, len = args.length; i < len; i++) {
      for (var k in args[i]) {
        if (args[i].hasOwnProperty(k)) dest[k] = args[i][k];
      }
    }
    return dest;
  };

  // Given a constructor and an array of args, instanciates a new objects with
  // said args. Like calling `apply` on a constructor.
  adt.util.ctrApply = function (ctr, args) {
    var C = function () {};
    C.prototype = ctr.prototype;
    var inst = new C();
    var ret = ctr.apply(inst, args);
    return Object(ret) === ret ? ret : inst;
  };

  // Partially applies arguments to a function in the same way `bind` would,
  // but doesn't cement the context in anyway.
  adt.util.partial = function (func) {
    var args = slice.call(arguments, 1);
    return function () {
      return func.apply(this, args.concat(adt.util.toArray(arguments)));
    };
  };

  // Standard inheritance helper.
  adt.util.inherit = function (sup, sub) {
    var C = function () {};
    C.prototype = sup.prototype;
    sub.prototype = new C();
    sub.prototype.constructor = sub;
    return sub;
  };

  // Helper function to return a unique id
  adt.util.uniqueId = (function () {
    var id = 0;
    return function (pre) { return pre + (id++); };
  })();

  // Base class from which all adt.js classes inherit.
  // All adt.js classes should have a clone method that clones the
  // object as best it can.
  adt.__Base__ = function () {};

  // Generates a new set of Algebraic data types. This will create a lot of
  // boilerplate to help with type checking. Each type will get is<type>()
  // methods that return true or false.
  adt.data = function () {
    var targ0 = typeof arguments[0];
    var callback, types, names;

    // adt.data(typesObj)
    if (targ0 === 'object') {
      types = arguments[0];

      // Call adt.data again with a desugared callback.
      return adt.data(function (d, type) {
        for (var name in types) type(name, types[name]);
      });
    }

    // adt.data(callback)
    callback = arguments[0] || function () {};
    names = [];

    // Create a new parent class.
    // This class should never be created using `new`. You obviously can,
    // but it won't be of much use. You can however override the apply method
    // to create default instances.
    var D = adt.util.inherit(adt.__Base__, function () {
      if (!(this instanceof D) && D.apply !== funcApply) {
        return D.apply(this, arguments);
      }
    });

    // Declares an adt type as part of the family.
    D.type = function (name, tmpl) {
      if (typeof name !== 'string') {
        tmpl = name;
        name = adt.util.uniqueId('Anonymous');
      }
      // Create a new adt template if not provided with one
      if (!tmpl) tmpl = adt.single();
      else if (typeof tmpl !== 'function') tmpl = adt.record(tmpl);

      // Add typechecking attributes for this type.
      D.prototype['is' + name] = false;

      // Call the template to build our type and export it on the parent type.
      D[name] = tmpl(D, name);
      names.push(name);
      return D[name];
    };

    // Call the callback with the constructor as the context.
    var types = callback.call(D, D, D.type);

    // If an object was returned in the callback, assume it's a mapping of
    // more types to add.
    if (typeof types === 'object' && !(types instanceof adt.__Base__)) {
      for (var name in types) {
        if (types.hasOwnProperty(name)) D.type(name, types[name]);
      }
    }

    // Keep the type function around because it allows for nice type
    // declarations, but give the option to seal it. This will call `seal`
    // on any sub types to.
    D.seal = function () {
      var i = 0, len = names.length, seal;
      for (; i < len; i++) {
        seal = this[name].seal;
        seal instanceof Function && seal();
      }
      delete D.type;
      delete D.seal;
      return D;
    };

    // Export names as a meta object
    D.__names__ = names;
    return D;
  };

  // Create a single empty class that always return the same instance.
  // Useful for sentinal values such as Nothing, Empty, etc.
  adt.single = function () {
    var ctr, inst;
    ctr = function () {
      if (!(this instanceof ctr)) return new ctr();
      if (inst) return inst;
      inst = this;
    };

    return function (parent, name) {
      adt.util.inherit(parent, ctr);
      ctr.className = name;
      ctr.prototype.clone = function () { return inst; };
      ctr.prototype.equals = function (obj) { return this === obj; };
      ctr.prototype.toString = function () { return name; };
      ctr.prototype['is' + name] = true;
      return new ctr();
    };
  };

  // Create a new class that has named fields. Each value can be obtained by
  // calling the name as a method. Each value can be changed by calling `set`
  // with an object of values to update. `set` returns a clone of the object.
  adt.record = function () {
    var targ0 = typeof arguments[0];
    var names, constraints, ctr, fields, callback;

    // adt.record(fieldNames...)
    if (targ0 === 'string') {
      var args = adt.util.toArray(arguments);
      return adt.record(function (r, field) {
        var i = 0, len = args.length;
        for (; i < len; i++) field(args[i], adt.any);
      });
    }

    // adt.record(fieldsObj)
    else if (targ0 === 'object') {
      fields = arguments[0];
      return adt.record(function (r, field) {
        for (var name in fields) field(name, fields[name]);
      });
    }

    // adt.record(callback)
    callback = arguments[0] || function () {};
    names = [];
    constraints = {};

    // A record's constructor can be called without `new` and will also throw
    // an error if called with too many arguments. Its arguments can be curried
    // as long as it isn't called with the `new` keyword.
    ctr = function () {
      var args = adt.util.toArray(arguments);
      var len = names.length;
      if (!(this instanceof ctr)) {
        return args.length < len
          ? adt.util.partial.apply(null, [ctr].concat(args))
          : adt.util.ctrApply(ctr, args);
      } else {
        if (args.length < len) throw new Error('Too few arguments');
        if (args.length > len) throw new Error('Too many arguments');
        var i = 0, len = args.length, n;
        for (; i < len; i++) {
          n = names[i];
          this[n] = constraints[n](args[i]);
        }
      }
    };

    return function (parent, name) {
      adt.util.inherit(parent, ctr);
      ctr.className = name;
      ctr.prototype['is' + name] = true;

      // Custom `toString` implementation.
      ctr.prototype.toString = function () {
        var vals = ctr.unapply(this);
        return name + (vals.length ? '(' + vals.join(', ') + ')' : '');
      };

      // This clone method will clone any values that are also adt types and
      // leaves anything else alone.
      ctr.prototype.clone = function () {
        var args = [];
        var i = 0, len = names.length, val;
        for (; i < len; i++) {
          val = this[names[i]];
          args.push(val instanceof adt.__Base__ ? val.clone() : val);
        }
        return ctr.apply(null, args);
      };

      // Lookup fields by either name or index. Throws an error if the name
      // doesn't exist or if the index is out of range.
      ctr.prototype.get = function (field) {
        if (typeof field === 'number') {
          if (field < 0 || field > names.length - 1) {
            throw new Error('Field index out of range');
          }
          field = names[field];
        } else {
          if (!constraints.hasOwnProperty(field)) {
            throw new Error('Field name does not exist');
          }
        }
        return this[field];
      };

      // Creates a new instance with the specified values changed.
      ctr.prototype.set = function (vals) {
        var args = []
        var i = 0, len = names.length, val, n;
        for (; i < len; i++) {
          n = names[i];
          val = n in vals ? vals[n] : this[n];
          args.push(val);
        }
        return ctr.apply(null, args);
      };

      // Performs deep equality checks on each field as long as it holds an
      // adt type. Any other types will just be compared using ===.
      ctr.prototype.equals = function (that) {
        if (this === that) return true;
        if (!(that instanceof ctr)) return false;
        var i = 0, len = names.length;
        var vala, valb, n;
        for (; i < len; i++) {
          n = names[i];
          vala = this[n];
          valb = that[n];
          if (vala instanceof adt.__Base__) {
            if (!vala.equals(valb)) return false;
          } else if (vala !== valb) return false;
        }
        return true;
      };

      // Creates a new instance using key-value pairs instead of by
      // positional arguments.
      ctr.create = function (vals) {
        var args = [];
        var i = 0, len = names.length, n;
        for (; i < len; i++) {
          n = names[i];
          if (!(n in vals)) throw new Error('Could not find field in arguments: ' + n);
          args.push(vals[n]);
        }
        return ctr.apply(null, args);
      };

      // Returns an array representation of the fields.
      ctr.unapply = function (inst) {
        var vals = [];
        var i = 0, len = names.length;
        for (; i < len; i++) vals.push(inst[names[i]]);
        return vals;
      };

      // Returns an object representation of the field.
      ctr.unapplyObj = function (inst) {
        var vals = {};
        var i = 0, len = names.length;
        for (; i < len; i++) vals[names[i]] = inst[names[i]];
        return vals;
      };

      // Declares a field as part of the type.
      ctr.field = function (name, constraint) {
        if (!constraint) constraint = adt.any;
        if (typeof constraint !== 'function') {
          throw new TypeError('Constraints must be functions')
        }
        names.push(name);
        constraints[name] = constraint;
        return ctr;
      };

      // Call the callback with the contructor as the context.
      fields = callback.call(ctr, ctr, ctr.field);

      // If an object was returned in the callback, assume it's a mapping of
      // more fields to add.
      if (typeof fields === 'object' && fields !== ctr) {
        for (var name in fields) {
          if (!fields.hasOwnProperty(name)) continue;
          ctr.field(name, fields[name]);
        }
      }

      // Export names and constraints as meta attributes.
      ctr.__names__ = names;
      ctr.__constraints__ = constraints;

      // Keep the field function around because it allows for nice type
      // declarations, but give the option to seal it.
      ctr.seal = function () {
        delete ctr.field;
        delete ctr.seal;
        return ctr;
      };

      return ctr;
    };
  };

  // Enumerations are types that have an order and can be compared using lt,
  // gt, lte, and gte.
  adt.enumeration = function () {
    var targ0 = typeof arguments[0];

    // adt.enumeration(typeNames...)
    if (targ0 === 'string') {
      var args = adt.util.toArray(arguments);
      return adt.enumeration(function (r, type) {
        var i = 0, len = args.length;
        for (; i < len; i++) type(args[i]);
      });
    }

    // Create the types
    var E = adt.data.apply(null, arguments);

    // Iterate through created types, applying an order meta attribute.
    var i = 0, len = E.__names__.length, name;
    for (; i < len; i++) {
      ctr = E[E.__names__[i]];
      if (ctr.constructor) ctr = ctr.constructor;
      ctr.__order__ = i;
    }

    // Helper function to make sure we are comparing the same types. We can't
    // compare the order of a different type, so it throws a TypeError if the
    // types are incompatible.
    function verifyType (that) {
      if (!(that instanceof E)) throw new TypeError('Unexpected type');
      return true;
    }

    // Helper to return the order of the particular instance
    function order (that) {
      return that.constructor.__order__;
    }

    // Less than
    E.prototype.lt = function (that) {
      return verifyType(that) && order(this) < order(that);
    };

    // Less than or equal
    E.prototype.lte = function (that) {
      return verifyType(that) && order(this) <= order(that);
    };

    // Greater than
    E.prototype.gt = function (that) {
      return verifyType(that) && order(this) > order(that);
    };

    // Greater than or equal
    E.prototype.gte = function (that) {
      return verifyType(that) && order(this) >= order(that);
    };

    // Equal (not that same as `equals`
    E.prototype.eq = function (that) {
      return verifyType(that) && order(this) === order(that);
    };

    // Not equals
    E.prototype.neq = function (that) {
      return verifyType(that) && order(this) !== order(that);
    };

    return E;
  };

  // Creates a singleton type that belongs to its own family.
  adt.newtype = function () {
    var args = adt.util.toArray(arguments);
    var data = adt.data();
    return data.type.apply(data, args);
  };

  // A contraint function that will accept any value.
  adt.any = function (x) { return x; };

  // A constraint generator that will perform instanceof checks on the value
  // to make sure it is of the correct type. If a value besides a function
  // is passed in, it will perform equality checks on it.
  //
  // It has special handling for Number, String, and Boolean. Literals won't
  // match an instanceof check, but will match with typeof.
  adt.only = function () {
    var args = arguments;
    return function (x) {
      var i = 0, len = args.length, type;
      for (; i < len; i++) {
        type = args[i];
        if (type instanceof Function) {
          if (x instanceof type
          || type === Number && typeof x === 'number'
          || type === String && typeof x === 'string'
          || type === Boolean && typeof x === 'boolean') return x;
        } else {
          if (type instanceof adt.__Base__ && type.equals(x)
          || type === x) return x;
        }
      }
      throw new TypeError('Unexpected type');
    };
  };
})(
  typeof exports !== 'undefined' ? exports : (this.adt = {})
);
<commit_msg>Fix enumeration bug, tweaks<commit_after>// adt.js
// ------
// Algebraic data types and immutable structures in Javascript
//
// version : 0.5.0
// author  : Nathan Faubion <nathan@n-son.com>
// license : MIT

;(function (adt) {
  'use strict';

  // Cache some prototype methods for easy use.
  var slice = Array.prototype.slice;
  var funcApply = Function.prototype.apply;

  // Utility functions
  adt.util = {};

  // Return an array of the supplied argument. Used for `arguments` objects.
  adt.util.toArray = function (a) {
    var dest = [], i = 0, len = a.length;
    for (; i < len; i++) dest[i] = a[i];
    return dest;
  };

  // A basic extend method for copying attributes of on object into another.
  adt.util.extend = function (dest /*, sources... */) {
    var args = slice.call(arguments, 1);
    for (var i = 0, len = args.length; i < len; i++) {
      for (var k in args[i]) {
        if (args[i].hasOwnProperty(k)) dest[k] = args[i][k];
      }
    }
    return dest;
  };

  // Given a constructor and an array of args, instanciates a new objects with
  // said args. Like calling `apply` on a constructor.
  adt.util.ctrApply = function (ctr, args) {
    var C = function () {};
    C.prototype = ctr.prototype;
    var inst = new C();
    var ret = ctr.apply(inst, args);
    return Object(ret) === ret ? ret : inst;
  };

  // Partially applies arguments to a function in the same way `bind` would,
  // but doesn't cement the context in anyway.
  adt.util.partial = function (func) {
    var args = slice.call(arguments, 1);
    return function () {
      return func.apply(this, args.concat(adt.util.toArray(arguments)));
    };
  };

  // Standard inheritance helper.
  adt.util.inherit = function (sup, sub) {
    var C = function () {};
    C.prototype = sup.prototype;
    sub.prototype = new C();
    sub.prototype.constructor = sub;
    return sub;
  };

  // Helper function to return a unique id
  adt.util.uniqueId = (function (id) {
    return function (pre) { return pre + (id++); };
  })(0);

  // Base class from which all adt.js classes inherit.
  // All adt.js classes should have a clone method that clones the
  // object as best it can.
  adt.__Base__ = function () {};

  // Generates a new set of Algebraic data types. This will create a lot of
  // boilerplate to help with type checking. Each type will get is<type>()
  // methods that return true or false.
  adt.data = function () {
    var targ0 = typeof arguments[0];
    var callback, types, names;

    // adt.data(typesObj)
    if (targ0 === 'object') {
      types = arguments[0];

      // Call adt.data again with a desugared callback.
      return adt.data(function (d, type) {
        for (var name in types) type(name, types[name]);
      });
    }

    // adt.data(callback)
    callback = arguments[0] || function () {};
    names = [];

    // Create a new parent class.
    // This class should never be created using `new`. You obviously can,
    // but it won't be of much use. You can however override the apply method
    // to create default instances.
    var D = adt.util.inherit(adt.__Base__, function () {
      if (!(this instanceof D) && D.apply !== funcApply) {
        return D.apply(this, arguments);
      }
    });

    // Declares an adt type as part of the family.
    D.type = function (name, tmpl) {
      if (typeof name !== 'string') {
        tmpl = name;
        name = adt.util.uniqueId('Anonymous');
      }
      // Create a new adt template if not provided with one
      if (!tmpl) tmpl = adt.single();
      else if (typeof tmpl !== 'function') tmpl = adt.record(tmpl);

      // Add typechecking attributes for this type.
      D.prototype['is' + name] = false;

      // Call the template to build our type and export it on the parent type.
      D[name] = tmpl(D, name);
      names.push(name);
      return D[name];
    };

    // Call the callback with the constructor as the context.
    var types = callback.call(D, D, D.type);

    // If an object was returned in the callback, assume it's a mapping of
    // more types to add.
    if (typeof types === 'object' && !(types instanceof adt.__Base__)) {
      for (var name in types) {
        if (types.hasOwnProperty(name)) D.type(name, types[name]);
      }
    }

    // Keep the type function around because it allows for nice type
    // declarations, but give the option to seal it. This will call `seal`
    // on any sub types to.
    D.seal = function () {
      var i = 0, len = names.length, seal;
      for (; i < len; i++) {
        seal = this[name].seal;
        seal instanceof Function && seal();
      }
      delete D.type;
      delete D.seal;
      return D;
    };

    // Export names as a meta object
    D.__names__ = names;
    return D;
  };

  // Create a single empty class that always return the same instance.
  // Useful for sentinal values such as Nothing, Empty, etc.
  adt.single = function () {
    var ctr, inst;
    ctr = function () {
      if (!(this instanceof ctr)) return new ctr();
      if (inst) return inst;
      inst = this;
    };

    return function (parent, name) {
      adt.util.inherit(parent, ctr);
      ctr.className = name;
      ctr.prototype.clone = function () { return inst; };
      ctr.prototype.equals = function (obj) { return this === obj; };
      ctr.prototype.toString = function () { return name; };
      ctr.prototype['is' + name] = true;
      return new ctr();
    };
  };

  // Create a new class that has named fields. Each value can be obtained by
  // calling the name as a method. Each value can be changed by calling `set`
  // with an object of values to update. `set` returns a clone of the object.
  adt.record = function () {
    var targ0 = typeof arguments[0];
    var names, constraints, ctr, fields, callback;

    // adt.record(fieldNames...)
    if (targ0 === 'string') {
      var args = adt.util.toArray(arguments);
      return adt.record(function (r, field) {
        var i = 0, len = args.length;
        for (; i < len; i++) field(args[i], adt.any);
      });
    }

    // adt.record(fieldsObj)
    else if (targ0 === 'object') {
      fields = arguments[0];
      return adt.record(function (r, field) {
        for (var name in fields) field(name, fields[name]);
      });
    }

    // adt.record(callback)
    callback = arguments[0] || function () {};
    names = [];
    constraints = {};

    // A record's constructor can be called without `new` and will also throw
    // an error if called with too many arguments. Its arguments can be curried
    // as long as it isn't called with the `new` keyword.
    ctr = function () {
      var args = adt.util.toArray(arguments);
      var len = names.length;
      if (!(this instanceof ctr)) {
        return args.length < len
          ? adt.util.partial.apply(null, [ctr].concat(args))
          : adt.util.ctrApply(ctr, args);
      } else {
        if (args.length < len) throw new Error('Too few arguments');
        if (args.length > len) throw new Error('Too many arguments');
        var i = 0, len = args.length, n;
        for (; i < len; i++) {
          n = names[i];
          this[n] = constraints[n](args[i]);
        }
      }
    };

    return function (parent, name) {
      adt.util.inherit(parent, ctr);
      ctr.className = name;
      ctr.prototype['is' + name] = true;

      // Custom `toString` implementation.
      ctr.prototype.toString = function () {
        var vals = ctr.unapply(this);
        return name + (vals.length ? '(' + vals.join(', ') + ')' : '');
      };

      // This clone method will clone any values that are also adt types and
      // leaves anything else alone.
      ctr.prototype.clone = function () {
        var args = [];
        var i = 0, len = names.length, val;
        for (; i < len; i++) {
          val = this[names[i]];
          args.push(val instanceof adt.__Base__ ? val.clone() : val);
        }
        return ctr.apply(null, args);
      };

      // Lookup fields by either name or index. Throws an error if the name
      // doesn't exist or if the index is out of range.
      ctr.prototype.get = function (field) {
        if (typeof field === 'number') {
          if (field < 0 || field > names.length - 1) {
            throw new Error('Field index out of range');
          }
          field = names[field];
        } else {
          if (!constraints.hasOwnProperty(field)) {
            throw new Error('Field name does not exist');
          }
        }
        return this[field];
      };

      // Creates a new instance with the specified values changed.
      ctr.prototype.set = function (vals) {
        var args = []
        var i = 0, len = names.length, val, n;
        for (; i < len; i++) {
          n = names[i];
          val = n in vals ? vals[n] : this[n];
          args.push(val);
        }
        return ctr.apply(null, args);
      };

      // Performs deep equality checks on each field as long as it holds an
      // adt type. Any other types will just be compared using ===.
      ctr.prototype.equals = function (that) {
        if (this === that) return true;
        if (!(that instanceof ctr)) return false;
        var i = 0, len = names.length;
        var vala, valb, n;
        for (; i < len; i++) {
          n = names[i];
          vala = this[n];
          valb = that[n];
          if (vala instanceof adt.__Base__) {
            if (!vala.equals(valb)) return false;
          } else if (vala !== valb) return false;
        }
        return true;
      };

      // Creates a new instance using key-value pairs instead of by
      // positional arguments.
      ctr.create = function (vals) {
        var args = [];
        var i = 0, len = names.length, n;
        for (; i < len; i++) {
          n = names[i];
          if (!(n in vals)) throw new Error('Could not find field in arguments: ' + n);
          args.push(vals[n]);
        }
        return ctr.apply(null, args);
      };

      // Returns an array representation of the fields.
      ctr.unapply = function (inst) {
        var vals = [];
        var i = 0, len = names.length;
        for (; i < len; i++) vals.push(inst[names[i]]);
        return vals;
      };

      // Returns an object representation of the field.
      ctr.unapplyObj = function (inst) {
        var vals = {};
        var i = 0, len = names.length;
        for (; i < len; i++) vals[names[i]] = inst[names[i]];
        return vals;
      };

      // Declares a field as part of the type.
      ctr.field = function (name, constraint) {
        if (!constraint) constraint = adt.any;
        if (typeof constraint !== 'function') {
          throw new TypeError('Constraints must be functions')
        }
        names.push(name);
        constraints[name] = constraint;
        return ctr;
      };

      // Call the callback with the contructor as the context.
      fields = callback.call(ctr, ctr, ctr.field);

      // If an object was returned in the callback, assume it's a mapping of
      // more fields to add.
      if (typeof fields === 'object' && fields !== ctr) {
        for (var name in fields) {
          if (!fields.hasOwnProperty(name)) continue;
          ctr.field(name, fields[name]);
        }
      }

      // Export names and constraints as meta attributes.
      ctr.__names__ = names;
      ctr.__constraints__ = constraints;

      // Keep the field function around because it allows for nice type
      // declarations, but give the option to seal it.
      ctr.seal = function () {
        delete ctr.field;
        delete ctr.seal;
        return ctr;
      };

      return ctr;
    };
  };

  // Enumerations are types that have an order and can be compared using lt,
  // gt, lte, and gte.
  adt.enumeration = function () {
    var targ0 = typeof arguments[0];

    // adt.enumeration(typeNames...)
    if (targ0 === 'string') {
      var args = adt.util.toArray(arguments);
      return adt.enumeration(function (r, type) {
        var i = 0, len = args.length;
        for (; i < len; i++) type(args[i]);
      });
    }

    // Create the types
    var E = adt.data.apply(null, arguments);
    var order = 0;

    // Helper to add the order attribute to a type.
    function addOrder (that) {
      if (that.constructor) that = that.constructor;
      that.__order__ = order++;
      return that;
    }

    // Helper function to make sure we are comparing the same types. We can't
    // compare the order of a different type, so it throws a TypeError if the
    // types are incompatible.
    function verifyType (that) {
      if (!(that instanceof E)) throw new TypeError('Unexpected type');
      return true;
    }

    // Helper to return the order of the particular instance
    function orderOf (that) {
      return that.constructor.__order__;
    }

    // Iterate through created types, applying an order meta attribute.
    var i = 0, len = E.__names__.length;
    for (; i < len; i++) addOrder(E[E.__names__[i]]);

    // Patch the type function to also add an order to any types created later.
    var oldType = E.type;
    E.type = function (name, tmpl) {
      return addOrder(oldType.call(E, name, tmpl));
    };

    // Less than
    E.prototype.lt = function (that) {
      return verifyType(that) && orderOf(this) < orderOf(that);
    };

    // Less than or equal
    E.prototype.lte = function (that) {
      return verifyType(that) && orderOf(this) <= orderOf(that);
    };

    // Greater than
    E.prototype.gt = function (that) {
      return verifyType(that) && orderOf(this) > orderOf(that);
    };

    // Greater than or equal
    E.prototype.gte = function (that) {
      return verifyType(that) && orderOf(this) >= orderOf(that);
    };

    // Equal (not that same as `equals`
    E.prototype.eq = function (that) {
      return verifyType(that) && orderOf(this) === orderOf(that);
    };

    // Not equals
    E.prototype.neq = function (that) {
      return verifyType(that) && orderOf(this) !== orderOf(that);
    };

    return E;
  };

  // Creates a singleton type that belongs to its own family.
  adt.newtype = function () {
    var args = adt.util.toArray(arguments);
    var data = adt.data();
    return data.type.apply(data, args);
  };

  // A contraint function that will accept any value.
  adt.any = function (x) { return x; };

  // A constraint generator that will perform instanceof checks on the value
  // to make sure it is of the correct type. If a value besides a function
  // is passed in, it will perform equality checks on it.
  //
  // It has special handling for Number, String, and Boolean. Literals won't
  // match an instanceof check, but will match with typeof.
  adt.only = function () {
    var args = arguments;
    return function (x) {
      var i = 0, len = args.length, type;
      for (; i < len; i++) {
        type = args[i];
        if (type instanceof Function) {
          if (x instanceof type
          || type === Number && typeof x === 'number'
          || type === String && typeof x === 'string'
          || type === Boolean && typeof x === 'boolean') return x;
        } else {
          if (type instanceof adt.__Base__ && type.equals(x)
          || type === x) return x;
        }
      }
      throw new TypeError('Unexpected type');
    };
  };
})(
  typeof exports !== 'undefined' ? exports : (this.adt = {})
);
<|endoftext|>


<commit_before>// (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP

import React, { Component } from 'react';
import Tiles from 'grommet/components/Tiles';
import Box from 'grommet/components/Box';
import Animate from 'grommet/components/Animate';

export default class ScrollAnimation extends Component {
  constructor (props) {
    super(props);
    this._onScroll = this._onScroll.bind(this);
    this.state = {
      scrollableHeight: 0,
      scrollProgress: 0
    };
  }

  _onScroll (event) {
    const element = event.target;
    const scrollTop = element.scrollTop;
    const scrollHeight = element.scrollHeight;
    const scrollableHeight = scrollHeight - 500;
    const scrollPercent = scrollTop / scrollableHeight;
    const scrollProgress = Math.round(scrollPercent * 100);

    if (scrollableHeight !== this.state.scrollableHeight) {
      this.setState({ scrollableHeight });
    }
    if (scrollProgress !== this.state.scrollProgress) {
      this.setState({ scrollProgress });
    }
  }

  _renderBoxes (amount, index) {
    const { scrollableHeight, scrollProgress } = this.state;
    const columnWidth = 100 / amount;
    const height = 250;

    return new Array(amount).fill().map((c, i) => {
      return (
        <Animate
          enter={{ animation: 'slide-up', duration: 500, delay: (i + 1) * 150 }}
          leave={{ animation: 'slide-down', duration: 500, delay: (i + 1) * 150 }}
          component={Box}
          visible={scrollProgress > Math.round((height * index) / scrollableHeight * 50)}
          keep={true}
          colorIndex="brand" justify="center" align="center" key={i}
          style={{ flex: `0 0 ${columnWidth}%`, height }}
        >

{i + 1}

        </Animate>
      );
    });
  }

  render () {
    const sections = new Array(4).fill().map((c, i) => {
      return (
        <Tiles key={`section-${i}`} flex={false}>
          {this._renderBoxes(3, i)}
        </Tiles>
      );
    });

    return (
      <Box
        onScroll={this._onScroll}
        pad="medium"
        style={{ height: 500, overflow: 'auto' }}
      >
        {sections}
      </Box>
    );
  }
};
<commit_msg>Wrap ScrollAnimation in Example component<commit_after>// (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP

import React, { Component } from 'react';
import Tiles from 'grommet/components/Tiles';
import Box from 'grommet/components/Box';
import Animate from 'grommet/components/Animate';
import Example from '../../Example';

export default class ScrollAnimation extends Component {
  constructor (props) {
    super(props);
    this._onScroll = this._onScroll.bind(this);
    this.state = {
      scrollableHeight: 0,
      scrollProgress: 0
    };
  }

  _onScroll (event) {
    const element = event.target;
    const scrollTop = element.scrollTop;
    const scrollHeight = element.scrollHeight;
    const scrollableHeight = scrollHeight - 500;
    const scrollPercent = scrollTop / scrollableHeight;
    const scrollProgress = Math.round(scrollPercent * 100);

    if (scrollableHeight !== this.state.scrollableHeight) {
      this.setState({ scrollableHeight });
    }
    if (scrollProgress !== this.state.scrollProgress) {
      this.setState({ scrollProgress });
    }
  }

  render () {
    const { scrollProgress } = this.state;

    return (
      <Example name="Scroll" code={
        <Box
          onScroll={this._onScroll}
          pad="medium" colorIndex="light-2"
          style={{ height: 500, overflow: 'auto' }}
        >
          <Tiles flex={false}>
            <Animate
              enter={{ animation: 'slide-up', duration: 500, delay: 150 }}
              leave={{ animation: 'slide-down', duration: 500, delay: 150 }}
              component={Box} visible={scrollProgress > 0} keep={true}
              colorIndex="brand" justify="center" align="center"
              style={{ flex: `0 0 33.333%`, height: 250 }}
            >

1

            </Animate>
            <Animate
              enter={{ animation: 'slide-up', duration: 500, delay: 300 }}
              leave={{ animation: 'slide-down', duration: 500, delay: 300 }}
              component={Box} visible={scrollProgress > 0} keep={true}
              colorIndex="brand" justify="center" align="center"
              style={{ flex: `0 0 33.333%`, height: 250 }}
            >

2

            </Animate>
            <Animate
              enter={{ animation: 'slide-up', duration: 500, delay: 450 }}
              leave={{ animation: 'slide-down', duration: 500, delay: 450 }}
              component={Box} visible={scrollProgress > 0} keep={true}
              colorIndex="brand" justify="center" align="center"
              style={{ flex: `0 0 33.333%`, height: 250 }}
            >

3

            </Animate>
          </Tiles>
          <Tiles flex={false}>
            <Animate
              enter={{ animation: 'slide-up', duration: 500, delay: 150 }}
              leave={{ animation: 'slide-down', duration: 500, delay: 150 }}
              component={Box} visible={scrollProgress > 16} keep={true}
              colorIndex="brand" justify="center" align="center"
              style={{ flex: `0 0 33.333%`, height: 250 }}
            >

1

            </Animate>
            <Animate
              enter={{ animation: 'slide-up', duration: 500, delay: 300 }}
              leave={{ animation: 'slide-down', duration: 500, delay: 300 }}
              component={Box} visible={scrollProgress > 16} keep={true}
              colorIndex="brand" justify="center" align="center"
              style={{ flex: `0 0 33.333%`, height: 250 }}
            >

2

            </Animate>
            <Animate
              enter={{ animation: 'slide-up', duration: 500, delay: 450 }}
              leave={{ animation: 'slide-down', duration: 500, delay: 450 }}
              component={Box} visible={scrollProgress > 16} keep={true}
              colorIndex="brand" justify="center" align="center"
              style={{ flex: `0 0 33.333%`, height: 250 }}
            >

3

            </Animate>
          </Tiles>
          <Tiles flex={false}>
            <Animate
              enter={{ animation: 'slide-up', duration: 500, delay: 150 }}
              leave={{ animation: 'slide-down', duration: 500, delay: 150 }}
              component={Box} visible={scrollProgress > 32} keep={true}
              colorIndex="brand" justify="center" align="center"
              style={{ flex: `0 0 33.333%`, height: 250 }}
            >

1

            </Animate>
            <Animate
              enter={{ animation: 'slide-up', duration: 500, delay: 300 }}
              leave={{ animation: 'slide-down', duration: 500, delay: 300 }}
              component={Box} visible={scrollProgress > 32} keep={true}
              colorIndex="brand" justify="center" align="center"
              style={{ flex: `0 0 33.333%`, height: 250 }}
            >

2

            </Animate>
            <Animate
              enter={{ animation: 'slide-up', duration: 500, delay: 450 }}
              leave={{ animation: 'slide-down', duration: 500, delay: 450 }}
              component={Box} visible={scrollProgress > 32} keep={true}
              colorIndex="brand" justify="center" align="center"
              style={{ flex: `0 0 33.333%`, height: 250 }}
            >

3

            </Animate>
          </Tiles>
        </Box>
      } />
    );
  }
};
<|endoftext|>


<commit_before>// All other packages automatically depend on this one

Package.describe({
  summary: "Core Meteor environment",
  version: '1.1.5-winr.6'
});

Package.registerBuildPlugin({
  name: "basicFileTypes",
  sources: ['plugin/basic-file-types.js']
});

Npm.depends({
  "double-ended-queue": "2.1.0-0"
});

Package.onUse(function (api) {
  api.use('underscore', ['client', 'server']);

  api.export('Meteor');

  api.addFiles('client_environment.js', 'client');
  api.addFiles('cordova_environment.js', 'web.cordova');
  api.addFiles('server_environment.js', 'server');
  api.addFiles('helpers.js', ['client', 'server']);
  api.addFiles('setimmediate.js', ['client', 'server']);
  api.addFiles('timers.js', ['client', 'server']);
  api.addFiles('errors.js', ['client', 'server']);
  api.addFiles('fiber_helpers.js', 'server');
  api.addFiles('fiber_stubs_client.js', 'client');
  api.addFiles('startup_client.js', ['client']);
  api.addFiles('startup_server.js', ['server']);
  api.addFiles('debug.js', ['client', 'server']);

  // dynamic variables, bindEnvironment
  // XXX move into a separate package?
  api.addFiles('dynamics_browser.js', 'client');
  api.addFiles('dynamics_nodejs.js', 'server');

  // note server before common. usually it is the other way around, but
  // in this case server must load first.
  api.addFiles('url_server.js', 'server');
  api.addFiles('url_common.js', ['client', 'server']);
});

Package.onTest(function (api) {
  api.use(['underscore', 'tinytest', 'test-helpers']);

  api.addFiles('browser_environment_test.js', 'web.browser');
  api.addFiles('client_environment_test.js', 'client');
  api.addFiles('cordova_environment_test.js', 'web.cordova');
  api.addFiles('server_environment_test.js', 'server');

  api.addFiles('helpers_test.js', ['client', 'server']);
  api.addFiles('dynamics_test.js', ['client', 'server']);

  api.addFiles('fiber_helpers_test.js', ['server']);
  api.addFiles('wrapasync_test.js', ['server']);

  api.addFiles('url_tests.js', ['client', 'server']);

  api.addFiles('timers_tests.js', ['client', 'server']);

  api.addFiles('debug_test.js', 'client');

  api.addFiles('bare_test_setup.js', 'client', {bare: true});
  api.addFiles('bare_tests.js', 'client');
});
<commit_msg>Include file in package<commit_after>// All other packages automatically depend on this one

Package.describe({
  summary: "Core Meteor environment",
  version: '1.1.5-winr.6'
});

Package.registerBuildPlugin({
  name: "basicFileTypes",
  sources: ['plugin/basic-file-types.js']
});

Npm.depends({
  "double-ended-queue": "2.1.0-0"
});

Package.onUse(function (api) {
  api.use('underscore', ['client', 'server']);

  api.export('Meteor');

  api.addFiles('client_environment.js', 'client');
  api.addFiles('cordova_environment.js', 'web.cordova');
  api.addFiles('server_environment.js', 'server');
  api.addFiles('helpers.js', ['client', 'server']);
  api.addFiles('setimmediate.js', ['client', 'server']);
  api.addFiles('timers.js', ['client', 'server']);
  api.addFiles('errors.js', ['client', 'server']);
  api.addFiles('fiber_helpers.js', 'server');
  api.addFiles('fiber_stubs_client.js', 'client');
  api.addFiles('startup_client.js', ['client']);
  api.addFiles('startup_server.js', ['server']);
  api.addFiles('debug.js', ['client', 'server']);

  // dynamic variables, bindEnvironment
  // XXX move into a separate package?
  api.addFiles('dynamics_browser.js', 'client');
  api.addFiles('dynamics_nodejs.js', 'server');

  // note server before common. usually it is the other way around, but
  // in this case server must load first.
  api.addFiles('url_server.js', 'server');
  api.addFiles('url_common.js', ['client', 'server']);

  // People expect process.exit() to not swallow console output.
  // On Windows, it sometimes does, so we fix it for all apps and packages
  api.addFiles('flush-buffers-on-exit-in-windows.js', 'server');
});

Package.onTest(function (api) {
  api.use(['underscore', 'tinytest', 'test-helpers']);

  api.addFiles('browser_environment_test.js', 'web.browser');
  api.addFiles('client_environment_test.js', 'client');
  api.addFiles('cordova_environment_test.js', 'web.cordova');
  api.addFiles('server_environment_test.js', 'server');

  api.addFiles('helpers_test.js', ['client', 'server']);
  api.addFiles('dynamics_test.js', ['client', 'server']);

  api.addFiles('fiber_helpers_test.js', ['server']);
  api.addFiles('wrapasync_test.js', ['server']);

  api.addFiles('url_tests.js', ['client', 'server']);

  api.addFiles('timers_tests.js', ['client', 'server']);

  api.addFiles('debug_test.js', 'client');

  api.addFiles('bare_test_setup.js', 'client', {bare: true});
  api.addFiles('bare_tests.js', 'client');
});
<|endoftext|>


<commit_before>// This is your spec helper. You can require other javascript files in this one and they'll be loaded into your suite.
//
// Teabag includes some useful javascripts for you, and you can include them here.
// require jasmine-jquery
// require sinon
// require expect
//
// You're also able to include any of the files in support as well.
// require support/your-support-file
//
// Deferring execution
// This is useful if you're using CommonJS or RequireJS or some other asynchronous loading method. To defer test
// execution until everything has been loaded asynchronously you can tell Teabag to defer, which then allows you to call
// Teabag.execute() at a later time. Here's a simple example:
//
// Teabag.defer = true
// setTimeout(function() { Teabag.execute() }, 1000)
//
// Spec files
// By default Teabag will go looking for files that match the _spec.{js,js.coffee,.coffee} naming convention, so just
// start dropping filename_spec.js files into this, or any nested path, and they'll automatically be picked up and
// included in the default suite.  If you're interested in creating custom suites, check out the configuration in
// config/initializers/teabag.rb
//
// For more information:
// http://github.com/modeset/teabag
<commit_msg>adjusted wording.<commit_after>// This is your spec helper.
//
// You can require other javascript files here.
//
// Teabag includes some useful javascripts for you, and you can include them here.
// require jasmine-jquery
// require sinon
// require expect
//
// You're also able to include any of the files in support as well.
// require support/your-support-file
//
// Deferring execution
// This is useful if you're using CommonJS or RequireJS or some other asynchronous loading method. To defer test
// execution until everything has been loaded asynchronously you can tell Teabag to defer, which then allows you to call
// Teabag.execute() at a later time. Here's a simple example:
//
// Teabag.defer = true
// setTimeout(function() { Teabag.execute() }, 1000)
//
// Spec files
// By default Teabag will go looking for files that match the _spec.{js,js.coffee,.coffee} naming convention, so just
// start dropping filename_spec.js files into this, or any nested path, and they'll automatically be picked up and
// included in the default suite.  If you're interested in creating custom suites, check out the configuration in
// config/initializers/teabag.rb
//
// If you'd rather just require your spec files here manually (to control order for instance) you can disable the suite
// matcher in the configuration and then use this file as a manifest.
//
// For more information:
// http://github.com/modeset/teabag
<|endoftext|>


<commit_before>Package.describe({
  summary: 'Expressive, dynamic, robust CSS',
  version: "2.513.9-beta.1"
});

Package.registerBuildPlugin({
  name: 'compileStylusBatch',
  use: ['ecmascript', 'caching-compiler'],
  sources: [
    'plugin/compile-stylus.js'
  ],
  npmDependencies: {
    stylus: "https://github.com/meteor/stylus/tarball/bb47a357d132ca843718c63998eb37b90013a449", // fork of 0.54.5
    nib: "1.1.2",
    "autoprefixer-stylus": "0.9.4"
  }
});

Package.onUse(function (api) {
  api.use('isobuild:compiler-plugin@1.0.0');
});

Package.onTest(function (api) {
  api.use(['tinytest', 'stylus', 'test-helpers', 'templating']);
  api.addFiles([
    'stylus_tests.html',
    'stylus_tests.styl',
    'stylus_tests.import.styl',
    'stylus_tests.js'
  ],'client');
});
<commit_msg>Remove -beta.n suffix from stylus package before republishing.<commit_after>Package.describe({
  summary: 'Expressive, dynamic, robust CSS',
  version: "2.513.9"
});

Package.registerBuildPlugin({
  name: 'compileStylusBatch',
  use: ['ecmascript', 'caching-compiler'],
  sources: [
    'plugin/compile-stylus.js'
  ],
  npmDependencies: {
    stylus: "https://github.com/meteor/stylus/tarball/bb47a357d132ca843718c63998eb37b90013a449", // fork of 0.54.5
    nib: "1.1.2",
    "autoprefixer-stylus": "0.9.4"
  }
});

Package.onUse(function (api) {
  api.use('isobuild:compiler-plugin@1.0.0');
});

Package.onTest(function (api) {
  api.use(['tinytest', 'stylus', 'test-helpers', 'templating']);
  api.addFiles([
    'stylus_tests.html',
    'stylus_tests.styl',
    'stylus_tests.import.styl',
    'stylus_tests.js'
  ],'client');
});
<|endoftext|>


<commit_before>/*
  Copyright (c) 2013 Ankur Sethi <contact@ankursethi.in>
  Licensed under the terms of the MIT license.
  See the file LICENSE for copying permissions.
*/

'use strict';

//
// The session timer. This service provides a timer that can be started and
// stopped, and keeps track of the time since the timer was started in
// milliseconds.
//
angular.module('SecondhandApp')
  .factory('SessionTimer', ['$timeout', function($timeout) {
    var SessionTimer = {
      currentTime: 0,
      currentTask: null,
      currentProject: null,
      running: false
    };

    var updateTimer = function() {
      SessionTimer.currentTime = new Date() - SessionTimer._lastTick;

      if (SessionTimer.running === true) {
        console.log('tick for task ' + SessionTimer.currentTask.name);
        SessionTimer._timeout = $timeout(updateTimer, 1000);
      }
    };

    SessionTimer.startTimer = function(project, task) {
      if (SessionTimer.running) {
        SessionTimer.pauseTimer();
        SessionTimer.resetTimer();
      }

      SessionTimer.currentTask = task;
      SessionTimer.currentProject = project;

      // Bookkeeping.
      SessionTimer.running = true;
      SessionTimer._lastTick = new Date();
      SessionTimer._timeout = $timeout(updateTimer, 1000);
    };

    SessionTimer.pauseTimer = function() {
      SessionTimer.running = false;
      $timeout.cancel(SessionTimer._timeout);
    };

    SessionTimer.resetTimer = function() {
      SessionTimer.currentTime = 0;
      delete SessionTimer._lastTick;
    };

    return SessionTimer;
  }]);
<commit_msg>Keep track of start time and end time for a task.<commit_after>/*
  Copyright (c) 2013 Ankur Sethi <contact@ankursethi.in>
  Licensed under the terms of the MIT license.
  See the file LICENSE for copying permissions.
*/

'use strict';

//
// The session timer. This service provides a timer that can be started and
// stopped, and keeps track of the time since the timer was started in
// milliseconds.
//
angular.module('SecondhandApp')
  .factory('SessionTimer', ['$timeout', function($timeout) {
    var SessionTimer = {
      currentTime: 0,
      startTime: null,
      endTime: null,
      currentTask: null,
      currentProject: null,
      running: false
    };

    var updateTimer = function() {
      SessionTimer.currentTime = new Date() - SessionTimer._lastTick;

      if (SessionTimer.running === true) {
        console.log('tick for task ' + SessionTimer.currentTask.name);
        SessionTimer._timeout = $timeout(updateTimer, 1000);
      }
    };

    SessionTimer.startTimer = function(project, task) {
      if (SessionTimer.running) {
        SessionTimer.pauseTimer();
        SessionTimer.resetTimer();
      }

      SessionTimer.currentTask = task;
      SessionTimer.currentProject = project;

      // Bookkeeping.
      SessionTimer.running = true;
      SessionTimer.startTime = new Date();
      SessionTimer._lastTick = SessionTimer.startTime;
      SessionTimer._timeout = $timeout(updateTimer, 1000);
    };

    SessionTimer.pauseTimer = function() {
      SessionTimer.running = false;
      SessionTimer.endTime = new Date();
      $timeout.cancel(SessionTimer._timeout);
    };

    SessionTimer.resetTimer = function() {
      SessionTimer.currentTime = 0;
      delete SessionTimer._lastTick;
    };

    return SessionTimer;
  }]);
<|endoftext|>


<commit_before>/*jshint esversion:6, node:true*/
'use strict';

const extend = require('gextend');

var DEFAULTS = {
    middleware: {
        use:   require('./middleware').use,
        order: require('./middleware').order,
    }
};

module.exports.init = function(context, config){

    const express = require('express');
    var app = express();

    /*
     * Enable middleware to use context,
     * i.e. to publish an event system wide.
     * context.emit('web.request.createUser', user);
     */
    config.context = context;

    /*
     * Create a logger for our express app.
     * This can be trickled down to middleware
     * as well.
     */
    config.logger = context.getLogger(config.name);

    /*
     * basedir will be used by middleware to
     * find the `public` directory, `views`,
     * etc...
     */
    config.basedir = __dirname;

    setup(app, config);

    return app;
};

function setup(app, config){

    config = extend({}, DEFAULTS, config);

    var use = config.middleware.use;

    var order = config.middleware.order;

    order.map((middleware)=>{
        use[middleware](app, config);
    });
}
<commit_msg>defaultApp: take basedir from config<commit_after>/*jshint esversion:6, node:true*/
'use strict';

const extend = require('gextend');

var DEFAULTS = {
    middleware: {
        use:   require('./middleware').use,
        order: require('./middleware').order,
    }
};

module.exports.init = function(context, config){

    const express = require('express');
    var app = express();

    /*
     * Enable middleware to use context,
     * i.e. to publish an event system wide.
     * context.emit('web.request.createUser', user);
     */
    config.context = context;

    /*
     * Create a logger for our express app.
     * This can be trickled down to middleware
     * as well.
     */
    config.logger = context.getLogger(config.name);

    /*
     * basedir will be used by middleware to
     * find the `public` directory, `views`,
     * etc...
     */
    if(!config.basedir){
        config.basedir = __dirname;
        config.logger.warn('You did not specify a "basedir"?');
        config.logger.warn('We are making a guess: %s', config.basedir);
    } else {
        config.logger.warn('Loading views and assets from: %s', config.basedir);
    }

    setup(app, config);

    return app;
};

function setup(app, config){

    config = extend({}, DEFAULTS, config);

    var use = config.middleware.use;

    var order = config.middleware.order;

    order.map((middleware)=>{
        use[middleware](app, config);
    });
}
<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');
var SurfaceCommand = require('../../ui/SurfaceCommand');
var uuid = require('../../util/uuid');
var deleteNode = require('../../model/transform/deleteNode');

var annotationHelpers = require('../../model/annotationHelpers');

var listUtils = require('./listUtils');

var ListCommand = function(surface) {
  SurfaceCommand.call(this, surface);
};

ListCommand.Prototype = function() {

  this.getSelection = function() {
    return this.getSurface().getSelection();
  };

  this.getCommandState = function() {
    var surface = this.getSurface();
    var sel = this.getSelection();
    var doc = this.getDocument();
    var active, disabled;

    if (sel.isPropertySelection()){
      disabled = !surface.isEnabled() || sel.isNull();
      var path = sel.getPath();
      var node = doc.get(path[0]);
      active = (node.type === 'list-item') && (node.ordered === this.ordered);
    } else if (sel.isContainerSelection()) {
      // is enabled only if all selected nodes are paragraphs
      var nodes = sel.getContainer().nodes;
      var selectedNodes = _.slice(nodes, nodes.indexOf(sel.startPath[0]), nodes.indexOf(sel.endPath[0])+1);
      disabled = !_.every(_.map(selectedNodes, function(elem){
        return (doc.get(elem).type) === 'paragraph';
      }));
      active = false;
    }

    return {
      active: active,
      disabled: disabled
    };
  };

  // Execute command and trigger transformations
  // TODO: This currently works for preoperty selection only. Make it work on container selection too.
  this.execute = function() {
    var sel = this.getSelection();
    var doc = this.getDocument();
    var surface = this.getSurface();
    var self = this;

    if (!sel.isPropertySelection()){
      var nodes = sel.getContainer().nodes;
      var selectedNodeIds = _.slice(nodes, nodes.indexOf(sel.startPath[0]), nodes.indexOf(sel.endPath[0])+1);
      var selectedNodes = _.map(selectedNodeIds, function(elem){
        return doc.get(elem);
      });
      var containerId = this.getContainerId();
      surface.transaction(function(tx, args){
        var container = tx.get(containerId);
        var newList = {
          id: uuid("list"),
          type: "list",
          ordered: self.ordered
        };
        var items = [];
        var newListItem;
        for (var i=0; i<selectedNodes.length; i++){
          newListItem = {
            id: uuid("list-item"),
            parent: newList.id,
            ordered: newList.ordered,
            content: selectedNodes[i].content,
            type: "list-item"
          };
          tx.create(newListItem);
          annotationHelpers.transferAnnotations(tx, [selectedNodes[i].id, 'content'], 0, [newListItem.id, 'content'], 0);
          items.push(newListItem.id);
        }
        newList.items = items;
        tx.create(newList);
        var pos = container.getPosition(sel.startPath[0]);
        // show the new list item and hide the old node
        container.show(newList.id, pos);
        for(i=0; i<selectedNodeIds.length; i++){
          deleteNode(tx, {nodeId: selectedNodeIds[i]});
        }
        var selection = tx.createSelection(null);
        args.selection = selection;
        return args;
      });
    } else {
      var path = sel.getPath();
      var node = doc.get(path[0]);

      surface.transaction(function(tx, args) {
        if (node.type === 'list-item') {
          if (node.ordered === self.ordered){
            // convert list item to paragraph
            var parentList = tx.get(node.parent);
            args.path = path;
            args.node = parentList;
            args.containerId = containerId;
            args = listUtils.listItemToParagraph(tx, args);
          } else {
            // switch list type between ordered and unordered list
            var items = tx.get([node.parent, 'items']);
            for (var i=0; i<items.length; i++){
              tx.set([items[i], 'ordered'], self.ordered);
            }
            tx.set([node.parent, 'ordered'], self.ordered);
          }
        } else {
          // convert node to list
          args.node = node;
          args.ordered = self.ordered;
          args.containerId = containerId;
          args.path = path;
          args.selection = sel;
          args = listUtils.paragraphToList(tx, args);
        }
        return args;
      });
    }
    return true;
  };
};

SurfaceCommand.extend(ListCommand);

module.exports = ListCommand;
<commit_msg>fix for undefined container id<commit_after>'use strict';

var _ = require('lodash');
var SurfaceCommand = require('../../ui/SurfaceCommand');
var uuid = require('../../util/uuid');
var deleteNode = require('../../model/transform/deleteNode');

var annotationHelpers = require('../../model/annotationHelpers');

var listUtils = require('./listUtils');

var ListCommand = function(surface) {
  SurfaceCommand.call(this, surface);
};

ListCommand.Prototype = function() {

  this.getSelection = function() {
    return this.getSurface().getSelection();
  };

  this.getCommandState = function() {
    var surface = this.getSurface();
    var sel = this.getSelection();
    var doc = this.getDocument();
    var active, disabled;

    if (sel.isPropertySelection()){
      disabled = !surface.isEnabled() || sel.isNull();
      var path = sel.getPath();
      var node = doc.get(path[0]);
      active = (node.type === 'list-item') && (node.ordered === this.ordered);
    } else if (sel.isContainerSelection()) {
      // is enabled only if all selected nodes are paragraphs
      var nodes = sel.getContainer().nodes;
      var selectedNodes = _.slice(nodes, nodes.indexOf(sel.startPath[0]), nodes.indexOf(sel.endPath[0])+1);
      disabled = !_.every(_.map(selectedNodes, function(elem){
        return (doc.get(elem).type) === 'paragraph';
      }));
      active = false;
    }

    return {
      active: active,
      disabled: disabled
    };
  };

  // Execute command and trigger transformations
  // TODO: This currently works for preoperty selection only. Make it work on container selection too.
  this.execute = function() {
    var sel = this.getSelection();
    var doc = this.getDocument();
    var surface = this.getSurface();
    var self = this;
    var containerId = this.getContainerId();

    if (!sel.isPropertySelection()){
      var nodes = sel.getContainer().nodes;
      var selectedNodeIds = _.slice(nodes, nodes.indexOf(sel.startPath[0]), nodes.indexOf(sel.endPath[0])+1);
      var selectedNodes = _.map(selectedNodeIds, function(elem){
        return doc.get(elem);
      });

      surface.transaction(function(tx, args){
        var container = tx.get(containerId);
        var newList = {
          id: uuid("list"),
          type: "list",
          ordered: self.ordered
        };
        var items = [];
        var newListItem;
        for (var i=0; i<selectedNodes.length; i++){
          newListItem = {
            id: uuid("list-item"),
            parent: newList.id,
            ordered: newList.ordered,
            content: selectedNodes[i].content,
            type: "list-item"
          };
          tx.create(newListItem);
          annotationHelpers.transferAnnotations(tx, [selectedNodes[i].id, 'content'], 0, [newListItem.id, 'content'], 0);
          items.push(newListItem.id);
        }
        newList.items = items;
        tx.create(newList);
        var pos = container.getPosition(sel.startPath[0]);
        // show the new list item and hide the old node
        container.show(newList.id, pos);
        for(i=0; i<selectedNodeIds.length; i++){
          deleteNode(tx, {nodeId: selectedNodeIds[i]});
        }
        var selection = tx.createSelection({
          type: 'property',
          path: [newListItem.id, 'content'],
          startOffset: newListItem.content.length
        });
        args.selection = selection;
        return args;
      });
    } else {
      var path = sel.getPath();
      var node = doc.get(path[0]);

      surface.transaction(function(tx, args) {
        if (node.type === 'list-item') {
          if (node.ordered === self.ordered){
            // convert list item to paragraph
            var parentList = tx.get(node.parent);
            args.path = path;
            args.node = parentList;
            args.containerId = containerId;
            args = listUtils.listItemToParagraph(tx, args);
          } else {
            // switch list type between ordered and unordered list
            var items = tx.get([node.parent, 'items']);
            for (var i=0; i<items.length; i++){
              tx.set([items[i], 'ordered'], self.ordered);
            }
            tx.set([node.parent, 'ordered'], self.ordered);
          }
        } else {
          // convert node to list
          args.node = node;
          args.ordered = self.ordered;
          args.containerId = containerId;
          args.path = path;
          args.selection = sel;
          args = listUtils.paragraphToList(tx, args);
        }
        return args;
      });
    }
    return true;
  };
};

SurfaceCommand.extend(ListCommand);

module.exports = ListCommand;
<|endoftext|>


<commit_before>var fs = require('fs'),
    path = require('path'),
    crypto = require('crypto');

require('express-hijackresponse');

module.exports = function (config) {
    config = config || {};
    var liveStyleClientCode = fs.readFileSync(path.resolve(__dirname, '../../livestyle-client.js'), 'utf-8')
            .replace(/liveStyleOptions\s*=\s*\{\}/, 'liveStyleOptions = ' + JSON.stringify(config)),
        liveStyleClientCodeMd5Hex = crypto.createHash('md5').update(liveStyleClientCode, 'utf-8').digest('hex');
    return function injectLiveStyleScriptIncludeIntoHtml(req, res, next) {
        if (req.url === '/__livestyle/livestyle-client.js') {
            res.set({
                'Content-Type': 'text/javascript',
                'ETag': '"' + liveStyleClientCodeMd5Hex + '"'
            });

            if (req.stale) {
                return res.send(liveStyleClientCode);
            } else {
                return res.sendStatus(304);
            }
        }

        if (req.method === 'GET' && (req.accepts('html') || (req.headers.accept && req.headers.accept.indexOf('*/*') !== -1))) {
            // Prevent If-None-Match revalidation with the downstream middleware with ETags that aren't suffixed with "-livestyle":
            var ifNoneMatch = req.headers['if-none-match'];
            if (ifNoneMatch) {
                var validIfNoneMatchTokens = ifNoneMatch.split(" ").filter(function (etag) {
                    return /-(?:livestyle|processimage)\"$/.test(etag);
                });
                if (validIfNoneMatchTokens.length > 0) {
                    req.headers['if-none-match'] = validIfNoneMatchTokens.join(" ");
                } else {
                    delete req.headers['if-none-match'];
                }
            }
            delete req.headers['if-modified-since'];
            delete req.headers['content-length'];
            delete req.headers['accept-encoding'];

            res.hijack(function (err, res) {
                if (err) {
                    return res.unhijack(function () {
                        next(err);
                    });
                }
                var contentType = res.getHeader('content-type');
                if (!contentType || !contentType.match(/^text\/html(?:;\s*charset=('|"|)([^'"]+)\1)?$/i)) {
                    res.unhijack(true);
                } else {
                    var oldETag = res.getHeader('ETag');
                    if (oldETag) {
                        var newETag = '"' + oldETag.replace(/^"|"$/g, '') + '-' + liveStyleClientCodeMd5Hex + '-livestyle"';
                        res.setHeader('ETag', newETag);

                        if (ifNoneMatch && ifNoneMatch.indexOf(newETag) !== -1) {
                            return res.sendStatus(304);
                        }
                    }

                    res.removeHeader('content-length');
                    res.removeHeader('last-modified');
                    res.writeHead(res.statusCode);

                    var injected = false,
                        state = 0;

                    function injectScriptAtIndex(chunk, i) {
                        if (i > 0) {
                            res.write(chunk.slice(0, i));
                        }
                        res.write('' +
                                  '');
                        if (chunk.length > i) {
                            res.write(chunk.slice(i));
                        }
                        injected = true;
                    }

                    res.on('end', function () {
                        if (!injected) {
                            injectScriptAtIndex(new Buffer([]), 0);
                        }
                        res.end();
                    }).on('data', function (chunk, encoding) {
                        if (injected) {
                            res.write(chunk, encoding);
                        } else {
                            for (var i = 0 ; i < chunk.length ; i += 1) {
                                var ch;
                                if (Buffer.isBuffer(chunk)) {
                                    ch = String.fromCharCode(chunk[i]);
                                } else {
                                    // string
                                    ch = chunk[i];
                                }
                                switch (state) {
                                case 0:
                                    if (ch === '<') {
                                        state = 1;
                                    }
                                    break;
                                case 1: // <
                                    if (ch === '/') {
                                        state = 2;
                                    } else {
                                        state = 0;
                                    }
                                    break;
                                case 2: // </
                                    if (ch === 'h' || ch === 'H') {
                                        state = 3;
                                    } else {
                                        state = 0;
                                    }
                                    break;
                                case 3: // </h
                                    if (ch === 'e' || ch === 'E') {
                                        state = 4;
                                    } else if (ch === 't' || ch === 'T') {
                                        state = 7;
                                    } else {
                                        state = 0;
                                    }
                                    break;
                                case 4: // </he
                                    if (ch === 'a' || ch === 'A') {
                                        state = 5;
                                    } else {
                                        state = 0;
                                    }
                                    break;
                                case 5: // </hea
                                    if (ch === 'd' || ch === 'D') {
                                        state = 6;
                                    } else {
                                        state = 0;
                                    }
                                    break;
                                case 6: // ' || ch === ' ') {
                                        injectScriptAtIndex(chunk, i + 1 - ''.length);
                                        return;
                                    } else {
                                        state = 0;
                                    }
                                    break;
                                case 7: // </ht
                                    if (ch === 'm' || ch === 'M') {
                                        state = 8;
                                    } else {
                                        state = 0;
                                    }
                                    break;
                                case 8: // </htm
                                    if (ch === 'l' || ch === 'L') {
                                        state = 9;
                                    } else {
                                        state = 0;
                                    }
                                    break;
                                case 9: // ' || ch === ' ') {
                                        injectScriptAtIndex(chunk, i + 1 - ''.length);
                                        return;
                                    } else {
                                        state = 0;
                                    }
                                    break;
                                }
                            }
                            if (!injected) {
                                res.write(chunk, encoding);
                            }
                        }
                    });
                }
            });
        }
        next();
    };
};
<commit_msg>Don't kill etags issued by express-compiless or express-compile-sass<commit_after>var fs = require('fs'),
    path = require('path'),
    crypto = require('crypto');

require('express-hijackresponse');

module.exports = function (config) {
    config = config || {};
    var liveStyleClientCode = fs.readFileSync(path.resolve(__dirname, '../../livestyle-client.js'), 'utf-8')
            .replace(/liveStyleOptions\s*=\s*\{\}/, 'liveStyleOptions = ' + JSON.stringify(config)),
        liveStyleClientCodeMd5Hex = crypto.createHash('md5').update(liveStyleClientCode, 'utf-8').digest('hex');
    return function injectLiveStyleScriptIncludeIntoHtml(req, res, next) {
        if (req.url === '/__livestyle/livestyle-client.js') {
            res.set({
                'Content-Type': 'text/javascript',
                'ETag': '"' + liveStyleClientCodeMd5Hex + '"'
            });

            if (req.stale) {
                return res.send(liveStyleClientCode);
            } else {
                return res.sendStatus(304);
            }
        }

        if (req.method === 'GET' && (req.accepts('html') || (req.headers.accept && req.headers.accept.indexOf('*/*') !== -1))) {
            // Prevent If-None-Match revalidation with the downstream middleware with ETags that aren't suffixed with "-livestyle":
            var ifNoneMatch = req.headers['if-none-match'];
            if (ifNoneMatch) {
                var validIfNoneMatchTokens = ifNoneMatch.split(" ").filter(function (etag) {
                    return /-(?:livestyle|processimage|compiless|compile-sass)\"$/.test(etag);
                });
                if (validIfNoneMatchTokens.length > 0) {
                    req.headers['if-none-match'] = validIfNoneMatchTokens.join(" ");
                } else {
                    delete req.headers['if-none-match'];
                }
            }
            delete req.headers['if-modified-since'];
            delete req.headers['content-length'];
            delete req.headers['accept-encoding'];

            res.hijack(function (err, res) {
                if (err) {
                    return res.unhijack(function () {
                        next(err);
                    });
                }
                var contentType = res.getHeader('content-type');
                if (!contentType || !contentType.match(/^text\/html(?:;\s*charset=('|"|)([^'"]+)\1)?$/i)) {
                    res.unhijack(true);
                } else {
                    var oldETag = res.getHeader('ETag');
                    if (oldETag) {
                        var newETag = '"' + oldETag.replace(/^"|"$/g, '') + '-' + liveStyleClientCodeMd5Hex + '-livestyle"';
                        res.setHeader('ETag', newETag);

                        if (ifNoneMatch && ifNoneMatch.indexOf(newETag) !== -1) {
                            return res.sendStatus(304);
                        }
                    }

                    res.removeHeader('content-length');
                    res.removeHeader('last-modified');
                    res.writeHead(res.statusCode);

                    var injected = false,
                        state = 0;

                    function injectScriptAtIndex(chunk, i) {
                        if (i > 0) {
                            res.write(chunk.slice(0, i));
                        }
                        res.write('' +
                                  '');
                        if (chunk.length > i) {
                            res.write(chunk.slice(i));
                        }
                        injected = true;
                    }

                    res.on('end', function () {
                        if (!injected) {
                            injectScriptAtIndex(new Buffer([]), 0);
                        }
                        res.end();
                    }).on('data', function (chunk, encoding) {
                        if (injected) {
                            res.write(chunk, encoding);
                        } else {
                            for (var i = 0 ; i < chunk.length ; i += 1) {
                                var ch;
                                if (Buffer.isBuffer(chunk)) {
                                    ch = String.fromCharCode(chunk[i]);
                                } else {
                                    // string
                                    ch = chunk[i];
                                }
                                switch (state) {
                                case 0:
                                    if (ch === '<') {
                                        state = 1;
                                    }
                                    break;
                                case 1: // <
                                    if (ch === '/') {
                                        state = 2;
                                    } else {
                                        state = 0;
                                    }
                                    break;
                                case 2: // </
                                    if (ch === 'h' || ch === 'H') {
                                        state = 3;
                                    } else {
                                        state = 0;
                                    }
                                    break;
                                case 3: // </h
                                    if (ch === 'e' || ch === 'E') {
                                        state = 4;
                                    } else if (ch === 't' || ch === 'T') {
                                        state = 7;
                                    } else {
                                        state = 0;
                                    }
                                    break;
                                case 4: // </he
                                    if (ch === 'a' || ch === 'A') {
                                        state = 5;
                                    } else {
                                        state = 0;
                                    }
                                    break;
                                case 5: // </hea
                                    if (ch === 'd' || ch === 'D') {
                                        state = 6;
                                    } else {
                                        state = 0;
                                    }
                                    break;
                                case 6: // ' || ch === ' ') {
                                        injectScriptAtIndex(chunk, i + 1 - ''.length);
                                        return;
                                    } else {
                                        state = 0;
                                    }
                                    break;
                                case 7: // </ht
                                    if (ch === 'm' || ch === 'M') {
                                        state = 8;
                                    } else {
                                        state = 0;
                                    }
                                    break;
                                case 8: // </htm
                                    if (ch === 'l' || ch === 'L') {
                                        state = 9;
                                    } else {
                                        state = 0;
                                    }
                                    break;
                                case 9: // ' || ch === ' ') {
                                        injectScriptAtIndex(chunk, i + 1 - ''.length);
                                        return;
                                    } else {
                                        state = 0;
                                    }
                                    break;
                                }
                            }
                            if (!injected) {
                                res.write(chunk, encoding);
                            }
                        }
                    });
                }
            });
        }
        next();
    };
};
<|endoftext|>