Added an extra parameter to rotateX/Y/Z to allow for local transformations.

Matrices are arrays of 16 numbers forming a 4x4 matrix.

    temp1 = []
    temp2 = []
    rotationTemp = []
    tempVector = []
    tempVectorFrom = []
    tempVectorTo = []
    fromTemp = []
    toTemp = []
    tempVectorX = []
    tempVectorY = []
    tempVectorZ = []

    makeRotate = (axis1, axis2, axis3, axis4) ->
        temp3 = []
        rotationTemp.push temp3
        (radians, output, local) ->
            sin = Math.sin radians
            cos = Math.cos radians
            temp3[axis1] = cos
            temp3[axis2] = -sin
            temp3[axis3] = sin
            temp3[axis4] = cos
            if local
                module.exports.multiply temp3, output, output
            else
                module.exports.multiply output, temp3, output
            return

    vector = require "./vector.litcoffee"

    module.exports =

Given a matrix, calling the "identity" property writes the identity matrix to
it.

        identity: (output) ->
            for row in [0...4]
                for column in [0...4]
                    output[row * 4 + column] = if row is column then 1 else 0
            return

Given two matrices, calling the "copy" property copies every component from the
first to the second.

        copy: (input, output) ->
            output[index] = value for value, index in input
            return

Given three matrices, calling the "multiply" property multiplies the first two
together and writes the result to the third.

        multiply: (a, b, output) ->
            module.exports.copy a, temp1
            module.exports.copy b, temp2

            for row in [0...4]
                for column in [0...4]
                    temp = 0
                    for component in [0...4]
                        temp += temp1[component * 4 + column] * temp2[row * 4 + component]
                    output[row * 4 + column] = temp
            return

Given a number of radians and a matrix, calling the "rotateX" property modifies
the matrix to have been rotated by that number of radians about the X axis.
If the third parameter is truthy, the rotation is applied in local rather than
global space.

        rotateX: makeRotate 5, 6, 9, 10

Given a number of radians and a matrix, calling the "rotateY" property modifies
the matrix to have been rotated by that number of radians about the Y axis.
If the third parameter is truthy, the rotation is applied in local rather than
global space.

        rotateY: makeRotate 0, 2, 8, 10

Given a number of radians and a matrix, calling the "rotateZ" property modifies
the matrix to have been rotated by that number of radians about the Z axis.
If the third parameter is truthy, the rotation is applied in local rather than
global space.

        rotateZ: makeRotate 0, 1, 4, 5

Given a vector specifying the scaling factor on each axis and a matrix, calling
the "scale" property scales the matrix by those scaling factors.

        scale: (vector, output) ->
            output[index] *= vector[0] for index in [0...4]
            output[index] *= vector[1] for index in [4...8]
            output[index] *= vector[2] for index in [8...12]
            return

Given a vector specifying a translation and a matrix to translate, calling the
"translate" property applies that translation to that matrix.

        translate: (vector, output) ->
            output[3] += vector[0]
            output[7] += vector[1]
            output[11] += vector[2]
            return

Given a matrix, X, Y, Z and W values (defaulting to 0, 0, 0 and 1 respectively
if not given), calling the "apply" property returns an array of four numbers
representing the transformed vector.

        apply: (matrix, x, y, z, w) ->
            if x is undefined then x = 0
            if y is undefined then y = 0
            if z is undefined then z = 0
            if w is undefined then w = 1

            [
                x * matrix[0] + y * matrix[1] + z * matrix[2] + w * matrix[3]
                x * matrix[4] + y * matrix[5] + z * matrix[6] + w * matrix[7]
                x * matrix[8] + y * matrix[9] + z * matrix[10] + w * matrix[11]
                x * matrix[12] + y * matrix[13] + z * matrix[14] + w * matrix[15]
            ]

Given a matrix, input vector and output vector, calling the "applyToVector"
property writes the input vector transformed by the matrix to the output vector.

        applyToVector: (matrix, input, output) ->
            vector.copy input, tempVector
            output[0] = tempVector[0] * matrix[0] + tempVector[1] * matrix[1] + tempVector[2] * matrix[2] + matrix[3]
            output[1] = tempVector[0] * matrix[4] + tempVector[1] * matrix[5] + tempVector[2] * matrix[6] + matrix[7]
            output[2] = tempVector[0] * matrix[8] + tempVector[1] * matrix[9] + tempVector[2] * matrix[10] + matrix[11]
            return

Given a matrix and output vector, calling the "getTranslation" property writes
the translation applied by the matrix to the output vector.

        getTranslation: (matrix, output) ->
            output[0] = matrix[3]
            output[1] = matrix[7]
            output[2] = matrix[11]

Given a matrix and output vector, calling the "getX" property writes the vector
of the matrix's X axis (a scaled normal) to the output vector.

        getX: (matrix, output) ->
            output[0] = matrix[0]
            output[1] = matrix[4]
            output[2] = matrix[8]

Given a matrix and output vector, calling the "getY" property writes the vector
of the matrix's Y axis (a scaled normal) to the output vector.

        getY: (matrix, output) ->
            output[0] = matrix[1]
            output[1] = matrix[5]
            output[2] = matrix[9]

Given a matrix and output vector, calling the "getZ" property writes the vector
of the matrix's Z axis (a scaled normal) to the output vector.

        getZ: (matrix, output) ->
            output[0] = matrix[2]
            output[1] = matrix[6]
            output[2] = matrix[10]

# setTranslation

- A vector specifying the translation to set.
- A matrix to set the translation of.

Overwrites the translation of the matrix with the content of the given vector.

        setTranslation: (output, matrix) ->
            matrix[3] = output[0]
            matrix[7] = output[1]
            matrix[11] = output[2]

# setX

- A vector specifying the X axis vector to set.
- A matrix to set the X axis vector of.

Overwrites the X axis of the matrix with the content of the given vector.

        setX: (output, matrix) ->
            matrix[0] = output[0]
            matrix[4] = output[1]
            matrix[8] = output[2]

# setY

- A vector specifying the Y axis vector to set.
- A matrix to set the Y axis vector of.

Overwrites the Y axis of the matrix with the content of the given vector.

        setY: (output, matrix) ->
            matrix[1] = output[0]
            matrix[5] = output[1]
            matrix[9] = output[2]

# setZ

- A vector specifying the Z axis vector to set.
- A matrix to set the Z axis vector of.

Overwrites the Z axis of the matrix with the content of the given vector.

        setZ: (output, matrix) ->
            matrix[2] = output[0]
            matrix[6] = output[1]
            matrix[10] = output[2]

# interpolate

- An input matrix to interpolate from.
- An input matrix to interpolate to.
- A number specifying how far along to interpolate; "0" is "from" and "1" is
  "to".
- An output matrix.

Attempts to perform a somewhat crude interpolation between the two matrices
which is not very linear.  Good enough for smoothing over small changes.
Prioritizes the Z and Y axes over the X axis when ensuring orthogonal.

        interpolate: (from, to, alpha, output) ->
            module.exports.copy from, fromTemp
            module.exports.copy to, toTemp
            module.exports.identity output
            module.exports.getTranslation fromTemp, tempVectorFrom
            module.exports.getTranslation toTemp, tempVectorTo
            vector.interpolate tempVectorFrom, tempVectorTo, alpha, tempVector
            module.exports.setTranslation tempVector, output

            module.exports.getX fromTemp, tempVectorFrom
            module.exports.getX toTemp, tempVectorTo
            vector.interpolate tempVectorFrom, tempVectorTo, alpha, tempVector
            vector.normalize tempVector, tempVectorX, true

            module.exports.getY fromTemp, tempVectorFrom
            module.exports.getY toTemp, tempVectorTo
            vector.interpolate tempVectorFrom, tempVectorTo, alpha, tempVectorY

            vector.cross tempVectorX, tempVectorY, tempVectorZ
            vector.normalize tempVectorZ, tempVectorZ
            vector.cross tempVectorZ, tempVectorX, tempVectorY
            vector.normalize tempVectorY, tempVectorY

            module.exports.setX tempVectorX, output
            module.exports.setY tempVectorY, output
            module.exports.setZ tempVectorZ, output
            return

# invert

- An input matrix to invert.
- An output matrix to write to.

Attempts to calculate the inverse of a matrix by negating its translation and
transposing its X, Y and Z axes.  Will not work if any scaling has been applied.

        invert: (input, output) ->
            module.exports.copy input, fromTemp
            module.exports.getX fromTemp, tempVectorX
            module.exports.getY fromTemp, tempVectorY
            module.exports.getZ fromTemp, tempVectorZ
            module.exports.getTranslation fromTemp, tempVector
            output[0] = input[0]
            output[1] = input[4]
            output[2] = input[8]
            output[3] = -vector.dot tempVector, tempVectorX

            output[4] = input[1]
            output[5] = input[5]
            output[6] = input[9]
            output[7] = -vector.dot tempVector, tempVectorY

            output[8] = input[2]
            output[9] = input[6]
            output[10] = input[10]
            output[11] = -vector.dot tempVector, tempVectorZ

            output[12] = 0
            output[13] = 0
            output[14] = 0
            output[15] = 1

            return

    module.exports.identity temp1
    module.exports.identity temp2
    for mat in rotationTemp
        module.exports.identity mat

Matrices are arrays of 16 numbers forming a 4x4 matrix.

    temp1 = []
    temp2 = []
    rotationTemp = []
    tempVector = []
    tempVectorFrom = []
    tempVectorTo = []
    fromTemp = []
    toTemp = []
    tempVectorX = []
    tempVectorY = []
    tempVectorZ = []

    makeRotate = (axis1, axis2, axis3, axis4) ->
        temp3 = []
        rotationTemp.push temp3
        (radians, output) ->
            sin = Math.sin radians
            cos = Math.cos radians
            temp3[axis1] = cos
            temp3[axis2] = -sin
            temp3[axis3] = sin
            temp3[axis4] = cos
            module.exports.multiply output, temp3, output
            return

    vector = require "./vector.litcoffee"

    module.exports =

Given a matrix, calling the "identity" property writes the identity matrix to
it.

        identity: (output) ->
            for row in [0...4]
                for column in [0...4]
                    output[row * 4 + column] = if row is column then 1 else 0
            return

Given two matrices, calling the "copy" property copies every component from the
first to the second.

        copy: (input, output) ->
            output[index] = value for value, index in input
            return

Given three matrices, calling the "multiply" property multiplies the first two
together and writes the result to the third.

        multiply: (a, b, output) ->
            module.exports.copy a, temp1
            module.exports.copy b, temp2

            for row in [0...4]
                for column in [0...4]
                    temp = 0
                    for component in [0...4]
                        temp += temp1[component * 4 + column] * temp2[row * 4 + component]
                    output[row * 4 + column] = temp
            return

Given a number of radians and a matrix, calling the "rotateX" property modifies
the matrix to have been rotated by that number of radians about the X axis.

        rotateX: makeRotate 5, 6, 9, 10

Given a number of radians and a matrix, calling the "rotateY" property modifies
the matrix to have been rotated by that number of radians about the Y axis.

        rotateY: makeRotate 0, 2, 8, 10

