aboutsummaryrefslogtreecommitdiff
path: root/node_modules/utila/scripts/coffee
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2017-05-03 15:35:00 +0200
committerFlorian Dold <florian.dold@gmail.com>2017-05-03 15:35:00 +0200
commitde98e0b232509d5f40c135d540a70e415272ff85 (patch)
treea79222a5b58484ab3b80d18efcaaa7ccc4769b33 /node_modules/utila/scripts/coffee
parente0c9d480a73fa629c1e4a47d3e721f1d2d345406 (diff)
node_modules
Diffstat (limited to 'node_modules/utila/scripts/coffee')
-rw-r--r--node_modules/utila/scripts/coffee/lib/Emitter.coffee145
-rw-r--r--node_modules/utila/scripts/coffee/lib/_common.coffee99
-rw-r--r--node_modules/utila/scripts/coffee/lib/array.coffee186
-rw-r--r--node_modules/utila/scripts/coffee/lib/classic.coffee87
-rw-r--r--node_modules/utila/scripts/coffee/lib/object.coffee170
-rw-r--r--node_modules/utila/scripts/coffee/lib/string.coffee16
-rw-r--r--node_modules/utila/scripts/coffee/lib/utila.coffee7
-rw-r--r--node_modules/utila/scripts/coffee/test/_prepare.coffee5
-rw-r--r--node_modules/utila/scripts/coffee/test/array.coffee143
-rw-r--r--node_modules/utila/scripts/coffee/test/object.coffee233
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