diff options
Diffstat (limited to 'node_modules/utila/scripts/coffee')
-rw-r--r-- | node_modules/utila/scripts/coffee/lib/Emitter.coffee | 145 | ||||
-rw-r--r-- | node_modules/utila/scripts/coffee/lib/_common.coffee | 99 | ||||
-rw-r--r-- | node_modules/utila/scripts/coffee/lib/array.coffee | 186 | ||||
-rw-r--r-- | node_modules/utila/scripts/coffee/lib/classic.coffee | 87 | ||||
-rw-r--r-- | node_modules/utila/scripts/coffee/lib/object.coffee | 170 | ||||
-rw-r--r-- | node_modules/utila/scripts/coffee/lib/string.coffee | 16 | ||||
-rw-r--r-- | node_modules/utila/scripts/coffee/lib/utila.coffee | 7 | ||||
-rw-r--r-- | node_modules/utila/scripts/coffee/test/_prepare.coffee | 5 | ||||
-rw-r--r-- | node_modules/utila/scripts/coffee/test/array.coffee | 143 | ||||
-rw-r--r-- | node_modules/utila/scripts/coffee/test/object.coffee | 233 |
10 files changed, 1091 insertions, 0 deletions
diff --git a/node_modules/utila/scripts/coffee/lib/Emitter.coffee b/node_modules/utila/scripts/coffee/lib/Emitter.coffee new file mode 100644 index 000000000..585a924ed --- /dev/null +++ b/node_modules/utila/scripts/coffee/lib/Emitter.coffee @@ -0,0 +1,145 @@ +array = require './array'
+
+module.exports = class Emitter
+
+ constructor: ->
+
+ @_listeners = {}
+
+ @_listenersForAnyEvent = []
+
+ @_disabledEmitters = {}
+
+ on: (eventName, listener) ->
+
+ unless @_listeners[eventName]?
+
+ @_listeners[eventName] = []
+
+ @_listeners[eventName].push listener
+
+ @
+
+ once: (eventName, listener) ->
+
+ ran = no
+
+ cb = =>
+
+ return if ran
+
+ ran = yes
+
+ do listener
+
+ setTimeout =>
+
+ @removeEvent eventName, cb
+
+ , 0
+
+ @on eventName, cb
+
+ @
+
+ onAnyEvent: (listener) ->
+
+ @_listenersForAnyEvent.push listener
+
+ @
+
+ removeEvent: (eventName, listener) ->
+
+ return @ unless @_listeners[eventName]?
+
+ array.pluckOneItem @_listeners[eventName], listener
+
+ @
+
+ removeListeners: (eventName) ->
+
+ return @ unless @_listeners[eventName]?
+
+ @_listeners[eventName].length = 0
+
+ @
+
+ removeAllListeners: ->
+
+ for name, listeners of @_listeners
+
+ listeners.length = 0
+
+ @
+
+ _emit: (eventName, data) ->
+
+ for listener in @_listenersForAnyEvent
+
+ listener.call @, data, eventName
+
+ return unless @_listeners[eventName]?
+
+ for listener in @_listeners[eventName]
+
+ listener.call @, data
+
+ return
+
+ # this makes sure that all the calls to this class's method 'fnName'
+ # are throttled
+ _throttleEmitterMethod: (fnName, time = 1000) ->
+
+ originalFn = @[fnName]
+
+ if typeof originalFn isnt 'function'
+
+ throw Error "this class does not have a method called '#{fnName}'"
+
+ lastCallArgs = null
+ pending = no
+ timer = null
+
+ @[fnName] = =>
+
+ lastCallArgs = arguments
+
+ do pend
+
+ pend = =>
+
+ if pending
+
+ clearTimeout timer
+
+ timer = setTimeout runIt, time
+
+ pending = yes
+
+ runIt = =>
+
+ pending = no
+
+ originalFn.apply @, lastCallArgs
+
+ _disableEmitter: (fnName) ->
+
+ if @_disabledEmitters[fnName]?
+
+ throw Error "#{fnName} is already a disabled emitter"
+
+ @_disabledEmitters[fnName] = @[fnName]
+
+ @[fnName] = ->
+
+ _enableEmitter: (fnName) ->
+
+ fn = @_disabledEmitters[fnName]
+
+ unless fn?
+
+ throw Error "#{fnName} is not a disabled emitter"
+
+ @[fnName] = fn
+
+ delete @_disabledEmitters[fnName]
\ No newline at end of file diff --git a/node_modules/utila/scripts/coffee/lib/_common.coffee b/node_modules/utila/scripts/coffee/lib/_common.coffee new file mode 100644 index 000000000..b120937f4 --- /dev/null +++ b/node_modules/utila/scripts/coffee/lib/_common.coffee @@ -0,0 +1,99 @@ +module.exports = common = + + ### + Checks to see if o is an object, and it isn't an instance + of some class. + ### + isBareObject: (o) -> + + if o? and o.constructor is Object + + return true + + false + + ### + Returns type of an object, including: + undefined, null, string, number, array, + arguments, element, textnode, whitespace, and object + ### + typeOf: (item) -> + + return 'null' if item is null + + return typeof item if typeof item isnt 'object' + + return 'array' if Array.isArray item + + # From MooTools + # - do we even need this? + if item.nodeName + + if item.nodeType is 1 then return 'element' + if item.nodeType is 3 then return (/\S/).test(item.nodeValue) ? 'textnode' : 'whitespace' + + else if typeof item.length is 'number' + + if item.callee then return 'arguments' + + return typeof item + + # Deep clone of any variable. + # From MooTools + clone: (item, includePrototype = false) -> + + switch common.typeOf item + + when 'array' then return common._cloneArray item, includePrototype + + when 'object' then return common._cloneObject item, includePrototype + + else return item + + ### + Deep clone of an object. + From MooTools + ### + _cloneObject: (o, includePrototype = false) -> + + if common.isBareObject o + + clone = {} + + for key of o + + clone[key] = common.clone o[key], includePrototype + + return clone + + else + + return o unless includePrototype + + return o if o instanceof Function + + clone = Object.create o.constructor.prototype + + for key of o + + if o.hasOwnProperty key + + clone[key] = common.clone o[key], includePrototype + + clone + + ### + Deep clone of an array. + From MooTools + ### + _cloneArray: (a, includePrototype = false) -> + + i = a.length + + clone = new Array i + + while i-- + + clone[i] = common.clone a[i], includePrototype + + clone
\ No newline at end of file diff --git a/node_modules/utila/scripts/coffee/lib/array.coffee b/node_modules/utila/scripts/coffee/lib/array.coffee new file mode 100644 index 000000000..429bf6dc6 --- /dev/null +++ b/node_modules/utila/scripts/coffee/lib/array.coffee @@ -0,0 +1,186 @@ +module.exports = array = + + ### + Tries to turn anything into an array. + ### + from: (r) -> + + Array::slice.call r + + ### + Clone of an array. Properties will be shallow copies. + ### + simpleClone: (a) -> + + a.slice 0 + + shallowEqual: (a1, a2) -> + + return no unless Array.isArray(a1) and Array.isArray(a2) and a1.length is a2.length + + for val, i in a1 + + return no unless a2[i] is val + + yes + + pluck: (a, i) -> + + return a if a.length < 1 + + + for value, index in a + + if index > i + + a[index - 1] = a[index] + + a.length = a.length - 1 + + a + + pluckItem: (a, item) -> + + return a if a.length < 1 + + + removed = 0 + + for value, index in a + + if value is item + + removed++ + + continue + + if removed isnt 0 + + a[index - removed] = a[index] + + a.length = a.length - removed if removed > 0 + + a + + pluckOneItem: (a, item) -> + + return a if a.length < 1 + + reached = no + + for value, index in a + + if not reached + + if value is item + + reached = yes + + continue + + else + + a[index - 1] = a[index] + + a.length = a.length - 1 if reached + + a + + pluckByCallback: (a, cb) -> + + return a if a.length < 1 + + removed = 0 + + for value, index in a + + if cb value, index + + removed++ + + continue + + if removed isnt 0 + + a[index - removed] = a[index] + + if removed > 0 + + a.length = a.length - removed + + a + + pluckMultiple: (array, indexesToRemove) -> + + return array if array.length < 1 + + removedSoFar = 0 + + indexesToRemove.sort() + + for i in indexesToRemove + + @pluck array, i - removedSoFar + + removedSoFar++ + + array + + injectByCallback: (a, toInject, shouldInject) -> + + valA = null + + valB = null + + len = a.length + + if len < 1 + + a.push toInject + + return a + + + for val, i in a + + valA = valB + + valB = val + + if shouldInject valA, valB, toInject + + return a.splice i, 0, toInject + + a.push toInject + + a + + injectInIndex: (a, index, toInject) -> + + len = a.length + + i = index + + if len < 1 + + a.push toInject + + return a + + toPut = toInject + + toPutNext = null + + `for(; i <= len; i++){ + + toPutNext = a[i]; + + a[i] = toPut; + + toPut = toPutNext; + + }` + + # a[i] = toPut + + null
\ No newline at end of file diff --git a/node_modules/utila/scripts/coffee/lib/classic.coffee b/node_modules/utila/scripts/coffee/lib/classic.coffee new file mode 100644 index 000000000..5b3f9c82e --- /dev/null +++ b/node_modules/utila/scripts/coffee/lib/classic.coffee @@ -0,0 +1,87 @@ +module.exports = classic = {} + +# Little helper for mixins from CoffeeScript FAQ, +# courtesy of Sethaurus (http://github.com/sethaurus) +classic.implement = (mixins..., classReference) -> + + for mixin in mixins + + classProto = classReference:: + + for member of mixin:: + + unless Object.getOwnPropertyDescriptor classProto, member + + desc = Object.getOwnPropertyDescriptor mixin::, member + + Object.defineProperty classProto, member, desc + + classReference + +classic.mix = (mixins..., classReference) -> + + classProto = classReference:: + + classReference.__mixinCloners = [] + + classReference.__applyClonersFor = (instance, args = null) -> + + for cloner in classReference.__mixinCloners + + cloner.apply instance, args + + return + + classReference.__mixinInitializers = [] + + classReference.__initMixinsFor = (instance, args = null) -> + + for initializer in classReference.__mixinInitializers + + initializer.apply instance, args + + return + + classReference.__mixinQuitters = [] + + classReference.__applyQuittersFor = (instance, args = null) -> + + for quitter in classReference.__mixinQuitters + + quitter.apply instance, args + + return + + for mixin in mixins + + unless mixin.constructor instanceof Function + + throw Error "Mixin should be a function" + + for member of mixin:: + + if member.substr(0, 11) is '__initMixin' + + classReference.__mixinInitializers.push mixin::[member] + + continue + + else if member.substr(0, 11) is '__clonerFor' + + classReference.__mixinCloners.push mixin::[member] + + continue + + else if member.substr(0, 12) is '__quitterFor' + + classReference.__mixinQuitters.push mixin::[member] + + continue + + unless Object.getOwnPropertyDescriptor classProto, member + + desc = Object.getOwnPropertyDescriptor mixin::, member + + Object.defineProperty classProto, member, desc + + classReference
\ No newline at end of file diff --git a/node_modules/utila/scripts/coffee/lib/object.coffee b/node_modules/utila/scripts/coffee/lib/object.coffee new file mode 100644 index 000000000..79977b3ac --- /dev/null +++ b/node_modules/utila/scripts/coffee/lib/object.coffee @@ -0,0 +1,170 @@ +_common = require './_common' + +module.exports = object = + + isBareObject: _common.isBareObject.bind _common + + ### + if object is an instance of a class + ### + isInstance: (what) -> + + not @isBareObject what + + ### + Alias to _common.typeOf + ### + typeOf: _common.typeOf.bind _common + + ### + Alias to _common.clone + ### + clone: _common.clone.bind _common + + ### + Empties an object of its properties. + ### + empty: (o) -> + + for prop of o + + delete o[prop] if o.hasOwnProperty prop + + o + + ### + Empties an object. Doesn't check for hasOwnProperty, so it's a tiny + bit faster. Use it for plain objects. + ### + fastEmpty: (o) -> + + delete o[property] for property of o + + o + + ### + Overrides values fomr `newValues` on `base`, as long as they + already exist in base. + ### + overrideOnto: (base, newValues) -> + + return base if not @isBareObject(newValues) or not @isBareObject(base) + + for key, oldVal of base + + newVal = newValues[key] + + continue if newVal is undefined + + if typeof newVal isnt 'object' or @isInstance newVal + + base[key] = @clone newVal + + # newVal is a plain object + else + + if typeof oldVal isnt 'object' or @isInstance oldVal + + base[key] = @clone newVal + + else + + @overrideOnto oldVal, newVal + base + + ### + Takes a clone of 'base' and runs #overrideOnto on it + ### + override: (base, newValues) -> + + @overrideOnto @clone(base), newValues + + append: (base, toAppend) -> + + @appendOnto @clone(base), toAppend + + # Deep appends values from `toAppend` to `base` + appendOnto: (base, toAppend) -> + + return base if not @isBareObject(toAppend) or not @isBareObject(base) + + for own key, newVal of toAppend + + continue unless newVal isnt undefined + + if typeof newVal isnt 'object' or @isInstance newVal + + base[key] = newVal + + else + + # newVal is a bare object + + oldVal = base[key] + + if typeof oldVal isnt 'object' or @isInstance oldVal + + base[key] = @clone newVal + + else + + @appendOnto oldVal, newVal + + base + + # Groups + groupProps: (obj, groups) -> + + grouped = {} + + for name, defs of groups + + grouped[name] = {} + + grouped['rest'] = {} + + `top: //` + for key, val of obj + + shouldAdd = no + + for name, defs of groups + + unless Array.isArray defs + + defs = [defs] + + for def in defs + + if typeof def is 'string' + + if key is def + + shouldAdd = yes + + else if def instanceof RegExp + + if def.test key + + shouldAdd = yes + + else if def instanceof Function + + if def key + + shouldAdd = yes + + else + + throw Error 'Group definitions must either + be strings, regexes, or functions.' + + if shouldAdd + + grouped[name][key] = val + + `continue top` + + grouped['rest'][key] = val + + grouped
\ No newline at end of file diff --git a/node_modules/utila/scripts/coffee/lib/string.coffee b/node_modules/utila/scripts/coffee/lib/string.coffee new file mode 100644 index 000000000..9515c648f --- /dev/null +++ b/node_modules/utila/scripts/coffee/lib/string.coffee @@ -0,0 +1,16 @@ +module.exports =
+
+ # pads a number with leading zeroes
+ #
+ # http://stackoverflow.com/a/10073788/607997
+ pad: (n, width, z = '0') ->
+
+ n = n + ''
+
+ if n.length >= width
+
+ n
+
+ else
+
+ new Array(width - n.length + 1).join(z) + n
\ No newline at end of file diff --git a/node_modules/utila/scripts/coffee/lib/utila.coffee b/node_modules/utila/scripts/coffee/lib/utila.coffee new file mode 100644 index 000000000..5d68529e4 --- /dev/null +++ b/node_modules/utila/scripts/coffee/lib/utila.coffee @@ -0,0 +1,7 @@ +module.exports = utila = + + array: require './array' + classic: require './classic' + object: require './object' + string: require './string' + Emitter: require './Emitter'
\ No newline at end of file diff --git a/node_modules/utila/scripts/coffee/test/_prepare.coffee b/node_modules/utila/scripts/coffee/test/_prepare.coffee new file mode 100644 index 000000000..b602a464e --- /dev/null +++ b/node_modules/utila/scripts/coffee/test/_prepare.coffee @@ -0,0 +1,5 @@ +path = require 'path' + +pathToLib = path.resolve __dirname, '../lib' + +require('little-popo')(pathToLib)
\ No newline at end of file diff --git a/node_modules/utila/scripts/coffee/test/array.coffee b/node_modules/utila/scripts/coffee/test/array.coffee new file mode 100644 index 000000000..a244861be --- /dev/null +++ b/node_modules/utila/scripts/coffee/test/array.coffee @@ -0,0 +1,143 @@ +require './_prepare' + +array = mod 'array' + +test 'from', -> + + array.from([1]).should.be.an.instanceOf Array + array.from([1])[0].should.equal 1 + +# test 'clone', -> + +# a = [0, 1, 2] + +# b = array.clone a + +# b[0].should.equal 0 +# b[1].should.equal 1 + +# b[0] = 3 + +# a[0].should.equal 0 + +test 'pluck', -> + + a = [0, 1, 2, 3] + + after = array.pluck a, 1 + + after.length.should.equal 3 + + after[0].should.equal 0 + after[1].should.equal 2 + after[2].should.equal 3 + after.should.equal a + +test 'pluckMultiple', -> + + a = [0, 1, 2, 3, 4, 5, 6] + + array.pluckMultiple a, [0, 4, 2, 6] + + a.length.should.equal 3 + a[0].should.equal 1 + a[1].should.equal 3 + a[2].should.equal 5 + +test 'pluckItem', -> + + a = [0, 1, 2, 3, 2, 4, 2] + + array.pluckItem a, 2 + + a[0].should.equal 0 + a[1].should.equal 1 + a[2].should.equal 3 + a[3].should.equal 4 + + array.pluckItem([1], 2).length.should.equal 1 + + +test 'pluckOneItem', -> + + a = [0, 1, 2, 3, 2, 4, 2] + + array.pluckOneItem a, 2 + + a[0].should.equal 0 + a[1].should.equal 1 + a[2].should.equal 3 + a[3].should.equal 2 + a[4].should.equal 4 + a[5].should.equal 2 + + a = [1, 2] + + array.pluckOneItem a, 1 + + a.length.should.equal 1 + a[0].should.equal 2 + + array.pluckOneItem([], 1).length.should.equal 0 + + array.pluckOneItem([1], 2).length.should.equal 1 + +test 'plcukByCallback', -> + + a = [0, 1, 2, 3] + + array.pluckByCallback a, (val, i) -> + + return yes if val is 2 + + return no + + a[0].should.equal 0 + a[1].should.equal 1 + a[2].should.equal 3 + +test 'injectByCallback', -> + + shouldInject = (valA, valB, toInject) -> + + unless valA? + + return yes if toInject <= valB + + return no + + unless valB? + + return yes if valA <= toInject + + return no + + return yes if valA <= toInject <= valB + + return no + + a = [0.5, 1, 2.5, 2.5, 2.75, 2.75, 3] + + array.injectByCallback a, 0, shouldInject + + a[0].should.equal 0 + a[1].should.equal 0.5 + a[7].should.equal 3 + + a = [0.5, 1, 2.5, 2.5, 2.75, 2.75, 3] + + array.injectByCallback a, 2.7, shouldInject + + a[0].should.equal 0.5 + a[4].should.equal 2.7 + a[5].should.equal 2.75 + a[7].should.equal 3 + + a = [0.5, 1, 2.5, 2.5, 2.75, 2.75, 3] + + array.injectByCallback a, 3.2, shouldInject + + a[0].should.equal 0.5 + a[4].should.equal 2.75 + a[6].should.equal 3 + a[7].should.equal 3.2
\ No newline at end of file diff --git a/node_modules/utila/scripts/coffee/test/object.coffee b/node_modules/utila/scripts/coffee/test/object.coffee new file mode 100644 index 000000000..e36140c8d --- /dev/null +++ b/node_modules/utila/scripts/coffee/test/object.coffee @@ -0,0 +1,233 @@ +require './_prepare' + +object = mod 'object' + +test 'isBareObject', -> + + object.isBareObject('a').should.equal false + + object.isBareObject({'a': 'a'}).should.equal true + +test 'typeOf', -> + + object.typeOf('s').should.equal 'string' + object.typeOf(0).should.equal 'number' + object.typeOf(false).should.equal 'boolean' + object.typeOf({}).should.equal 'object' + object.typeOf(arguments).should.equal 'arguments' + object.typeOf([]).should.equal 'array' + +test 'empty', -> + + o = + + a: 1 + b: 2 + + + object.empty o + + o.should.not.have.property 'a' + o.should.not.have.property 'b' + +test 'fastEmpty', -> + + o = + a: 1 + b: 2 + + + object.fastEmpty o + + o.should.not.have.property 'a' + o.should.not.have.property 'b' + +test 'clone', -> + + object.clone([1])[0].should.equal 1 + object.clone({a:1}).a.should.equal 1 + + o = {a: 1} + + object.clone(o).should.not.equal o + +test 'clone [include prototype]', -> + + class C + + constructor: (@a) -> + + sayA: -> @a + 'a' + + a = new C 'a' + + a.sayA().should.equal 'aa' + + b = object.clone a, yes + + b.should.not.equal a + + b.constructor.should.equal C + + b.a.should.equal 'a' + + b.a = 'a2' + + b.sayA().should.equal 'a2a' + +test 'clone [without prototype]', -> + + class C + + constructor: (@a) -> + + sayA: -> @a + 'a' + + a = new C 'a' + + a.sayA().should.equal 'aa' + + b = object.clone a, no + + b.should.equal a + +test 'overrideOnto [basic]', -> + + onto = + a: 'a' + b: + c: 'c' + d: + e: 'e' + + what = + a: 'a2' + b: + c: 'c2' + d: + f: 'f2' + + object.overrideOnto onto, what + + onto.a.should.equal 'a2' + onto.b.should.have.property 'c' + onto.b.c.should.equal 'c2' + onto.b.d.should.not.have.property 'f' + onto.b.d.e.should.equal 'e' + +test 'override', -> + + onto = + + a: 'a' + + b: + + c: 'c' + + d: + + e: 'e' + + what = + + a: 'a2' + + b: + + c: 'c2' + + d: + + f: 'f2' + + + onto2 = object.override onto, what + + onto2.a.should.equal 'a2' + onto2.b.should.have.property 'c' + onto2.b.c.should.equal 'c2' + onto2.b.d.should.not.have.property 'f' + onto2.b.d.e.should.equal 'e' + + onto.should.not.equal onto2 + +do -> + + what = + + a: 'a2' + + c: -> + + z: 'z' + + y: + + a: 'a' + + onto = + + a: 'a' + + b: 'b' + + test 'appendOnto [basic]', -> + + object.appendOnto onto, what + + onto.a.should.equal 'a2' + onto.b.should.equal 'b' + onto.z.should.equal 'z' + + test "appendOnto [shallow copies instances]", -> + + onto.c.should.be.instanceof Function + onto.c.should.equal what.c + + + test "appendOnto [clones objects]", -> + + onto.should.have.property 'y' + onto.y.a.should.equal 'a' + onto.y.should.not.equal what.y + +test 'groupProps', -> + + obj = + + a1: '1' + a2: '2' + + b1: '1' + b2: '2' + + c1: '1' + c2: '2' + + rest1: '1' + rest2: '2' + + groups = object.groupProps obj, + + a: ['a1', 'a2'] + + b: [/^b[0-9]+$/] + + c: (key) -> key[0] is 'c' + + groups.a.should.have.property 'a1' + groups.a.a1.should.equal '1' + + groups.a.should.have.property 'a2' + + groups.b.should.have.property 'b1' + groups.b.should.have.property 'b2' + + groups.c.should.have.property 'c1' + groups.c.should.have.property 'c2' + + groups.rest.should.have.property 'rest1' + groups.rest.should.have.property 'rest1' + + groups.rest.should.not.have.property 'c1'
\ No newline at end of file |