Given a number of radians and a matrix, calling the "rotateZ" property modifies
the matrix to have been rotated by that number of radians about the Z axis.

        rotateZ: makeRotate 0, 1, 4, 5

Given a vector specifying the scaling factor on each axis and a matrix, calling
the "scale" property scales the matrix by those scaling factors.

        scale: (vector, output) ->
            output[index] *= vector[0] for index in [0...4]
            output[index] *= vector[1] for index in [4...8]
            output[index] *= vector[2] for index in [8...12]
            return

Given a vector specifying a translation and a matrix to translate, calling the
"translate" property applies that translation to that matrix.

        translate: (vector, output) ->
            output[3] += vector[0]
            output[7] += vector[1]
            output[11] += vector[2]
            return

Given a matrix, X, Y, Z and W values (defaulting to 0, 0, 0 and 1 respectively
if not given), calling the "apply" property returns an array of four numbers
representing the transformed vector.

        apply: (matrix, x, y, z, w) ->
            if x is undefined then x = 0
            if y is undefined then y = 0
            if z is undefined then z = 0
            if w is undefined then w = 1

            [
                x * matrix[0] + y * matrix[1] + z * matrix[2] + w * matrix[3]
                x * matrix[4] + y * matrix[5] + z * matrix[6] + w * matrix[7]
                x * matrix[8] + y * matrix[9] + z * matrix[10] + w * matrix[11]
                x * matrix[12] + y * matrix[13] + z * matrix[14] + w * matrix[15]
            ]

Given a matrix, input vector and output vector, calling the "applyToVector"
property writes the input vector transformed by the matrix to the output vector.

        applyToVector: (matrix, input, output) ->
            vector.copy input, tempVector
            output[0] = tempVector[0] * matrix[0] + tempVector[1] * matrix[1] + tempVector[2] * matrix[2] + matrix[3]
            output[1] = tempVector[0] * matrix[4] + tempVector[1] * matrix[5] + tempVector[2] * matrix[6] + matrix[7]
            output[2] = tempVector[0] * matrix[8] + tempVector[1] * matrix[9] + tempVector[2] * matrix[10] + matrix[11]
            return

Given a matrix and output vector, calling the "getTranslation" property writes
the translation applied by the matrix to the output vector.

        getTranslation: (matrix, output) ->
            output[0] = matrix[3]
            output[1] = matrix[7]
            output[2] = matrix[11]

Given a matrix and output vector, calling the "getX" property writes the vector
of the matrix's X axis (a scaled normal) to the output vector.

        getX: (matrix, output) ->
            output[0] = matrix[0]
            output[1] = matrix[4]
            output[2] = matrix[8]

Given a matrix and output vector, calling the "getY" property writes the vector
of the matrix's Y axis (a scaled normal) to the output vector.

        getY: (matrix, output) ->
            output[0] = matrix[1]
            output[1] = matrix[5]
            output[2] = matrix[9]

Given a matrix and output vector, calling the "getZ" property writes the vector
of the matrix's Z axis (a scaled normal) to the output vector.

        getZ: (matrix, output) ->
            output[0] = matrix[2]
            output[1] = matrix[6]
            output[2] = matrix[10]

# setTranslation

- A vector specifying the translation to set.
- A matrix to set the translation of.

Overwrites the translation of the matrix with the content of the given vector.

        setTranslation: (output, matrix) ->
            matrix[3] = output[0]
            matrix[7] = output[1]
            matrix[11] = output[2]

# setX

- A vector specifying the X axis vector to set.
- A matrix to set the X axis vector of.

Overwrites the X axis of the matrix with the content of the given vector.

        setX: (output, matrix) ->
            matrix[0] = output[0]
            matrix[4] = output[1]
            matrix[8] = output[2]

# setY

- A vector specifying the Y axis vector to set.
- A matrix to set the Y axis vector of.

Overwrites the Y axis of the matrix with the content of the given vector.

        setY: (output, matrix) ->
            matrix[1] = output[0]
            matrix[5] = output[1]
            matrix[9] = output[2]

# setZ

- A vector specifying the Z axis vector to set.
- A matrix to set the Z axis vector of.

Overwrites the Z axis of the matrix with the content of the given vector.

        setZ: (output, matrix) ->
            matrix[2] = output[0]
            matrix[6] = output[1]
            matrix[10] = output[2]

# interpolate

- An input matrix to interpolate from.
- An input matrix to interpolate to.
- A number specifying how far along to interpolate; "0" is "from" and "1" is
  "to".
- An output matrix.

Attempts to perform a somewhat crude interpolation between the two matrices
which is not very linear.  Good enough for smoothing over small changes.
Prioritizes the Z and Y axes over the X axis when ensuring orthogonal.

        interpolate: (from, to, alpha, output) ->
            module.exports.copy from, fromTemp
            module.exports.copy to, toTemp
            module.exports.identity output
            module.exports.getTranslation fromTemp, tempVectorFrom
            module.exports.getTranslation toTemp, tempVectorTo
            vector.interpolate tempVectorFrom, tempVectorTo, alpha, tempVector
            module.exports.setTranslation tempVector, output

            module.exports.getX fromTemp, tempVectorFrom
            module.exports.getX toTemp, tempVectorTo
            vector.interpolate tempVectorFrom, tempVectorTo, alpha, tempVector
            vector.normalize tempVector, tempVectorX, true

            module.exports.getY fromTemp, tempVectorFrom
            module.exports.getY toTemp, tempVectorTo
            vector.interpolate tempVectorFrom, tempVectorTo, alpha, tempVectorY

            vector.cross tempVectorX, tempVectorY, tempVectorZ
            vector.normalize tempVectorZ, tempVectorZ
            vector.cross tempVectorZ, tempVectorX, tempVectorY
            vector.normalize tempVectorY, tempVectorY

            module.exports.setX tempVectorX, output
            module.exports.setY tempVectorY, output
            module.exports.setZ tempVectorZ, output
            return

# invert

- An input matrix to invert.
- An output matrix to write to.

Attempts to calculate the inverse of a matrix by negating its translation and
transposing its X, Y and Z axes.  Will not work if any scaling has been applied.

        invert: (input, output) ->
            module.exports.copy input, fromTemp
            module.exports.getX fromTemp, tempVectorX
            module.exports.getY fromTemp, tempVectorY
            module.exports.getZ fromTemp, tempVectorZ
            module.exports.getTranslation fromTemp, tempVector
            output[0] = input[0]
            output[1] = input[4]
            output[2] = input[8]
            output[3] = -vector.dot tempVector, tempVectorX

            output[4] = input[1]
            output[5] = input[5]
            output[6] = input[9]
            output[7] = -vector.dot tempVector, tempVectorY

            output[8] = input[2]
            output[9] = input[6]
            output[10] = input[10]
            output[11] = -vector.dot tempVector, tempVectorZ

            output[12] = 0
            output[13] = 0
            output[14] = 0
            output[15] = 1

            return

    module.exports.identity temp1
    module.exports.identity temp2
    for mat in rotationTemp
        module.exports.identity mat


- updated policy model

- updated policy model

Policy
======

    _ = require "underscore"

    class Policy
        constructor: () ->
            @rules = []
            @libsToWrap = []

            @policy =

Indicate if a given library (name) should be wrapped in a separate membrane. If
a policy doesn't talk about a specific depending library, then it there is no
need for it to be wrapped. Therefor, the default return value is `false`:

                wrapWithMembrane: (libName) -> false

        disable: (lib) -> this
        enableHSTS: -> this

        on: (name) ->
            child = new OnRule name, this
            # check if (lib, call) = name must be added to libsToWrap
            # iff lib[0].toLowerCase() == lib[0]
            @rules.push child
            child

        before: (name) ->
            child = new BeforeRule name, this
            @rules.push child
            child

        after: (name) ->
            child = new AfterRule name, this
            @rules.push child
            child

The `build` method generates the whole structure of our semantic model of the membrane object.

        build: () =>
            @libsToWrap = []

            strEqual = (fullName) ->
                (rule) -> fullName.indexOf(rule.apiCall) > -1

            areType = (t) ->
                (rule) -> rule instanceof t

            conditionsAreTrue = (dTgt, ret) ->
                (rule) ->
                    _.chain(rule.conditions)
                        .map (cond) -> cond(dTgt, ret) == true
                        .reduce ((memo, c) -> memo and c), true
                        .value()

            doGetActions = (dTgt, args...) ->
                (rule) ->
                    _.chain(rule.actions)
                        .map (action) -> action.apply(this, [dTgt].concat(args))
                    return rule

            calcRetValue = (origRet, rule) -> rule.ret(origRet)

            isEmpty = (l) -> l.size().value() == 0
            isNotFunction = (v) -> typeof v != "function"

            @policy.onGet = (wTgt, name, wRec, dTgt, ret) =>
                fullName = "#{dTgt.constructor.name.toString()}.#{name}"
                relevantRules = _.chain(@rules)
                    .filter(strEqual(fullName))

                onRules = relevantRules.filter(areType(OnRule))
                beforeRules = relevantRules.filter(areType(BeforeRule))
                afterRules = relevantRules.filter(areType(AfterRule))

                onGetValue = onRules.filter(conditionsAreTrue(dTgt, ret))
                    .map(doGetActions(dTgt, ret))
                    .reduce(calcRetValue, ret)
                    .value()

            @policy.functionCall = (dTgt, dryThis, dryArgs, calcResult, fullName) =>
                relevantRules = _.chain(@rules).filter(strEqual(fullName))

                beforeRules = relevantRules.filter(areType(BeforeRule))
                afterRules = relevantRules.filter(areType(AfterRule))

                calcResult = beforeRules.filter(conditionsAreTrue(dTgt))
                       .map(doGetActions(dTgt, dryArgs, calcResult))
                       .reduce(calcRetValue, calcResult)
                       .value()

                # return as function because the generic membrane will invoke it afterwards
                ->
                    ret = calcResult()
                    afterRules.filter(conditionsAreTrue(dTgt, ret))
                        .map(doGetActions(dTgt, dryArgs, ret))
                        .reduce(calcRetValue, ret)
                        .value()

            @policy

    class Rule
        constructor: (@apiCall, @parent) ->

List of actions with side effects [0..n]:

            @actions = []

The default return function [1..1]:

            @ret = (v) -> v

A list of conditions that evaluate to `true` or `false` [1..n]:

            @conditions = [ -> true]

        do: (f) =>
            @actions.push f
            this

        return: (f) =>
            @ret = (v) -> f.call(this, v)
            this

        if: (cond) =>
            @conditions.push (dtgt, ret) -> cond(dtgt, ret)
            this

        on: (name) => @parent.on name
        before: (name) => @parent.before name
        after: (name) => @parent.after name
        build: () -> @parent.build()

    class OnRule extends Rule
    class AfterRule extends Rule
    class BeforeRule extends Rule

    module.exports = Policy

Policy
======

    _ = require "underscore"

    class Policy
        constructor: () ->
            @rules = []
            @libsToWrap = []

            @policy =

Indicate if a given library (name) should be wrapped in a separate membrane. If
a policy doesn't talk about a specific depending library, then it there is no
need for it to be wrapped. Therefor, the default return value is `false`:

                mustWrap: (libName) ->
                    #return true if libName == "fs"
                    false
                skip: (libName) -> false

        disable: (lib) -> this
        enableHSTS: -> this

        on: (name) ->
            child = new OnRule name, this
            # check if (lib, call) = name must be added to libsToWrap
            # iff lib[0].toLowerCase() == lib[0]
            @rules.push child
            child

        before: (name) ->
            child = new BeforeRule name, this
            @rules.push child
            child

        after: (name) ->
            child = new AfterRule name, this
            @rules.push child
            child

The `build` method generates the whole structure of our semantic model of the membrane object.

        build: () =>
            @libsToWrap = []

            strEqual = (fullName) ->
                (rule) -> fullName.indexOf(rule.apiCall) > -1

            areType = (t) ->
                (rule) -> rule instanceof t

            conditionsAreTrue = (dTgt, ret) ->
                (rule) ->
                    _.chain(rule.conditions)
                        .map (cond) -> cond(dTgt, ret) == true
                        .reduce ((memo, c) -> memo and c), true
                        .value()

            doGetActions = (dTgt, args...) ->
                (rule) ->
                    _.chain(rule.actions)
                        .map (action) -> action.apply(this, [dTgt].concat(args))
                    return rule

            calcRetValue = (origRet, rule) -> rule.ret(origRet)

            isEmpty = (l) -> l.size().value() == 0
            isNotFunction = (v) -> typeof v != "function"

            @policy.onGet = (wTgt, name, wRec, dTgt, ret) =>
                fullName = "#{dTgt.constructor.name.toString()}.#{name}"
                relevantRules = _.chain(@rules)
                    .filter(strEqual(fullName))

                onRules = relevantRules.filter(areType(OnRule))
                beforeRules = relevantRules.filter(areType(BeforeRule))
                afterRules = relevantRules.filter(areType(AfterRule))

                onGetValue = onRules.filter(conditionsAreTrue(dTgt, ret))
                    .map(doGetActions(dTgt, ret))
                    .reduce(calcRetValue, ret)
                    .value()

            @policy.functionCall = (dTgt, dryThis, dryArgs, calcResult, fullName) =>
                throw new Error "here" if fullName.indexOf("writeHead") > -1
                relevantRules = _.chain(@rules).filter(strEqual(fullName))

                beforeRules = relevantRules.filter(areType(BeforeRule))
                afterRules = relevantRules.filter(areType(AfterRule))

                calcResult = beforeRules.filter(conditionsAreTrue(dTgt))
                       .map(doGetActions(dTgt, dryArgs, calcResult))
                       .reduce(calcRetValue, calcResult)
                       .value()

                # return as function because the generic membrane will invoke it afterwards
                ->
                    ret = calcResult()
                    afterRules.filter(conditionsAreTrue(dTgt, ret))
                        .map(doGetActions(dTgt, dryArgs, ret))
                        .reduce(calcRetValue, ret)
                        .value()

            @policy

    class Rule
        constructor: (@apiCall, @parent) ->

List of actions with side effects [0..n]:

            @actions = []

The default return function [1..1]:

            @ret = (v) -> v

A list of conditions that evaluate to `true` or `false` [1..n]:

            @conditions = [() -> true]

        do: (f) =>
            @actions.push f
            this

        return: (f) =>
            @ret = (v) -> f.call(this, v)
            this

        if: (cond) =>
            @conditions.push (dtgt, ret) -> cond(dtgt, ret)
            this

        on: (name) => @parent.on name
        before: (name) => @parent.before name
        after: (name) => @parent.after name
        build: () -> @parent.build()

    class OnRule extends Rule
    class AfterRule extends Rule
    class BeforeRule extends Rule

    module.exports = Policy


Remove old CC 3.0 lisences

Remove old CC 3.0 lisences

    joi = require 'joi'

## All

### Required

These fields are required for all objects.

    exports.required =
      _id: joi.string().regex(/^[a-f0-9]{24}$/)
      tilbyder: joi.string()
      endret: joi.string()
      checksum: joi.string()
      lisens: joi.string().valid([
        'Privat' # @TODO This is just temporarily
        'CC BY 4.0'
        'CC BY-SA 4.0'
        'CC BY-ND 4.0'
        'CC BY-NC 4.0'
        'CC BY-NC-SA 4.0'
        'CC BY-NC-ND 4.0'
      ])
      navngiving: joi.string()
      status: joi.string().valid([
        'Offentlig'
        'Privat'
        'Kladd'
        'Slettet'
      ])

### Optional

There optional are optional for all objects.

    exports.optional =
      navn: joi.string()
      kommuner: joi.array().includes(joi.string())
      fylker: joi.array().includes(joi.string())
      områder: joi.array().includes(joi.string().regex(/^[a-f0-9]{24}$/))
      beskrivelse: joi.string()
      lenker: joi.array().includes(joi.object(
        tittel: joi.string().optional()
        type: joi.string().optional()
        url: joi.string().regex(/^https?:\/\//)
      ))
      tags: joi.array().includes(joi.string())
      privat: joi.object()
      grupper: joi.array().includes(joi.string().regex(/^[a-f0-9]{24}$/))
      steder: joi.array().includes(joi.string().regex(/^[a-f0-9]{24}$/))
      bilder: joi.array().includes(joi.string().regex(/^[a-f0-9]{24}$/))
      url: joi.string().regex(/^https?:\/\//)

## Data types

    exports.type =

### Bilder

      bilder:
        geojson: joi.object(
          type: joi.string().valid('Point').required()
          properties: joi.object(
            altitude: joi.number().integer()
          )
          coordinates: joi.array().includes(joi.number()).length(2).required()
        )
        fotograf: joi.object(
          navn: joi.string()
          telefon: joi.string()
          epost: joi.string().email()
        )
        eier: joi.object(
          navn: joi.string()
          telefon: joi.string()
          epost: joi.string().email()
          url: joi.string().regex(/^https?:\/\//)
        )
        img: joi.array().includes(joi.object(
          url: joi.string().regex(/^https?:\/\//).required()
          width: joi.number().integer()
          height: joi.number().integer()
          size: joi.number()
        ))

### Grupper

      grupper:
        geojson: joi.object(
          type: joi.string().valid('Polygon').required()
          coordinates: joi.array().includes(
            joi.array().includes(
              joi.array().includes(joi.number()).length(2)
            )
          ).required()
        )
        organisasjonsnr: joi.string()
        logo: joi.string().regex(/^https?:\/\//)
        ansatte: joi.number().integer()
        kontaktinfo: joi.array().includes(joi.object(
          tittel: joi.string()
          adresse1: joi.string()
          adresse2: joi.string()
          postnummer: joi.number().integer()
          poststed: joi.string()
          land: joi.string()
          telefon: joi.string()
          fax: joi.string()
          epost: joi.string().email()
          url: joi.string().regex(/^https?:\/\//)
        ))
        foreldregruppe: joi.string().regex(/^[a-f0-9]{24}$/)

### Turer

      turer:
        geojson: joi.object(
          type: joi.string().valid('LineString').required()
          coordinates: joi.array().includes(
            joi.array().includes(joi.number()).length(2)
          ).required()
        )
        distanse: joi.number()
        retning: joi.string().valid([
          "AB"
          "BA"
          "ABA"
          "BAB"
        ])
        adkomst: joi.string()
        gradering: joi.string().valid([
          "Enkel"
          "Middels"
          "Krevende"
          "Ekspert"
        ])
        passer_for: joi.array().includes(joi.string())
        tilrettelagt_for: joi.array().includes(joi.string())
        sesong: joi.array().includes(joi.number().integer().min(1).max(12))
        tidsbruk: joi.object(
          normal: joi.object(
            dager: joi.number().integer()
            timer: joi.number().integer()
            minutter: joi.number().integer()
          )
          min: joi.object(
            dager: joi.number().integer()
            timer: joi.number().integer()
            minutter: joi.number().integer()
          )
          max: joi.object(
            dager: joi.number().integer()
            timer: joi.number().integer()
            minutter: joi.number().integer()
          )
        )

### Områder

      områder:
        geojson: joi.object(
          type: joi.string().valid('Polygon').required()
          coordinates: joi.array().includes(
            joi.array().includes(
              joi.array().includes(joi.number()).length(2)
            )
          ).required()
        )
        foreldreområder: joi.array().includes(joi.string().regex(/^[a-f0-9]{24}$/))

### Steder

      steder:
        navn_alt: joi.array().includes(joi.string())
        ssr_id: joi.number().integer()
        geojson: joi.object(
          type: joi.string().valid('Point').required()
          properties: joi.object(
            altitude: joi.number().integer()
          )
          coordinates: joi.array().includes(joi.number()).length(2).required()
        )
        kommune: joi.string()
        fylke: joi.string()
        adkomst: joi.object(
          sommer: joi.string()
          vinter: joi.string()
        )
        tilrettelagt_for: joi.array().includes(joi.string())
        fasiliteter: joi.object()
        byggeår: joi.number().integer()
        besøksstatisikk: joi.object()
        betjeningsgrad: joi.string()
        kart: joi.string()
        turkart: joi.array().includes(joi.string())

    joi = require 'joi'

## All

### Required

These fields are required for all objects.

    exports.required =
      _id: joi.string().regex(/^[a-f0-9]{24}$/)
      tilbyder: joi.string()
      endret: joi.string()
      checksum: joi.string()
      lisens: joi.string().valid([
        'Privat' # @TODO This is just temporarily
        'CC BY 3.0 NO'
        'CC BY-SA 3.0 NO'
        'CC BY-ND 3.0 NO'
        'CC BY-NC 3.0 NO'
        'CC BY-NC-SA 3.0 NO'
        'CC BY-NC-ND 3.0 NO'
        'CC BY 4.0'
        'CC BY-SA 4.0'
        'CC BY-ND 4.0'
        'CC BY-NC 4.0'
        'CC BY-NC-SA 4.0'
        'CC BY-NC-ND 4.0'
      ])
      navngiving: joi.string()
      status: joi.string().valid([
        'Offentlig'
        'Privat'
        'Kladd'
        'Slettet'
      ])

### Optional

There optional are optional for all objects.

    exports.optional =
      navn: joi.string()
      kommuner: joi.array().includes(joi.string())
      fylker: joi.array().includes(joi.string())
      områder: joi.array().includes(joi.string().regex(/^[a-f0-9]{24}$/))
      beskrivelse: joi.string()
      lenker: joi.array().includes(joi.object(
        tittel: joi.string().optional()
        type: joi.string().optional()
        url: joi.string().regex(/^https?:\/\//)
      ))
      tags: joi.array().includes(joi.string())
      privat: joi.object()
      grupper: joi.array().includes(joi.string().regex(/^[a-f0-9]{24}$/))
      steder: joi.array().includes(joi.string().regex(/^[a-f0-9]{24}$/))
      bilder: joi.array().includes(joi.string().regex(/^[a-f0-9]{24}$/))
      url: joi.string().regex(/^https?:\/\//)

## Data types

    exports.type =

### Bilder

      bilder:
        geojson: joi.object(
          type: joi.string().valid('Point').required()
          properties: joi.object(
            altitude: joi.number().integer()
          )
          coordinates: joi.array().includes(joi.number()).length(2).required()
        )
        fotograf: joi.object(
          navn: joi.string()
          telefon: joi.string()
          epost: joi.string().email()
        )
        eier: joi.object(
          navn: joi.string()
          telefon: joi.string()
          epost: joi.string().email()
          url: joi.string().regex(/^https?:\/\//)
        )
        img: joi.array().includes(joi.object(
          url: joi.string().regex(/^https?:\/\//).required()
          width: joi.number().integer()
          height: joi.number().integer()
          size: joi.number()
        ))

### Grupper

      grupper:
        geojson: joi.object(
          type: joi.string().valid('Polygon').required()
          coordinates: joi.array().includes(
            joi.array().includes(
              joi.array().includes(joi.number()).length(2)
            )
          ).required()
        )
        organisasjonsnr: joi.string()
        logo: joi.string().regex(/^https?:\/\//)
        ansatte: joi.number().integer()
        kontaktinfo: joi.array().includes(joi.object(
          tittel: joi.string()
          adresse1: joi.string()
          adresse2: joi.string()
          postnummer: joi.number().integer()
          poststed: joi.string()
          land: joi.string()
          telefon: joi.string()
          fax: joi.string()
          epost: joi.string().email()
          url: joi.string().regex(/^https?:\/\//)
        ))
        foreldregruppe: joi.string().regex(/^[a-f0-9]{24}$/)

### Turer

      turer:
        geojson: joi.object(
          type: joi.string().valid('LineString').required()
          coordinates: joi.array().includes(
            joi.array().includes(joi.number()).length(2)
          ).required()
        )
        distanse: joi.number()
        retning: joi.string().valid([
          "AB"
          "BA"
          "ABA"
          "BAB"
        ])
        adkomst: joi.string()
        gradering: joi.string().valid([
          "Enkel"
          "Middels"
          "Krevende"
          "Ekspert"
        ])
        passer_for: joi.array().includes(joi.string())
        tilrettelagt_for: joi.array().includes(joi.string())
        sesong: joi.array().includes(joi.number().integer().min(1).max(12))
        tidsbruk: joi.object(
          normal: joi.object(
            dager: joi.number().integer()
            timer: joi.number().integer()
            minutter: joi.number().integer()
          )
          min: joi.object(
            dager: joi.number().integer()
            timer: joi.number().integer()
            minutter: joi.number().integer()
          )
          max: joi.object(
            dager: joi.number().integer()
            timer: joi.number().integer()
            minutter: joi.number().integer()
          )
        )

### Områder

      områder:
        geojson: joi.object(
          type: joi.string().valid('Polygon').required()
          coordinates: joi.array().includes(
            joi.array().includes(
              joi.array().includes(joi.number()).length(2)
            )
          ).required()
        )
        foreldreområder: joi.array().includes(joi.string().regex(/^[a-f0-9]{24}$/))

### Steder

      steder:
        navn_alt: joi.array().includes(joi.string())
        ssr_id: joi.number().integer()
        geojson: joi.object(
          type: joi.string().valid('Point').required()
          properties: joi.object(
            altitude: joi.number().integer()
          )
          coordinates: joi.array().includes(joi.number()).length(2).required()
        )
        kommune: joi.string()
        fylke: joi.string()
        adkomst: joi.object(
          sommer: joi.string()
          vinter: joi.string()
        )
        tilrettelagt_for: joi.array().includes(joi.string())
        fasiliteter: joi.object()
        byggeår: joi.number().integer()
        besøksstatisikk: joi.object()
        betjeningsgrad: joi.string()
        kart: joi.string()
        turkart: joi.array().includes(joi.string())


Update Librato image count handling

Update Librato image count handling

    url          = require 'url'

    compression  = require 'compression'
    express      = require 'express'
    morgan       = require 'morgan'
    responseTime = require 'response-time'

    multer       = require 'multer'
    async        = require 'async'
    dms2dec      = require 'dms2dec'

    raven        = require 'raven'
    sentry       = require './sentry'
    librato      = require './librato'

    app = express()
    app.use morgan 'combined'
    app.use compression()
    app.use responseTime()

    Upload = require 's3-uploader'
    s3 = new Upload process.env.AWS_BUCKET_NAME,
      awsBucketRegion: process.env.AWS_BUCKET_REGION
      awsBucketPath: process.env.AWS_BUCKET_PATH
      awsBucketAcl: 'public-read'
      awsHttpTimeout: 60000
      returnExif: true

      versions: [{
        original: true
        awsImageAcl: 'private'
      },{
        suffix: '-large'
        quality: 80
        maxHeight: 1040
        maxWidth: 1040
      },{
        suffix: '-medium'
        maxHeight: 780
        maxWidth: 780
      },{
        suffix: '-small'
        maxHeight: 320
        maxWidth: 320
      }]

    origins = process.env.ALLOW_ORIGINS?.split(',') or []

    app.all '/upload', (req, res, next) ->
      res.once 'close', -> sentry.captureResClose res

      origin = url.parse req.get('Origin') or ''

      if origin.hostname not in origins
        error = new Error "Bad Origin Header #{req.get('Origin')}"
        error.status = 403
        return next error

      res.set 'Access-Control-Allow-Origin', req.get('Origin')
      res.set 'Access-Control-Allow-Methods', 'POST'
      res.set 'Access-Control-Allow-Headers', 'X-Requested-With, Content-Type'
      res.set 'Access-Control-Expose-Headers', 'X-Response-Time'
      res.set 'Access-Control-Allow-Max-Age', 0

      return res.send 200 if req.method is 'OPTIONS'
      return next()

    app.post '/upload', multer(dest: require('os').tmpdir()), (req, res, next) ->
      librato.logImagesUploaded Object.keys req.files

      async.mapSeries Object.keys(req.files), (key, cb) ->
        if req.files[key].extension.toLowerCase() not in ['jpg', 'jpeg', 'png', 'gif']
          error = new Error "Invalid Image #{req.files[key].extension}"
          error.status = 422
          return cb error

        t1 = new Date().getTime()
        s3.upload req.files[key].path, {}, (err, images, meta) ->
          return cb err if err

          librato.logImageProcessingTime t1, new Date().getTime()

          if meta.exif['exif:GPSLatitude'] and meta.exif['exif:GPSLongitude']
            meta.geojson =
              type: 'Point'
              coordinates: dms2dec \
                meta.exif['exif:GPSLatitude'], \
                meta.exif['exif:GPSLatitudeRef'], \
                meta.exif['exif:GPSLongitude'], \
                meta.exif['exif:GPSLongitudeRef']
              .reverse()

          return cb null, versions: images.splice(1), meta: meta
      , (err, files) ->
        return next err if err
        sentry.captureHeaderSent req, files if res._headerSent
        return res.status(201).json files

    app.use (req, res, next) ->
      res.status(404).json message: 'Not Found'

    app.use raven.middleware.express sentry
    app.use (err, req, res, next) ->
      if not err.status or err.status >= 500
        sentry.captureError err

        console.error err.message
        console.error err.stack

        res.status(err.status or 500).json message: 'Internal Server Error'
      else
        sentry.captureMessage err.message, level: 'warning', req: req
        res.status(err.status).json message: err.message

    if not module.parent
      app.listen process.env.PORT_WWW
      console.log "Server listening on port #{process.env.PORT_WWW}"
    else
      module.exports = app

    url          = require 'url'

    compression  = require 'compression'
    express      = require 'express'
    morgan       = require 'morgan'
    responseTime = require 'response-time'

    multer       = require 'multer'
    async        = require 'async'
    dms2dec      = require 'dms2dec'

    raven        = require 'raven'
    sentry       = require './sentry'
    librato      = require './librato'

    app = express()
    app.use morgan 'combined'
    app.use compression()
    app.use responseTime()

    Upload = require 's3-uploader'
    s3 = new Upload process.env.AWS_BUCKET_NAME,
      awsBucketRegion: process.env.AWS_BUCKET_REGION
      awsBucketPath: process.env.AWS_BUCKET_PATH
      awsBucketAcl: 'public-read'
      awsHttpTimeout: 60000
      returnExif: true

      versions: [{
        original: true
        awsImageAcl: 'private'
      },{
        suffix: '-large'
        quality: 80
        maxHeight: 1040
        maxWidth: 1040
      },{
        suffix: '-medium'
        maxHeight: 780
        maxWidth: 780
      },{
        suffix: '-small'
        maxHeight: 320
        maxWidth: 320
      }]

    origins = process.env.ALLOW_ORIGINS?.split(',') or []

    app.all '/upload', (req, res, next) ->
      res.once 'close', -> sentry.captureResClose res

      origin = url.parse req.get('Origin') or ''

      if origin.hostname not in origins
        error = new Error "Bad Origin Header #{req.get('Origin')}"
        error.status = 403
        return next error

      res.set 'Access-Control-Allow-Origin', req.get('Origin')
      res.set 'Access-Control-Allow-Methods', 'POST'
      res.set 'Access-Control-Allow-Headers', 'X-Requested-With, Content-Type'
      res.set 'Access-Control-Expose-Headers', 'X-Response-Time'
      res.set 'Access-Control-Allow-Max-Age', 0

      return res.send 200 if req.method is 'OPTIONS'
      return next()

    app.post '/upload', multer(dest: require('os').tmpdir()), (req, res, next) ->
      librato.measure 'image.upload', Object.keys(req.files).length, {}

      async.mapSeries Object.keys(req.files), (key, cb) ->
        if req.files[key].extension.toLowerCase() not in ['jpg', 'jpeg', 'png', 'gif']
          error = new Error "Invalid Image #{req.files[key].extension}"
          error.status = 422
          return cb error

        t1 = new Date().getTime()
        s3.upload req.files[key].path, {}, (err, images, meta) ->
          return cb err if err

          librato.logImageProcessingTime t1, new Date().getTime()

          if meta.exif['exif:GPSLatitude'] and meta.exif['exif:GPSLongitude']
            meta.geojson =
              type: 'Point'
              coordinates: dms2dec \
                meta.exif['exif:GPSLatitude'], \
                meta.exif['exif:GPSLatitudeRef'], \
                meta.exif['exif:GPSLongitude'], \
                meta.exif['exif:GPSLongitudeRef']
              .reverse()

          return cb null, versions: images.splice(1), meta: meta
      , (err, files) ->
        return next err if err
        sentry.captureHeaderSent req, files if res._headerSent
        return res.status(201).json files

    app.use (req, res, next) ->
      res.status(404).json message: 'Not Found'

    app.use raven.middleware.express sentry
    app.use (err, req, res, next) ->
      if not err.status or err.status >= 500
        sentry.captureError err

        console.error err.message
        console.error err.stack

        res.status(err.status or 500).json message: 'Internal Server Error'
      else
        sentry.captureMessage err.message, level: 'warning', req: req
        res.status(err.status).json message: err.message

    if not module.parent
      app.listen process.env.PORT_WWW
      console.log "Server listening on port #{process.env.PORT_WWW}"
    else
      module.exports = app


more formatting

more formatting

### Underscore Strings

Useful Underscore string methods for more readable, human language:

- [Capitalization](#capitalization)
- [Cases](#cases)
- [Tags](#tags)
- [Lists](#lists)
- [Hyphenation](#hyphenation)
- [Quantify](#quantify)
- [Written Numbers](#written-numbers)

-------

#### Setup
Do nothing without the presence of Underscore.

    return unless _?

This regular expression includes words we won't capitalize.

    noncapsWords = /^(a|an|and|as|be|of|the|to)$/

...and this helps to split "cased" words into their constituent parts...

    caseSplitter = /[-_\s]|(!?[A-Z][a-z]*)/g

...so we can join them together with some glue.

    cleanJoin    = (arr, glue) -> _.compact(arr).join(glue)

Assuming we are using the English language, we'll declare some numbers

    numbers =
      "EN": ["one", "two", "three", "four", "five", "six", "seven","eight", "nine", "ten", "eleven", "twelve"]
      "FR": [{m: "un", f: "une"}, "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf", "dix", "onze", "douze"]
      "DE": ["eins", "zwei", "drei", "vier", "fünf", "sechs", "sieben", "acht", "neun", "zehn", "elf", "zwölf"]
      "IT": [{m: "uno", f: "una"}, "due", "tre", "quattro", "cinque", "sei", "sette", "otto", "nove", "dieci", "undici", "dodic"]
      "ES": [{m: "uno", f: "una"}, "dos", "tres", "cuatro", "cinco", "seis", "siete", "ocho", "nueve", "diez", "once", "doce"]

Declare the mixins we're adding...

    mixins =

-------

#### Capitalization
Capitalize the first letter of a string.

      capitalize: (str) ->
        str.charAt(0).toUpperCase() + str.slice(1)

Capitalize all words in a string apart from some common lower case words.

```coffee
# Examples
_.capitalizeAll("this and that") # "This and That"
```

      capitalizeAll: (str, regEx = noncapsWords) ->
        _.map(str.split(" "), (s, i) ->
          if i > 0 and regEx.test(s) then s else _.capitalize(s)
        ).join(" ")

#### Cases
Transform strings between common code cases:

```coffee
# Examples
_.camelCase("some-thing")  # "someThing"
_.hyphenCase("some_thing") # "some-thing"
_.snakeCase("someThing")   # "some_thing"
_.humanCase("fromA_to-Z")  # "from A to Z"
```

      camelCase: (str) ->
        str.replace(/[\s_-](\w)/g, (a, w) -> w.toUpperCase())

      hyphenCase: (str) ->
        cleanJoin(str.split(caseSplitter), "-").toLowerCase()

      snakeCase: (str) ->
        cleanJoin(str.split(caseSplitter), "_").toLowerCase()

      humanCase: (str) ->
        cleanJoin(str.split(caseSplitter), " ")

#### Tags
Enclose a string inside an HTML tag.

```coffee
# Examples
_.wrapInTag("Hello world!", "strong") # "<strong>Hello world!</strong>"
```

      wrapInTag: (str, tag = "span") ->
        "<#{tag}>#{str}</#{tag}>"

#### Lists
Group strings into a grammatically correct list with an arbitrary limit.

```coffee
# Examples
_.prettyList(["Ben", "Bob"])                      # "Ben and Bob"
_.prettyList(["Ben", "Bob", "Bill"])              # "Ben, Bob and Bill"
_.prettyList(["Ben", "Bob", "Bill", "Max"], 2)    # "Ben, Bob and 2 more"
_.prettyList(["Ben", "Bob"], 1, {more: "other"})  # "Ben and 1 other"
```

      prettyList: (arr, max, opts = {}) ->
        more   = opts.more or "more"
        amp    = opts.amp or "and"

        if opts.wrap
          arr = _.map(arr, (s) -> _.wrapInTag(s, opts.wrap))

        if max < (len = arr.length)
          diff = len - max
          more = _.quantify(more, diff, false) if opts.quantify
          diff = _.writtenNumber(diff, opts.numbers) if opts.written
          arr  = arr.slice(0, max)
          arr  = arr.concat("#{diff} #{more}")

        arr
          .slice(0, -1)
          .join(", ")
          .concat((if arr.length is 1 then "" else " #{amp} "), arr.slice(-1))

#### Hyphenation
Add soft hyphens every `n` characters so that the CSS attribute
`hyphens: manual` will allow for nice breaks in long strings of text.

```coffee
# Examples
_.hyphenate("antidisestablishmentarianism") # "antidisest%C2%ADablishment%C2%ADarianism"
```

      hyphenate: (str = "", n = 10, softHyphen = "\u00AD") ->
        str.replace new RegExp("\\w{#{n}}", "g"), (w) -> w + softHyphen

#### Quantify
Add an "s" to a string when an amount is non-singular, disregarding the
order of the arguments passsed.

```coffee
# Examples
_.prettyList("monkey", 1)                   # "1 monkey"
_.prettyList(1, "monkey")                   # "1 monkey"
_.prettyList("monkey", 9, written: true)    # "nine monkeys"
```

      quantify: (str, n, {numberless, written, lang}) ->
        { n, str } = str: n, n: str unless _.isString(str)

        _n = _.writtenNumber(n, lang) if written?

        (if numberless? then "" else _n + " ") +
        str +
        (if n is 1 then "" else "s")

#### Written Numbers
Convert numbers between one and twelve into their written counter-parts.

```coffee
# Examples
_.writtenNumber(1)                          # "one"
_.writtenNumber(2, "DE")                    # "zwei"
```

      writtenNumber: (n, lang = "EN", gender = "m") ->
        if n < 13
          num = numbers[lang][n - 1]
          num[gender] and num[gender] or num
        else
          n

      setNumbers: (arr, lang) ->
        numbers[lang] = arr

Add the mixin object to Underscore.

    _.mixin(mixins)

### Underscore Strings

Useful Underscore string methods for more readable, human language

Do nothing without the presence of Underscore.

    return unless _?

This regular expression includes words we won't capitalize.

    noncapsWords = /^(a|an|and|as|be|of|the|to)$/

...and this helps to split "cased" words into their constituent parts...

    caseSplitter = /[-_\s]|(!?[A-Z][a-z]*)/g

...so we can join them together with some glue.

    cleanJoin    = (arr, glue) -> _.compact(arr).join(glue)

Assuming we are using the English language, we'll declare some numbers

    numbers =
      "EN": ["one", "two", "three", "four", "five", "six", "seven","eight", "nine", "ten", "eleven", "twelve"]
      "FR": [{m: "un", f: "une"}, "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf", "dix", "onze", "douze"]
      "DE": ["eins", "zwei", "drei", "vier", "fünf", "sechs", "sieben", "acht", "neun", "zehn", "elf", "zwölf"]
      "IT": [{m: "uno", f: "una"}, "due", "tre", "quattro", "cinque", "sei", "sette", "otto", "nove", "dieci", "undici", "dodic"]
      "ES": [{m: "uno", f: "una"}, "dos", "tres", "cuatro", "cinco", "seis", "siete", "ocho", "nueve", "diez", "once", "doce"]

Declare the mixins we're adding...

    mixins =

#### Capitalization
Capitalize the first letter of a string.

      capitalize: (str) ->
        str.charAt(0).toUpperCase() + str.slice(1)

Capitalize all words in a string apart from some common lower case words.

```coffee
# Examples
_.capitalizeAll("this and that") # "This and That"
```

      capitalizeAll: (str, regEx = noncapsWords) ->
        _.map(str.split(" "), (s, i) ->
          if i > 0 and regEx.test(s) then s else _.capitalize(s)
        ).join(" ")

#### Cases
Transform strings between common code cases:

```coffee
# Examples
_.camelCase("some-thing")  # "someThing"
_.hyphenCase("some_thing") # "some-thing"
_.snakeCase("someThing")   # "some_thing"
_.humanCase("fromA_to-Z")  # "from A to Z"
```

      camelCase: (str) ->
        str.replace(/[\s_-](\w)/g, (a, w) -> w.toUpperCase())

      hyphenCase: (str) ->
        cleanJoin(str.split(caseSplitter), "-").toLowerCase()

      snakeCase: (str) ->
        cleanJoin(str.split(caseSplitter), "_").toLowerCase()

      humanCase: (str) ->
        cleanJoin(str.split(caseSplitter), " ")

#### Tags
Enclose a string inside an HTML tag.

```coffee
# Examples
_.wrapInTag("Hello world!", "strong") # "<strong>Hello world!</strong>"
```

      wrapInTag: (str, tag = "span") ->
        "<#{tag}>#{str}</#{tag}>"

#### Lists
Group strings into a grammatically correct list with an arbitrary limit.

```coffee
# Examples
_.prettyList(["Ben", "Bob"])                      # "Ben and Bob"
_.prettyList(["Ben", "Bob", "Bill"])              # "Ben, Bob and Bill"
_.prettyList(["Ben", "Bob", "Bill", "Max"], 2)    # "Ben, Bob and 2 more"
_.prettyList(["Ben", "Bob"], 1, {more: "other"})  # "Ben and 1 other"
```

      prettyList: (arr, max, opts = {}) ->
        more   = opts.more or "more"
        amp    = opts.amp or "and"

        if opts.wrap
          arr = _.map(arr, (s) -> _.wrapInTag(s, opts.wrap))

        if max < (len = arr.length)
          diff = len - max
          more = _.quantify(more, diff, false) if opts.quantify
          diff = _.writtenNumber(diff, opts.numbers) if opts.written
          arr  = arr.slice(0, max)
          arr  = arr.concat("#{diff} #{more}")

        arr
          .slice(0, -1)
          .join(", ")
          .concat((if arr.length is 1 then "" else " #{amp} "), arr.slice(-1))

#### Hyphenation
Add soft hyphens every `n` characters so that the CSS attribute
`hyphens: manual` will allow for nice breaks in long strings of text.

```coffee
# Examples
_.hyphenate("antidisestablishmentarianism") # "antidisest%C2%ADablishment%C2%ADarianism"
```

      hyphenate: (str = "", n = 10, softHyphen = "\u00AD") ->
        str.replace new RegExp("\\w{#{n}}", "g"), (w) -> w + softHyphen

Add an "s" to a string when an amount is non-singular, disregarding the
order of the arguments passsed.

```coffee
# Examples
_.prettyList("monkey", 1)                   # "1 monkey"
_.prettyList(1, "monkey")                   # "1 monkey"
_.prettyList("monkey", 9, written: true)    # "nine monkeys"
```

      quantify: (str, n, {numberless, written, lang}) ->
        { n, str } = str: n, n: str unless _.isString(str)

        _n = _.writtenNumber(n, lang) if written?

        (if numberless? then "" else _n + " ") +
        str +
        (if n is 1 then "" else "s")

#### Written Numbers
Convert numbers between one and twelve into their written counter-parts.

```coffee
# Examples
_.writtenNumber(1)                          # "one"
_.writtenNumber(2, "DE")                    # "zwei"
```

      writtenNumber: (n, lang = "EN", gender = "m") ->
        if n < 13
          num = numbers[lang][n - 1]
          num[gender] and num[gender] or num
        else
          n

      setNumbers: (arr, lang) ->
        numbers[lang] = arr

Add the mixin object to Underscore.

    _.mixin(mixins)


Don't be rude.

Don't be rude.

Multiples of 3 and 5
====================
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get
3, 5, 6 and 9. The sum of these multiples is 23.

Find the sum of all the multiples of 3 or 5 below 1000.

Answer
======
Include library functions for Number Theory.

    require('./number-theory')

Don't include 1000 in this strange Fizz Buzz.

    multiples = (n for n in [1..999] when 3.divides(n) || 5.divides(n))

    answer = multiples.sum()
    console.log(answer)

Multiples of 3 and 5
====================
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get
3, 5, 6 and 9. The sum of these multiples is 23.

Find the sum of all the multiples of 3 or 5 below 1000.

Answer
======
Include library functions for Number Theory.

    require('./number-theory')

Don't include 1000 in this perverted Fizz Buzz.

    multiples = (n for n in [1..999] when 3.divides(n) || 5.divides(n))

    answer = multiples.sum()
    console.log(answer)


removing sourceColumn reset

removing sourceColumn reset

Source maps allow JavaScript runtimes to match running JavaScript back to
the original source code that corresponds to it. This can be minified
JavaScript, but in our case, we're concerned with mapping pretty-printed
JavaScript back to CoffeeScript.

In order to produce maps, we must keep track of positions (line number, column number)
that originated every node in the syntax tree, and be able to generate a
[map file](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit)
— which is a compact, VLQ-encoded representation of the JSON serialization
of this information — to write out alongside the generated JavaScript.

LineMap
-------

A **LineMap** object keeps track of information about original line and column
positions for a single line of output JavaScript code.
**SourceMaps** are implemented in terms of **LineMaps**.

    class LineMap
      constructor: (@line) ->
        @columns = []

      add: (column, [sourceLine, sourceColumn], options={}) ->
        return if @columns[column] and options.noReplace
        @columns[column] = {line: @line, column, sourceLine, sourceColumn}

      sourceLocation: (column) ->
        column-- until (mapping = @columns[column]) or (column <= 0)
        mapping and [mapping.sourceLine, mapping.sourceColumn]

SourceMap
---------

Maps locations in a single generated JavaScript file back to locations in
the original CoffeeScript source file.

This is intentionally agnostic towards how a source map might be represented on
disk. Once the compiler is ready to produce a "v3"-style source map, we can walk
through the arrays of line and column buffer to produce it.

    class SourceMap
      constructor: ->
        @lines = []

Adds a mapping to this SourceMap. `sourceLocation` and `generatedLocation`
are both `[line, column]` arrays. If `options.noReplace` is true, then if there
is already a mapping for the specified `line` and `column`, this will have no
effect.

      add: (sourceLocation, generatedLocation, options = {}) ->
        [line, column] = generatedLocation
        lineMap = (@lines[line] or= new LineMap(line))
        lineMap.add column, sourceLocation, options

Look up the original position of a given `line` and `column` in the generated
code.

      sourceLocation: ([line, column]) ->
        line-- until (lineMap = @lines[line]) or (line <= 0)
        lineMap and lineMap.sourceLocation column

V3 SourceMap Generation
-----------------------

Builds up a V3 source map, returning the generated JSON as a string.
`options.sourceRoot` may be used to specify the sourceRoot written to the source
map.  Also, `options.sourceFiles` and `options.generatedFile` may be passed to
set "sources" and "file", respectively.

      generate: (options = {}, code = null) ->
        writingline       = 0
        lastColumn        = 0
        lastSourceLine    = 0
        lastSourceColumn  = 0
        needComma         = no
        buffer            = ""

        for lineMap, lineNumber in @lines when lineMap
          for mapping in lineMap.columns when mapping
            while writingline < mapping.line
              lastColumn = 0
              needComma = no
              buffer += ";"
              writingline++

Write a comma if we've already written a segment on this line.

            if needComma
              buffer += ","
              needComma = no

Write the next segment. Segments can be 1, 4, or 5 values.  If just one, then it
is a generated column which doesn't match anything in the source code.

The starting column in the generated source, relative to any previous recorded
column for the current line:

            buffer += @encodeVlq mapping.column - lastColumn
            lastColumn = mapping.column

The index into the list of sources:

            buffer += @encodeVlq 0

The starting line in the original source, relative to the previous source line.

            buffer += @encodeVlq mapping.sourceLine - lastSourceLine
            lastSourceLine = mapping.sourceLine

The starting column in the original source, relative to the previous column.

            buffer += @encodeVlq mapping.sourceColumn - lastSourceColumn
            lastSourceColumn = mapping.sourceColumn
            needComma = yes

Produce the canonical JSON object format for a "v3" source map.

        v3 =
          version:    3
          file:       options.generatedFile or ''
          sourceRoot: options.sourceRoot or ''
          sources:    options.sourceFiles or ['']
          names:      []
          mappings:   buffer

        v3.sourcesContent = [code] if options.inline

        JSON.stringify v3, null, 2

Base64 VLQ Encoding
-------------------

Note that SourceMap VLQ encoding is "backwards".  MIDI-style VLQ encoding puts
the most-significant-bit (MSB) from the original value into the MSB of the VLQ
encoded value (see [Wikipedia](http://en.wikipedia.org/wiki/File:Uintvar_coding.svg)).
SourceMap VLQ does things the other way around, with the least significat four
bits of the original value encoded into the first byte of the VLQ encoded value.

      VLQ_SHIFT            = 5
      VLQ_CONTINUATION_BIT = 1 << VLQ_SHIFT             # 0010 0000
      VLQ_VALUE_MASK       = VLQ_CONTINUATION_BIT - 1   # 0001 1111

      encodeVlq: (value) ->
        answer = ''

        # Least significant bit represents the sign.
        signBit = if value < 0 then 1 else 0

        # The next bits are the actual value.
        valueToEncode = (Math.abs(value) << 1) + signBit

        # Make sure we encode at least one character, even if valueToEncode is 0.
        while valueToEncode or not answer
          nextChunk = valueToEncode & VLQ_VALUE_MASK
          valueToEncode = valueToEncode >> VLQ_SHIFT
          nextChunk |= VLQ_CONTINUATION_BIT if valueToEncode
          answer += @encodeBase64 nextChunk

        answer

Regular Base64 Encoding
-----------------------

      BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

      encodeBase64: (value) ->
        BASE64_CHARS[value] or throw new Error "Cannot Base64 encode value: #{value}"

Our API for source maps is just the `SourceMap` class.

    module.exports = SourceMap

Source maps allow JavaScript runtimes to match running JavaScript back to
the original source code that corresponds to it. This can be minified
JavaScript, but in our case, we're concerned with mapping pretty-printed
JavaScript back to CoffeeScript.

In order to produce maps, we must keep track of positions (line number, column number)
that originated every node in the syntax tree, and be able to generate a
[map file](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit)
— which is a compact, VLQ-encoded representation of the JSON serialization
of this information — to write out alongside the generated JavaScript.

LineMap
-------

A **LineMap** object keeps track of information about original line and column
positions for a single line of output JavaScript code.
**SourceMaps** are implemented in terms of **LineMaps**.

    class LineMap
      constructor: (@line) ->
        @columns = []

      add: (column, [sourceLine, sourceColumn], options={}) ->
        return if @columns[column] and options.noReplace
        @columns[column] = {line: @line, column, sourceLine, sourceColumn}

      sourceLocation: (column) ->
        column-- until (mapping = @columns[column]) or (column <= 0)
        mapping and [mapping.sourceLine, mapping.sourceColumn]

SourceMap
---------

Maps locations in a single generated JavaScript file back to locations in
the original CoffeeScript source file.

This is intentionally agnostic towards how a source map might be represented on
disk. Once the compiler is ready to produce a "v3"-style source map, we can walk
through the arrays of line and column buffer to produce it.

    class SourceMap
      constructor: ->
        @lines = []

Adds a mapping to this SourceMap. `sourceLocation` and `generatedLocation`
are both `[line, column]` arrays. If `options.noReplace` is true, then if there
is already a mapping for the specified `line` and `column`, this will have no
effect.

      add: (sourceLocation, generatedLocation, options = {}) ->
        [line, column] = generatedLocation
        lineMap = (@lines[line] or= new LineMap(line))
        lineMap.add column, sourceLocation, options

Look up the original position of a given `line` and `column` in the generated
code.

      sourceLocation: ([line, column]) ->
        line-- until (lineMap = @lines[line]) or (line <= 0)
        lineMap and lineMap.sourceLocation column

V3 SourceMap Generation
-----------------------

Builds up a V3 source map, returning the generated JSON as a string.
`options.sourceRoot` may be used to specify the sourceRoot written to the source
map.  Also, `options.sourceFiles` and `options.generatedFile` may be passed to
set "sources" and "file", respectively.

      generate: (options = {}, code = null) ->
        writingline       = 0
        lastColumn        = 0
        lastSourceLine    = 0
        lastSourceColumn  = 0
        needComma         = no
        buffer            = ""

        for lineMap, lineNumber in @lines when lineMap
          for mapping in lineMap.columns when mapping
            while writingline < mapping.line
              lastColumn = 0
              needComma = no
              buffer += ";"
              writingline++

Write a comma if we've already written a segment on this line.

            if needComma
              buffer += ","
              needComma = no

Write the next segment. Segments can be 1, 4, or 5 values.  If just one, then it
is a generated column which doesn't match anything in the source code.

The starting column in the generated source, relative to any previous recorded
column for the current line:

            buffer += @encodeVlq mapping.column - lastColumn
            lastColumn = mapping.column

The index into the list of sources:

            buffer += @encodeVlq 0

The starting line in the original source, relative to the previous source line.

            buffer += @encodeVlq mapping.sourceLine - lastSourceLine
            if lastSourceLine isnt mapping.sourceLine
              lastSourceLine = mapping.sourceLine
              lastSourceColumn = 0

The starting column in the original source, relative to the previous column.

            buffer += @encodeVlq mapping.sourceColumn - lastSourceColumn
            lastSourceColumn = mapping.sourceColumn
            needComma = yes

Produce the canonical JSON object format for a "v3" source map.

        v3 =
          version:    3
          file:       options.generatedFile or ''
          sourceRoot: options.sourceRoot or ''
          sources:    options.sourceFiles or ['']
          names:      []
          mappings:   buffer

        v3.sourcesContent = [code] if options.inline

        JSON.stringify v3, null, 2

Base64 VLQ Encoding
-------------------

Note that SourceMap VLQ encoding is "backwards".  MIDI-style VLQ encoding puts
the most-significant-bit (MSB) from the original value into the MSB of the VLQ
encoded value (see [Wikipedia](http://en.wikipedia.org/wiki/File:Uintvar_coding.svg)).
SourceMap VLQ does things the other way around, with the least significat four
bits of the original value encoded into the first byte of the VLQ encoded value.

      VLQ_SHIFT            = 5
      VLQ_CONTINUATION_BIT = 1 << VLQ_SHIFT             # 0010 0000
      VLQ_VALUE_MASK       = VLQ_CONTINUATION_BIT - 1   # 0001 1111

      encodeVlq: (value) ->
        answer = ''

        # Least significant bit represents the sign.
        signBit = if value < 0 then 1 else 0

        # The next bits are the actual value.
        valueToEncode = (Math.abs(value) << 1) + signBit

        # Make sure we encode at least one character, even if valueToEncode is 0.
        while valueToEncode or not answer
          nextChunk = valueToEncode & VLQ_VALUE_MASK
          valueToEncode = valueToEncode >> VLQ_SHIFT
          nextChunk |= VLQ_CONTINUATION_BIT if valueToEncode
          answer += @encodeBase64 nextChunk

        answer

Regular Base64 Encoding
-----------------------

      BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

      encodeBase64: (value) ->
        BASE64_CHARS[value] or throw new Error "Cannot Base64 encode value: #{value}"

Our API for source maps is just the `SourceMap` class.

    module.exports = SourceMap


add to usage notes

add to usage notes

# /api/Extras/Batman.Paginator

`Batman.Paginator` is an abstract class which is implemented by `Batman.ModelPaginator`. For information about paginating records, see `Batman.ModelPaginator`.

`Batman.Paginator` provides:

- exposing pages of records (via `toArray`) and changing pages (`nextPage` / `previousPage`)
- item caching and  prevention of reloading/concurrent loading of pages
- calculation calucations for `page`, `offset`, `limit`, etc.

## ::constructor(options={}) : Paginator

Returns a new paginator, mixing in `options`. `options` may include:

- `limit`
- `offset` or `page`
- `totalCount`

## ::loadItemsForOffsetAndLimit(offset, limit)

Implementations of `Batman.Paginator` must implement this function. See `Batman.ModelPaginator` for an example.

This function should load items, then call `@updateCache(offset, limit, items)`.

Internally, `Batman.Paginator`:

- prevents reloading a page when it's still loading
- prevents loading a page twice

## ::%toArray : Array

Returns an array of items in the current `page`. This property depends on `offset` and `limit`, so changing `offset`, `limit` or `page` will automatically update `toArray`.

## ::nextPage()

Increments the current `page`, causing `toArray` to be updated.

## ::previousPage()

Decrements the current `page`, causing `toArray` to be updated.

## ::%page : Number

Current page number, determined by `offset` and `limit`. Setting `page` automatically increases `offset`.

Since `toArray` depends on `offset`, setting `page` will also cause `toArray` to be updated.

## ::%offset : Number

Number of items skipped for the current `page`.

## ::%limit : Number

Items per page.

## ::%totalCount : Number

Total number of records covered by the `Paginator`.

## ::%pageCount : Number

Total number of pages covered by the `Paginator`, calculated from `totalCount` and `limit`.

## ::updateCache(offset, limit, items)

Registers `items` as the items from `offset` for `limit`. This should be called by `loadItemsForOffsetAndLimit` to inform the paginator of loaded records.

# /api/Extras/Batman.Paginator/Batman.ModelPaginator

`Batman.ModelPaginator` is a concrete implementation of `Batman.Paginator`. It may be used for paginating `Batman.Model` instances.

A `Batman.ModelPaginator` provides pagination by:

- Taking `model`, `limit`, `params`, and `page`/`offset` as input
- Exposing records by its `toArray` property (eg, `paginator.get('toArray')`)

## Using Batman.ModelPaginator

Add a paginator to your controller:

```coffeescript
class App.PostsController extends Batman.Controller
  index: -> # renders posts/index.html
    @set 'paginator, new Batman.ModelPaginator
      model: App.Post
      limit: 10
      page: 1
      params: {order: "created_at"}
```

Then, bind to it in your HTML:

```html
<ul>
  <li data-foreach-post='paginator.toArray'>
    <span data-bind='post.name'></span>
  </li>
</ul>
<button data-event-click='paginator.previousPage'>Prev</button>
<button data-event-click='paginator.nextPage'>    Next</button>
```

If you want your paginator to update from other properties, wrap it in `@accessor`. For example, to make a new paginator when `postsOrder` changes, you could:

```coffeescript
class App.PostsController extends Batman.Controller
  index: ->
    @set('postsOrder', 'created_at')
    # renders posts/index.html

  @accessor 'paginator,
    new Batman.ModelPaginator
      model: App.Post
      limit: 10
      page: 1
      params: {order: @get('postsOrder')}
```

Now, if you set `postsOrder` to `length`, it would cause `paginator` to be reevaluated, and the new paginator would use `order=length` to load records. Also, `paginator.toArray` would be updated with the new records in the new order.

## ::constructor(options) : ModelPaginator

Besides the options passed to `Batman.Paginator`, you may also pass:

- `model`: A `Batman.Model` class whose records are paginated
- `params` : A plain JS object which will be used when loading items from the server

## ::loadItemsForOffsetAndLimit(offset, limit)

Loads records by calling `@model.load` with:

- any key/values passed as `@params`
- `offset` and `limit`

## ::.params : Object

A plain JavaScript object whose key-value pairs will be passed to `@model.load` when loading records.

## ::.model : Class

A `Batman.Model` subclass whose records are paginated by the `ModelPaginator`.

# /api/Extras/Batman.Paginator

`Batman.Paginator` is an abstract class which is implemented by `Batman.ModelPaginator`. For information about paginating records, see `Batman.ModelPaginator`.

Internally, `Batman.Paginator` prevents loading the same page twice.

## ::constructor(options={}) : Paginator

Returns a new paginator, mixing in `options`. `options` may include:

- `limit`
- `offset` or `page`
- `totalCount`

## ::loadItemsForOffsetAndLimit(offset, limit)

Implementations of `Batman.Paginator` must implement this function. See `Batman.ModelPaginator` for an example.

This function should load items, then call `@updateCache(offset, limit, items)`.

Internally, `Batman.Paginator`:

- prevents reloading a page when it's still loading
- prevents loading a page twice

## ::%toArray : Array

Returns an array of items in the current `page`. This property depends on `offset` and `limit`, so changing `offset`, `limit` or `page` will automatically update `toArray`.

## ::nextPage()

Increments the current `page`, causing `toArray` to be updated.

## ::previousPage()

Decrements the current `page`, causing `toArray` to be updated.

## ::%page : Number

Current page number, determined by `offset` and `limit`. Setting `page` automatically increases `offset`.

Since `toArray` depends on `offset`, setting `page` will also cause `toArray` to be updated.

## ::%offset : Number

Number of items skipped for the current `page`.

## ::%limit : Number

Items per page.

## ::%totalCount : Number

Total number of records covered by the `Paginator`.

## ::%pageCount : Number

Total number of pages covered by the `Paginator`, calculated from `totalCount` and `limit`.

## ::updateCache(offset, limit, items)

Registers `items` as the items from `offset` for `limit`. This should be called by `loadItemsForOffsetAndLimit` to inform the paginator of loaded records.

# /api/Extras/Batman.Paginator/Batman.ModelPaginator

`Batman.ModelPaginator` is a concrete implementation of `Batman.Paginator`. It may be used for paginating `Batman.Model` instances.

A `Batman.ModelPaginator` provides pagination by:

- Taking `model`, `limit`, `params`, and `page`/`offset` as input
- Exposing records by its `toArray` property (eg, `paginator.get('toArray')`)

## Using Batman.ModelPaginator

Add a paginator to your controller:

```coffee
class App.PostsController extends Batman.Controller
  index: -> # renders posts/index.html
    @set 'paginator, new Batman.ModelPaginator
      model: App.Post
      limit: 10
      page: 1
      params: {order: "created_at"}
```

Then, bind to it in your HTML:

```html
<ul>
  <li data-foreach-post='paginator.toArray'>
    <span data-bind='post.name'></span>
  </li>
</ul>
<button data-event-click='paginator.previousPage'>Prev</button>
<button data-event-click='paginator.nextPage'>    Next</button>
```

## ::constructor(options) : ModelPaginator

Besides the options passed to `Batman.Paginator`, you may also pass:

- `model`: A `Batman.Model` class whose records are paginated
- `params` : A plain JS object which will be used when loading items from the server

## ::loadItemsForOffsetAndLimit(offset, limit)

Loads records by calling `@model.load` with:

- any key/values passed as `@params`
- `offset` and `limit`

## ::.params : Object

A plain JavaScript object whose key-value pairs will be passed to `@model.load` when loading records.

## ::.model : Class

A `Batman.Model` subclass whose records are paginated by the `ModelPaginator`.


better docs for source maps

better docs for source maps

Source maps allow JavaScript runtimes to match running JavaScript back to
the original source code that corresponds to it. This can be minified
JavaScript, but in our case, we're concerned with mapping pretty-printed
JavaScript back to CoffeeScript.

In order to produce maps, we must keep track of positions (line number, column number)
that originated every node in the syntax tree, and be able to generate a
[map file](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit)
— which is a compact, VLQ-encoded representation of the JSON serialization
of this information — to write out alongside the generated JavaScript.

LineMap
-------

A **LineMap** object keeps track of information about original line and column
positions for a single line of output JavaScript code.
**SourceMaps** are implemented in terms of **LineMaps**.

    class LineMap
      constructor: (@line) ->
        @columns = []

      add: (column, [sourceLine, sourceColumn], options={}) ->
        return if @columns[column] and options.noReplace
        @columns[column] = {line: @line, column, sourceLine, sourceColumn}

      sourceLocation: (column) ->
        column-- until (mapping = @columns[column]) or (column <= 0)
        mapping and [mapping.sourceLine, mapping.sourceColumn]

SourceMap
---------

Maps locations in a single generated JavaScript file back to locations in
the original CoffeeScript source file.

This is intentionally agnostic towards how a source map might be represented on
disk. Once the compiler is ready to produce a "v3"-style source map, we can walk
through the arrays of line and column buffer to produce it.

    class SourceMap
      constructor: ->
        @lines = []

Adds a mapping to this SourceMap. `sourceLocation` and `generatedLocation`
are both `[line, column]` arrays. If `options.noReplace` is true, then if there
is already a mapping for the specified `line` and `column`, this will have no
effect.

      add: (sourceLocation, generatedLocation, options = {}) ->
        [line, column] = generatedLocation
        lineMap = (@lines[line] or= new LineMap(line))
        lineMap.add column, sourceLocation, options

Look up the original position of a given `line` and `column` in the generated
code.

      sourceLocation: ([line, column]) ->
        line-- until (lineMap = @lines[line]) or (line <= 0)
        lineMap and lineMap.sourceLocation column

V3 SourceMap Generation
-----------------------

Builds up a V3 source map, returning the generated JSON as a string.
`options.sourceRoot` may be used to specify the sourceRoot written to the source
map.  Also, `options.sourceFiles` and `options.generatedFile` may be passed to
set "sources" and "file", respectively.

      generate: (options = {}, code = null) ->
        writingline       = 0
        lastColumn        = 0
        lastSourceLine    = 0
        lastSourceColumn  = 0
        needComma         = no
        buffer            = ""

        for lineMap, lineNumber in @lines when lineMap
          for mapping in lineMap.columns when mapping
            while writingline < mapping.line
              lastColumn = 0
              needComma = no
              buffer += ";"
              writingline++

Write a comma if we've already written a segment on this line.

            if needComma
              buffer += ","
              needComma = no

Write the next segment. Segments can be 1, 4, or 5 values.  If just one, then it
is a generated column which doesn't match anything in the source code.

The starting column in the generated source, relative to any previous recorded
column for the current line:

            buffer += @encodeVlq mapping.column - lastColumn
            lastColumn = mapping.column

The index into the list of sources:

            buffer += @encodeVlq 0

The starting line in the original source, relative to the previous source line.

            buffer += @encodeVlq mapping.sourceLine - lastSourceLine
            if lastSourceLine isnt mapping.sourceLine
              lastSourceLine = mapping.sourceLine
              lastSourceColumn = 0

The starting column in the original source, relative to the previous column.

            buffer += @encodeVlq mapping.sourceColumn - lastSourceColumn
            lastSourceColumn = mapping.sourceColumn
            needComma = yes

Produce the canonical JSON object format for a "v3" source map.

        v3 =
          version:    3
          file:       options.generatedFile or ''
          sourceRoot: options.sourceRoot or ''
          sources:    options.sourceFiles or ['']
          names:      []
          mappings:   buffer

        v3.sourcesContent = [code] if options.inline

        JSON.stringify v3, null, 2

Base64 VLQ Encoding
-------------------

Note that SourceMap VLQ encoding is "backwards".  MIDI-style VLQ encoding puts
the most-significant-bit (MSB) from the original value into the MSB of the VLQ
encoded value (see [Wikipedia](http://en.wikipedia.org/wiki/File:Uintvar_coding.svg)).
SourceMap VLQ does things the other way around, with the least significat four
bits of the original value encoded into the first byte of the VLQ encoded value.

      VLQ_SHIFT            = 5
      VLQ_CONTINUATION_BIT = 1 << VLQ_SHIFT             # 0010 0000
      VLQ_VALUE_MASK       = VLQ_CONTINUATION_BIT - 1   # 0001 1111

      encodeVlq: (value) ->
        answer = ''

        # Least significant bit represents the sign.
        signBit = if value < 0 then 1 else 0

        # The next bits are the actual value.
        valueToEncode = (Math.abs(value) << 1) + signBit

        # Make sure we encode at least one character, even if valueToEncode is 0.
        while valueToEncode or not answer
          nextChunk = valueToEncode & VLQ_VALUE_MASK
          valueToEncode = valueToEncode >> VLQ_SHIFT
          nextChunk |= VLQ_CONTINUATION_BIT if valueToEncode
          answer += @encodeBase64 nextChunk

        answer

Regular Base64 Encoding
-----------------------

      BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

      encodeBase64: (value) ->
        BASE64_CHARS[value] or throw new Error "Cannot Base64 encode value: #{value}"

Our API for source maps is just the `SourceMap` class.

    module.exports = SourceMap

Source maps allow JavaScript runtimes to match running JavaScript back to
the original source code that corresponds to it. This can be minified
JavaScript, but in our case, we're concerned with mapping pretty-printed
JavaScript back to CoffeeScript.

In order to produce maps, we must keep track of positions (line number, column number)
that originated every node in the syntax tree, and be able to generate a
[map file](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit)
— which is a compact, VLQ-encoded representation of the JSON serialization
of this information — to write out alongside the generated JavaScript.

LineMap
-------

A **LineMap** object keeps track of information about original line and column
positions for a single line of output JavaScript code.
**SourceMaps** are implemented in terms of **LineMaps**.

    class LineMap
      constructor: (@line) ->
        @columns = []

      add: (column, [sourceLine, sourceColumn], options={}) ->
        return if @columns[column] and options.noReplace
        @columns[column] = {line: @line, column, sourceLine, sourceColumn}

      sourceLocation: (column) ->
        column-- until (mapping = @columns[column]) or (column <= 0)
        mapping and [mapping.sourceLine, mapping.sourceColumn]

SourceMap
---------

Maps locations in for a single generated JavaScript file back to locations in
the original CoffeeScript source file.

This is intentionally agnostic towards how a source map might be represented on
disk. Once the compiler is ready to produce a "v3"-style source map, we can walk
through the arrays of line and column buffer to produce it.

    class SourceMap
      constructor: ->
        @lines = []

Adds a mapping to this SourceMap. `sourceLocation` and `generatedLocation`
are both `[line, column]` arrays. If `options.noReplace` is true, then if there
is already a mapping for the specified `line` and `column`, this will have no
effect.

      add: (sourceLocation, generatedLocation, options = {}) ->
        [line, column] = generatedLocation
        lineMap = (@lines[line] or= new LineMap(line))
        lineMap.add column, sourceLocation, options

Look up the original position of a given `line` and `column` in the generated
code.

      sourceLocation: ([line, column]) ->
        line-- until (lineMap = @lines[line]) or (line <= 0)
        lineMap and lineMap.sourceLocation column

V3 SourceMap Generation
-----------------------

Builds up a V3 source map, returning the generated JSON as a string.
`options.sourceRoot` may be used to specify the sourceRoot written to the source
map.  Also, `options.sourceFiles` and `options.generatedFile` may be passed to
set "sources" and "file", respectively.

      generate: (options = {}, code = null) ->
        writingline       = 0
        lastColumn        = 0
        lastSourceLine    = 0
        lastSourceColumn  = 0
        needComma         = no
        buffer            = ""

        for lineMap, lineNumber in @lines when lineMap
          for mapping in lineMap.columns when mapping
            while writingline < mapping.line
              lastColumn = 0
              needComma = no
              buffer += ";"
              writingline++

Write a comma if we've already written a segment on this line.

            if needComma
              buffer += ","
              needComma = no

Write the next segment. Segments can be 1, 4, or 5 values.  If just one, then it
is a generated column which doesn't match anything in the source code.

The starting column in the generated source, relative to any previous recorded
column for the current line:

            buffer += @encodeVlq mapping.column - lastColumn
            lastColumn = mapping.column

The index into the list of sources:

            buffer += @encodeVlq 0

The starting line in the original source, relative to the previous source line.

            buffer += @encodeVlq mapping.sourceLine - lastSourceLine
            if lastSourceLine isnt mapping.sourceLine
              lastSourceLine = mapping.sourceLine
              lastSourceColumn = 0

The starting column in the original source, relative to the previous column.

            buffer += @encodeVlq mapping.sourceColumn - lastSourceColumn
            lastSourceColumn = mapping.sourceColumn
            needComma = yes

Produce the canonical JSON object format for a "v3" source map.

        v3 =
          version:    3
          file:       options.generatedFile or ''
          sourceRoot: options.sourceRoot or ''
          sources:    options.sourceFiles or ['']
          names:      []
          mappings:   buffer

        v3.sourcesContent = [code] if options.inline

        JSON.stringify v3, null, 2

Base64 VLQ Encoding
-------------------

Note that SourceMap VLQ encoding is "backwards".  MIDI-style VLQ encoding puts
the most-significant-bit (MSB) from the original value into the MSB of the VLQ
encoded value (see [Wikipedia](http://en.wikipedia.org/wiki/File:Uintvar_coding.svg)).
SourceMap VLQ does things the other way around, with the least significat four
bits of the original value encoded into the first byte of the VLQ encoded value.

      VLQ_SHIFT            = 5
      VLQ_CONTINUATION_BIT = 1 << VLQ_SHIFT             # 0010 0000
      VLQ_VALUE_MASK       = VLQ_CONTINUATION_BIT - 1   # 0001 1111

      encodeVlq: (value) ->
        answer = ''

        # Least significant bit represents the sign.
        signBit = if value < 0 then 1 else 0

        # The next bits are the actual value.
        valueToEncode = (Math.abs(value) << 1) + signBit

        # Make sure we encode at least one character, even if valueToEncode is 0.
        while valueToEncode or not answer
          nextChunk = valueToEncode & VLQ_VALUE_MASK
          valueToEncode = valueToEncode >> VLQ_SHIFT
          nextChunk |= VLQ_CONTINUATION_BIT if valueToEncode
          answer += @encodeBase64 nextChunk

        answer

Regular Base64 Encoding
-----------------------

      BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

      encodeBase64: (value) ->
        BASE64_CHARS[value] or throw new Error "Cannot Base64 encode value: #{value}"

Our API for source maps is just the `SourceMap` class.

    module.exports = SourceMap


keypress event for textarea

keypress event for textarea

# Form - Text

    exports.pkgmanRegister = (registrar) ->

#### Implements hook `shrubAngularDirective`.

      registrar.registerHook 'shrubAngularDirective', -> [
        ->

          scope: field: '=', form: '='

          link: (scope) ->

            scope.$watch 'field', (field) ->

              field.minLength ?= 0
              field.maxLength ?= Infinity
              field.pattern ?= /.*/
              field.model ?= 'field.value'

              field.syncModel scope

          template: '''

    <label
      data-ng-if="!!field.label"
      data-ng-bind="field.label"
    ></label>

    <textarea
      class="form-control"
      name="{{field.name}}"
      type="{{field.type}}"

      data-shrub-ui-attributes="field.attributes"
      data-ng-keypress="field.keyPress($event)"
      data-ng-model="field.value"
      data-ng-required="field.required"
      data-ng-minlength="{{field.minlength}}"
      data-ng-maxlength="{{field.maxlength}}"
      data-ng-pattern="field.pattern"
      data-ng-trim="{{field.trim}}"
    ></textarea>

    '''

      ]

      assignToElement = (element, value) -> element.val value

#### Implements hook `shrubFormWidgets`.

      registrar.registerHook 'shrubFormWidgets', ->

        widgets = []

        widgets.push

          type: 'textarea'
          assignToElement: assignToElement
          directive: 'shrub-form-widget-textarea'

        widgets

# Form - Text

    exports.pkgmanRegister = (registrar) ->

#### Implements hook `shrubAngularDirective`.

      registrar.registerHook 'shrubAngularDirective', -> [
        ->

          scope: field: '=', form: '='

          link: (scope) ->

            scope.$watch 'field', (field) ->

              field.minLength ?= 0
              field.maxLength ?= Infinity
              field.pattern ?= /.*/
              field.model ?= 'field.value'

              field.syncModel scope

          template: '''

    <label
      data-ng-if="!!field.label"
      data-ng-bind="field.label"
    ></label>

    <textarea
      class="form-control"
      name="{{field.name}}"
      type="{{field.type}}"

      data-shrub-ui-attributes="field.attributes"
      data-ng-model="field.value"
      data-ng-required="field.required"
      data-ng-minlength="{{field.minlength}}"
      data-ng-maxlength="{{field.maxlength}}"
      data-ng-pattern="field.pattern"
      data-ng-trim="{{field.trim}}"
    ></textarea>

    '''

      ]

      assignToElement = (element, value) -> element.val value

#### Implements hook `shrubFormWidgets`.

      registrar.registerHook 'shrubFormWidgets', ->

        widgets = []

        widgets.push

          type: 'textarea'
          assignToElement: assignToElement
          directive: 'shrub-form-widget-textarea'

        widgets