Use and parse return self

Use and parse return self

#Includes

	{EventEmitter} = require 'events'
	async = require 'async'
	util = require 'util'
	_ = require 'lodash'

	ElementFactory = require './element-factory'
	Phrase = require './phrase'
	InputOption = require './input-option'

#Lacona

	class Parser extends EventEmitter
		constructor: (@options) ->
			@phrases = []

			@middleware = []

			@understand require('./plugins/literal')
			@understand require('./plugins/freetext')
			@understand require('./plugins/integer')
			@understand require('./plugins/date')
			@understand require('./plugins/validator')
			@understand require('./plugins/suggester')
			@understand require('./plugins/list')

		phraseAccessor: (name) =>
			_.filter @phrases, (phrase) ->
				phrase.name is name or name in phrase.extends

###`understand`

`understand` takes a schema and scope, and defines a set of words for Lacona to understand

		understand: (options) ->
			scope = options.scope
			schema = if options.schema? then options.schema else options
			if not util.isArray(schema)
				schema = [schema]
			for phrase in schema
				elementFactory = new ElementFactory(scope, @)
				@phrases.push new Phrase(phrase, scope, elementFactory)
			return @

###`use`

`use` defines middleware. It must be passed a function that accepts 2 arguments, an inputOption,
and a callback that should be passed an error (or null) and a modulated inputOption. This will be passed
to the `data` event (or the next middleware) rather than the inputOption itself.

		use: (next) ->
			@middleware.push next
			return @

		parse: (inputText) ->
			input = new InputOption(inputText)

			async.each _.filter(@phrases, (item) -> item.sentence), (phrase, done) =>
				phrase.parse input, null, (option) =>
					if option.text is ''
						async.eachSeries @middleware, (call, done) =>
							call option, done
						, (err) =>
							return done(err) if err?
							@emit 'data', option
				, done

			, (err) =>
				if err?
					@emit 'error', err
				else
					@emit 'end'
			return @

	convertToHTML = (inputOption, done) ->
		html = '
'
		html += ''
		for match in inputOption.match
			html += "#{match.string}"
		html += ''
		for suggestion in inputOption.suggestion.words
			html += "#{suggestion.string}"
		html += ''
		for completion in inputOption.completion
			html += "#{completion.string}"
		html += '
'

		inputOption.html = html
		done()

	module.exports =
		Parser: Parser
		convertToHTML: convertToHTML

#Includes

	{EventEmitter} = require 'events'
	async = require 'async'
	util = require 'util'
	_ = require 'lodash'

	ElementFactory = require './element-factory'
	Phrase = require './phrase'
	InputOption = require './input-option'

#Lacona

	class Parser extends EventEmitter
		constructor: (@options) ->
			@phrases = []

			@middleware = []

			@understand require('./plugins/literal')
			@understand require('./plugins/freetext')
			@understand require('./plugins/integer')
			@understand require('./plugins/date')
			@understand require('./plugins/validator')
			# @understand require('./plugins/suggester')
			# @understand require('./plugins/list')

		phraseAccessor: (name) =>
			_.filter @phrases, (phrase) ->
				phrase.name is name or name in phrase.extends

###`understand`

`understand` takes a schema and scope, and defines a set of words for Lacona to understand

		understand: (options) ->
			scope = options.scope
			schema = if options.schema? then options.schema else options
			if not util.isArray(schema)
				schema = [schema]
			for phrase in schema
				elementFactory = new ElementFactory(scope, @)
				@phrases.push new Phrase(phrase, scope, elementFactory)
			return @

###`use`

`use` defines middleware. It must be passed a function that accepts 2 arguments, an inputOption,
and a callback that should be passed an error (or null) and a modulated inputOption. This will be passed
to the `data` event (or the next middleware) rather than the inputOption itself.

		use: (next) ->
			@middleware.push next

		parse: (inputText) ->
			input = new InputOption(inputText)

			async.each _.filter(@phrases, (item) -> item.sentence), (phrase, done) =>
				phrase.parse input, null, (option) =>
					if option.text is ''
						async.eachSeries @middleware, (call, done) =>
							call option, done
						, (err) =>
							return done(err) if err?
							@emit 'data', option
				, done

			, (err) =>
				if err?
					@emit 'error', err
				else
					@emit 'end'

	convertToHTML = (inputOption, done) ->
		html = '
'
		html += ''
		for match in inputOption.match
			html += "#{match.string}"
		html += ''
		for suggestion in inputOption.suggestion.words
			html += "#{suggestion.string}"
		html += ''
		for completion in inputOption.completion
			html += "#{completion.string}"
		html += '
'

		inputOption.html = html
		done()

	module.exports =
		Parser: Parser
		convertToHTML: convertToHTML


added annotations

added annotations

# CLASS: Component
* Extends: [Element][Element]

An interactive component.

    Event = require './event'
    localizeEventCoordinates = require '../helper/localize-event-coordinates'
    module.exports = class Component extends require './shape'

## CONSTRUCTOR
### new Component(args)
* Returns: [Component][Component]

Create a Component instance

      constructor: (args = {}) ->
        super

and register capturing and non-capturing validation listeners. Those will stop the
event propagation if the event **type** is not enabled.

        for name in ['grab', 'release', 'drag']
          do (name) =>
            @addListener name, ((e) -> e.stop() unless @events?[name]), yes
            @addListener name, ((e) -> e.stop() unless @events?[name]), no

Register capturing listeners. Those listeners can be extended in subclasses.

        for name in ['grab', 'release', 'drag']
          @addListener name, this["#{name}CaptureListener"], yes

---

## METHODS
### #mousemoveCaptureListener(event)
* Returns: [Component][Component]

Capture **mousemove** event passing throught this component

      mousemoveCaptureListener: (event) ->
        super
        $ = @___runtime

Reset component state.

        @state = null

If component is grabbed then set the state to **active**.

        if $.grab
          @state = 'active'

Create **drag** Event and broadcast it to this component if drag event is enabled,

          if @events?.drag
            @broadcastEvent $.dragEvent = new Event type:'drag',
              x:event.x, y:event.y, target:this

setting the drag offset.

              offsetX: event.x - ($.dragEvent?.x or $.grabEvent?.x or 0)
              offsetY: event.y - ($.dragEvent?.y or $.grabEvent?.y or 0)

Otherwise, set the state to the name of the first matching zone in order.

        else if zones = event.zones
          @state = (if zones.hover then 'hover' else if zones.normal then 'normal')

        return this

#### PARAMETERS
**event**
* Type: [Event][Event]

---

### #mouseupCaptureListener(event)
* Returns: [Component][Component]

Capture **mouseup** event passing throught this component

      mouseupCaptureListener: (event) ->
        super
        $ = @___runtime

Reset component state.

        @state = null

If component is grabbed then release it

        if $.grab
          $.grab = false

If release event is enabled then create **release** Event, save it
and deliver it to this component,

          if @events?.release
            @broadcastEvent $.releaseEvent = new Event type:'release',
              x:event.x, y:event.y, target:this

Update the **#state** to the first matching zone name in order

        if zones = event.zones
          @state = (if zones.hover then 'hover' else if zones.normal then 'normal')

        return this

#### PARAMETERS
**event**
* Type: [Event][Event]

---

### #mousedownListener(event)
* Returns: [Component][Component]

Receive **mousedown** event.

      mousedownListener: (event) ->
        super

If component is in active state and **grab** event is enabled then grab this component.

        if (@state is 'active') and @events?.grab
          ($ = @___runtime).grab = true

Create **grab** event and deliver it to this component.

          @broadcastEvent $.grabEvent = new Event type:'grab',
            x:event.x, y:event.y, target:this
        return this

#### PARAMETERS

---

### #dragCaptureListener(event)
* Returns: [Component][Component]

Capture **drag** events passing through this component

      dragCaptureListener: (event) ->

Save the event and localize event coordinates.

        @___runtime.dragEvent = event
        localizeEventCoordinates event, @origin
        return this

#### PARAMETERS
**event**
* Type: [Event][Event]

---

### #grabCaptureListener(event)
* Returns: [Component][Component]

Capture **grab** events passing through this component.

      grabCaptureListener: (event) ->

Save the event and localize event coordinates.

        @___runtime.grabEvent = event
        localizeEventCoordinates event, @origin
        return this

#### PARAMETERS
**event**
* Type: [Event][Event]

---

* Returns: [Component][Component]

Capture **release** events passing through this component.

      releaseCaptureListener: (event) ->

Save the event and localize event coordinates.

        @___runtime.releaseEvent = event
        localizeEventCoordinates event, @origin
        return this

#### PARAMETERS
**event**
* Type: [Event][Event]

---

* Returns: [Component][Component]

#### #dragListener(event)
* Returns: [Component][Component]

**drag** event receiver stub.

      dragListener: -> this

#### PARAMETERS
**event**
* Type: [Event][Event]

---

### #grabListener(event)
* Returns: [Component][Component]

**grab** event receiver stub.

      grabListener: -> this

#### PARAMETERS
**event**
* Type: [Event][Event]

---
### #releaseListener(event)
* Returns: [Component][Component]

**release** event receiver stub.

      releaseListener: -> this

#### PARAMETERS
**event**
* Type: [Event][Event]

# CLASS: Component

    Event = require './event'
    localizeEventCoordinates = require '../helper/localize-event-coordinates'

    module.exports = class Component extends require './shape'
      constructor: (args = {}) ->
        super
        for name in ['grab', 'release', 'drag']
          do (name) =>
            @addListener name, ((e) -> e.stop() unless @events?[name]), yes
            @addListener name, ((e) -> e.stop() unless @events?[name]), no

        for name in ['grab', 'release', 'drag']
          @addListener name, this["#{name}CaptureListener"], yes

      mousemoveCaptureListener: (event) ->
        super
        if @___runtime.grab
          @state =
          if zones = event.zones
            @state = (if zones.hover then 'hover' else if zones.normal then 'normal')

      mouseupCaptureListener: (event) ->
        super
        ($ = @___runtime).grab = false

        if $.grab
          $.grab = false
          @state = null
          if @events?.release
            @broadcastEvent $.releaseEvent = new Event type:'release',
              x:event.x, y:event.y, target:this

      mousemoveListener: (event) ->
        super
        $ = @___runtime
        if $.grab
          @state = 'active'
          if @events?.drag
            @broadcastEvent $.dragEvent = new Event type:'drag',
              x:event.x, y:event.y, target:this
              offsetX: event.x - ($.dragEvent?.x or $.grabEvent?.x or 0)
              offsetY: event.y - ($.dragEvent?.y or $.grabEvent?.y or 0)
        else
          @state = null
          if states = event.states
            @state = (if states.hover then 'hover' else if states.normal then 'normal')

        return this

      mousedownListener: (event) ->
        super
        ($ = @___runtime).grab = true
        if (@state is 'active') and @events?.grab
          @broadcastEvent $.grabEvent = new Event type:'grab',
            x:event.x, y:event.y, target:this
        return this

      mouseupListener: (event) ->
        super
        $ = @___runtime
        @state = null
        if zones = event.zones
          @state = (if zones.hover then 'hover' else if zones.normal then 'normal')
        if $.grab
          $.grab = false
          @state = null
          if states = event.states
            @state = (if states.hover then 'hover' else if states.normal then 'normal')

          @broadcastEvent $.grabEvent = new Event type:'release',
            x:event.x, y:event.y, target:this

        return this

      dragCaptureListener: (event) ->
        @___runtime.dragEvent = event
        localizeEventCoordinates event, @origin
        return this

      grabCaptureListener: (event) ->
        @___runtime.grabEvent = event
        localizeEventCoordinates event, @origin
        return this

      releaseCaptureListener: (event) ->
        @___runtime.releaseEvent = event
        localizeEventCoordinates event, @origin
        return this

      dragListener: -> this

      grabListener: -> this

      releaseListener: -> this


update docs

update docs

# /api/App Components/Batman.Model/Batman.Model Associations
batman.js associations are modeled after [ActiveRecord Associations](http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html). There are 3 types of assocations available on `Batman.Model`: [`hasMany`](/docs/api/batman.model_associations.html#class_function_hasmany), [`belongsTo`](/docs/api/batman.model_associations.html#class_function_belongsto), and [`hasOne`](/docs/api/batman.model_associations.html#class_function_hasone). batman.js also supports polymorphic associations through the use of [polymorphic-specific options](/docs/api/batman.model_associations.html#polymorphic_association_options).

To add associations to your models, declare them in your model definition. Association functions take a label (string) and options (Object). The label names the association and is used to provide smart defaults for several options. All available options are [detailed below](/docs/api/batman.model_associations.html#association_options).

For example:

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', inverseOf: 'parentItem', encoderKey: 'children'

class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', inverseOf: 'childItem'
```

Then, associated records will be available via accessors:

```coffeescript
  parent = new App.ParentItem
  child = new App.ChildItem

  child.set('parentItem', parent)
  child.get('parentItem') # => parent
```

or,

```coffeescript
  parent = new App.ParentItem
  child = new App.ChildItem
  secondChild = new App.ChildItem
  parent.get('childItems').add(child)
  parent.get('childItems').add(secondChild)
  parent.get('childItems') # => Batman.AssociationSet
  parent.get('childItems.length') # => 2
```

## @hasMany(label : string [, options : Object])
`hasMany` expresses a one-to-many relationship on a `Batman.Model`.

## @hasOne(label : string [, options : Object])
`hasOne` expresses a one-to-one relationship on a `Batman.Model` when this model contains the primary key (eg, `id`) and does not contain the foreign key. If this model contains the foreign key, use `belongsTo` instead.

## @belongsTo(label : string [, options : Object])
`belongsTo` expresses a one-to-one relationship on a `Batman.Model` when this model contains the foreign key (eg, `parent_id`). If the other model contains the foreign key, use `hasOne` instead. It often expresses inverse of a `hasMany` or `hasOne` association. You can declare this with the `inverseOf` option (see [options](/docs/api/batman.model_associations.html#association_options) below) so that both sides of the association are loaded from JSON.

## Batman.AssocationProxy

Association accessors won't always return a `Batman.AssociationSet` or `Batman.Model`. Generally they will return a `Batman.AssocationProxy` named after the association type, such as `Batman.BelongsToAssociationProxy` or `Batman.HasOneAssociationProxy`.

## ::load(callback : Function)
Called to load the associated record from storage, setting it as  [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target). If a callback is passed, it is called with two arguments: any error and the loaded record. Also, when this function finishes, it sets [`loaded`](/docs/api/batman.model_associations.html#prototype_accessor_loaded) to `true` and fires `loaded` on the record.

## ::toJSON() : Object
Returns a [stringifiable JavaScript object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#toJSON_behavior) for the target record, if the [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target) is present.

## ::%target
The associated record. Getting `target` does not implicitly call `load` on the association.

## ::%loaded
`true` or `false`, whether or not the record has been loaded from storage.

## ::fetchFromLocal()
This method is called by [`load`](/docs/api/batman.model_associations.html#prototype_function_load) to fetch the [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target) record(s). If this method returns a falsy value, then [`fetchFromRemote`](/docs/api/batman.model_associations.html#prototype_function_fetchfromremote) is called.  `Batman.AssocationProxy` subclasses must implement this method.

## ::fetchFromRemote([callback : Function])
If [`fetchFromLocal`](/docs/api/batman.model_associations.html#prototype_function_fetchfromlocal) returns a falsy value, this method is called by [`load`](/docs/api/batman.model_associations.html#prototype_function_load) to fetch the [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target) record(s). The `callback` is called with two arguments: any error and the fetched record(s). `Batman.AssocationProxy` subclasses must implement this method.

## Association Options

##### `primaryKey[= "id"] : string`
The primary key for the association.

##### `foreignKey[= "#{label}_id"] : string`
The foreign key for the association.

##### `saveInline[= false] : boolean`
If true, this model's attributes will be included in the associated model's JSON. This means that when an associated record is saved, this record's attributes will be included in the JSON.  (An alternative might be to include the associations' primary keys in the model's JSON with an [encoder](/docs/api/batman.model.html#class_function_encode).)

##### `autoload[= true] : boolean`
If `true`, batman.js will automatically call `load` when the associated records are accessed. This is useful in view bindings, where binding to the associated records will automatically cause them to be loaded.

##### `nestUrl[= false] : boolean`
If `true`, this model's URL will be nested under the associated model:

```coffeescript
class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', nestUrl: true

# ...

child = new ChildItem(parent_id: 1, id: 5)
child.url() # => 'parent_items/1/child_items/5'
```

`nestUrl` only applies if the model is persisted with `Batman.RestStorage` (or a subclass).

##### `name : string`
By default, batman.js checks for a model with the singular, camel-case name of association's `label` attached to `Batman.currentApp`. If the associated model's name is different from that, use `name` to specify it.

```coffeescript
class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem' # automatically finds App.ParentItem
  @belongsTo 'alternativeParentItem', name: 'ParentItem' # also finds App.ParentItem
```

##### `inverseOf : string`
The foreign association to set on load. If the associated model has an association with the same name as the `inverseOf` value, it will be populated when data is loaded from storage. For example:

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', saveInline: true, inverseOf: 'parentItem'

class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', inverseOf: 'childItems'
```

would allow:

```coffeescript
App.ParentItem.find 1, (err, parent) ->
  children = parent.get('childItems')
  children.get('first.parentItem') == parent # => true

App.ChildItem.find 5, (err, childItem) ->
  childItem.get('parentItem').load (err, parent) ->
    parent.get('childItems').has(childItem) # => true
```

##### `encoderKey[= label] : string`
Key that represents this association's records when in serialized form. For example,

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', encoderKey: 'children'
```

will correctly decode this JSON:

```javascript
{id: 1, children: [{ id: 5, parent_id: 1 }, {id: 6, parent_id: 1}]}
```

It will also encode the `childItems` as `children` (unless `saveInline` is set to `false`).

##### `namespace[= Batman.currentApp] : string`
batman.js expects to find a model with the given `name` on `Batman.currentApp`. If your model is defined elsewhere, use `namespace` to specify where the model is defined.

```coffeescript
class App.Admin.Person extends Batman.Model
  @belongsTo 'organization', namespace: App.Admin # finds App.Admin.Organization instead of App.Organization
```

## Polymorphic Association Options
batman.js also supports [polymorphic associations](http://guides.rubyonrails.org/association_basics.html#polymorphic-associations). For example:

```coffeescript
class App.Superpower extends Batman.Model
  @encode 'name'
  @belongsTo 'superpowerable', polymorphic: true

class App.Hero extends Batman.Model
  @hasMany 'superpowers', as: 'superpowerable', polymorphic: true

class App.Villain extends Batman.Model
  @hasMany 'superpowers', as: 'superpowerable', polymorphic: true
```
By default, attributes of the polymorphic association will be encoded according to the label. So, `hero.toJSON()` might return:

```javascript
{ id: 1,
  name: 'Superman',
  superpowers: [
    {id: 15, superpowerable_id: 1, superpowerable_type: 'hero', name: 'Super Strength'},
    {id: 16, superpowerable_id: 1, superpowerable_type: 'hero', name: 'Invincibility'},
  ]
}
```

##### `polymorphic[= false] : boolean`
Set to `true` when the association is [polymorphic](http://guides.rubyonrails.org/association_basics.html#polymorphic-associations).

##### `as : string`
Specifies the name of the polymorphic interface.

##### `foreignTypeKey[= "#{label}_type"] : string`
Specifies the field which contains the `type` for a polymorphic record.

##### `encodeForeignTypeKey[=true] : boolean`
Set to `true` when the `foreignTypeKey` should be included in the JSON of the record.

# /api/App Components/Batman.Model/Batman.Model Associations
batman.js associations are modeled after [ActiveRecord Associations](http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html). There are 3 types of assocations available on `Batman.Model`: [`hasMany`](/docs/api/batman.model_associations.html#class_function_hasmany), [`belongsTo`](/docs/api/batman.model_associations.html#class_function_belongsto), and [`hasOne`](/docs/api/batman.model_associations.html#class_function_hasone). batman.js also supports polymorphic associations through the use of [polymorphic-specific options](/docs/api/batman.model_associations.html#polymorphic_association_options).

To add associations to your models, declare them in your model definition. Association functions take a label (string) and options (Object). The label names the association and is used to provide smart defaults for several options. All available options are [detailed below](/docs/api/batman.model_associations.html#association_options).

For example:

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', inverseOf: 'parentItem', encoderKey: 'children'

class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', inverseOf: 'childItem'
```

Then, associated records will be available via accessors:

```coffeescript
  parent = new App.ParentItem
  child = new App.ChildItem

  child.set('parentItem', parent)
  child.get('parentItem') # => parent
```

or,

```coffeescript
  parent = new App.ParentItem
  child = new App.ChildItem
  secondChild = new App.ChildItem
  parent.get('childItems').add(child)
  parent.get('childItems').add(secondChild)
  parent.get('childItems') # => Batman.AssociationSet
  parent.get('childItems.length') # => 2
```

## @hasMany(label : string [, options : Object])
`hasMany` expresses a one-to-many relationship on a `Batman.Model`.

## @hasOne(label : string [, options : Object])
`hasOne` expresses a one-to-one relationship on a `Batman.Model` when this model contains the primary key (eg, `id`) and does not contain the foreign key. If this model contains the foreign key, use `belongsTo` instead.

## @belongsTo(label : string [, options : Object])
`belongsTo` expresses a one-to-one relationship on a `Batman.Model` when this model contains the foreign key (eg, `parent_id`). If the other model contains the foreign key, use `hasOne` instead. It often expresses inverse of a `hasMany` or `hasOne` association. You can declare this with the `inverseOf` option (see [options](/docs/api/batman.model_associations.html#association_options) below) so that both sides of the association are loaded from JSON.

## Batman.AssocationProxy

Association accessors won't always return a `Batman.AssociationSet` or `Batman.Model`. Generally they will return a `Batman.AssocationProxy` named after the association type, such as `Batman.BelongsToAssociationProxy` or `Batman.HasOneAssociationProxy`.

## ::load(callback : Function)
Called to load the associated record from storage, setting it as  [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target). If a callback is passed, it is called with two arguments: any error and the loaded record. Also, when this function finishes, it sets [`loaded`](/docs/api/batman.model_associations.html#prototype_accessor_loaded) to `true` and fires `loaded` on the record.

## ::toJSON() : Object
Returns a [stringifiable JavaScript object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#toJSON_behavior) for the target record, if the [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target) is present.

## ::%target
The associated record. Getting `target` does not implicitly call `load` on the association.

## ::%loaded
`true` or `false`, whether or not the record has been loaded from storage.

## ::fetchFromLocal()
This method is called by [`load`](/docs/api/batman.model_associations.html#prototype_function_load) to fetch the [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target) record(s). If this method returns a falsy value, then [`fetchFromRemote`](/docs/api/batman.model_associations.html#prototype_function_fetchfromremote) is called.  `Batman.AssocationProxy` subclasses must implement this method.

## ::fetchFromRemote([callback : Function])
If [`fetchFromLocal`](/docs/api/batman.model_associations.html#prototype_function_fetchfromlocal) returns a falsy value, this method is called by [`load`](/docs/api/batman.model_associations.html#prototype_function_load) to fetch the [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target) record(s). The `callback` is called with two arguments: any error and the fetched record(s). `Batman.AssocationProxy` subclasses must implement this method.

## Association Options

##### `primaryKey[= "id"] : string`
The primary key for the association.

##### `foreignKey[= "#{label}_id"] : string`
The foreign key for the association.

##### `saveInline[= true] : boolean`
If true, this model's attributes will be included in the associated model's JSON. This means that when an associated record is saved, this record's attributes will be included in the JSON.  (An alternative might be to include the associations' primary keys in the model's JSON with an [encoder](/docs/api/batman.model.html#class_function_encode).)

##### `autoload[= true] : boolean`
If `true`, batman.js will automatically call `load` when the associated records are accessed. This is useful in view bindings, where binding to the associated records will automatically cause them to be loaded.

##### `nestUrl[= false] : boolean`
If `true`, this model's URL will be nested under the associated model:

```coffeescript
class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', nestUrl: true

# ...

child = new ChildItem(parent_id: 1, id: 5)
child.url() # => 'parent_items/1/child_items/5'
```

`nestUrl` only applies if the model is persisted with `Batman.RestStorage` (or a subclass).

##### `name : string`
By default, batman.js checks for a model with the singular, camel-case name of association's `label` attached to `Batman.currentApp`. If the associated model's name is different from that, use `name` to specify it.

```coffeescript
class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem' # automatically finds App.ParentItem
  @belongsTo 'alternativeParentItem', name: 'ParentItem' # also finds App.ParentItem
```

##### `inverseOf : string`
The foreign association to set on load. If the associated model has an association with the same name as the `inverseOf` value, it will be populated when data is loaded from storage. For example:

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', saveInline: true, inverseOf: 'parentItem'

class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', inverseOf: 'childItems'
```

would allow:

```coffeescript
App.ParentItem.find 1, (err, parent) ->
  children = parent.get('childItems')
  children.get('first.parentItem') == parent # => true

App.ChildItem.find 5, (err, childItem) ->
  childItem.get('parentItem').load (err, parent) ->
    parent.get('childItems').has(childItem) # => true
```

##### `encoderKey[= label] : string`
Key that represents this association's records when in serialized form. For example,

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', encoderKey: 'children'
```

will correctly decode this JSON:

```javascript
{id: 1, children: [{ id: 5, parent_id: 1 }, {id: 6, parent_id: 1}]}
```

It will also encode the `childItems` as `children` (unless `saveInline` is set to `false`).

##### `namespace[= Batman.currentApp] : string`
batman.js expects to find a model with the given `name` on `Batman.currentApp`. If your model is defined elsewhere, use `namespace` to specify where the model is defined.

```coffeescript
class App.Admin.Person extends Batman.Model
  @belongsTo 'organization', namespace: App.Admin # finds App.Admin.Organization instead of App.Organization
```

## Polymorphic Association Options
batman.js also supports [polymorphic associations](http://guides.rubyonrails.org/association_basics.html#polymorphic-associations). For example:

```coffeescript
class App.Superpower extends Batman.Model
  @encode 'name'
  @belongsTo 'superpowerable', polymorphic: true

class App.Hero extends Batman.Model
  @hasMany 'superpowers', as: 'superpowerable', polymorphic: true

class App.Villain extends Batman.Model
  @hasMany 'superpowers', as: 'superpowerable', polymorphic: true
```
By default, attributes of the polymorphic association will be encoded according to the label. So, `hero.toJSON()` might return:

```javascript
{ id: 1,
  name: 'Superman',
  superpowers: [
    {id: 15, superpowerable_id: 1, superpowerable_type: 'hero', name: 'Super Strength'},
    {id: 16, superpowerable_id: 1, superpowerable_type: 'hero', name: 'Invincibility'},
  ]
}
```

##### `polymorphic[= false] : boolean`
Set to `true` when the association is [polymorphic](http://guides.rubyonrails.org/association_basics.html#polymorphic-associations).

##### `as : string`
Specifies the name of the polymorphic interface.

##### `foreignTypeKey[= "#{label}_type"] : string`
Specifies the field which contains the `type` for a polymorphic record.

##### `encodeForeignTypeKey[=true] : boolean`
Set to `true` when the `foreignTypeKey` should be included in the JSON of the record.


Move font config into renderer

Move font config into renderer

    PngRenderer = require './png_renderer'

    class PngStepCount extends PngRenderer

      do_render: (path) =>
        ctx    = PngRenderer.ctx
        width  = @config.width
        height = @config.height

        for step, i in path
          ctx.font      = "#{Math.floor height * 0.25}pt Arial"
          ctx.textAlign = @config.step_count.text_align
          ctx.fillStyle = @config.step_count.text_color

          x = (width  * 0.5) + (width  * step.col)
          y = (height * 0.5) + (height * step.row)

          ctx.beginPath()
          ctx.fillText i, x, y

    module.exports = PngStepCount

    PngRenderer = require './png_renderer'

    class PngStepCount extends PngRenderer

      do_render: (path) =>
        ctx    = PngRenderer.ctx
        width  = @config.width
        height = @config.height

        for step, i in path
          ctx.font      = @config.step_count.text_font height
          ctx.textAlign = @config.step_count.text_align
          ctx.fillStyle = @config.step_count.text_color

          x = (width  * 0.5) + (width  * step.col)
          y = (height * 0.5) + (height * step.row)

          ctx.beginPath()
          ctx.fillText i, x, y

    module.exports = PngStepCount


added localizer to capturing listeners

added localizer to capturing listeners

# CLASS: Element
* Extends: [Evented][Evented]
* Parent: [Index][Parent]

A visual element.

---

    module.exports = class Element extends require 'ecl/dist/evented'

## CONSTRUCTOR

### new Element()

Creates an Element instance.

      constructor: ->
        super

Register validating listeners for each **type** from the list.

        for type in ['mousemove', 'mousedown', 'mouseup']

Localize the **type** variable.

          do (type) =>

Add capturing listener which will cancel and stop the event
if the event type is not enabled.

            @addListener type:type, capture:yes, listener: (event) ->
              event.cancel().stop() unless @events?[type]

Add normal listener which will cancel and stop the event
if the event type is not enabled.

            @addListener type:type, capture:no, listener: (event) ->
              event.cancel().stop() unless @events?[type]

Register extendable listeners for each **type** from the list.

        for type in ['mousemove', 'mousedown', 'mouseup']

Add capturing extendable listener

          @addListener type, this["#{type}CaptureListener"], yes

Add normal extendable listener

          @addListener type, this["#{type}Listener"], no

#### PARAMETERS
* **args** - named arguments

---

## PROPERTIES

---

## METHODS
### #localizeEventCoordinates(event) ->
* Returns: [Element][Element]

Helper method, to localize event coordinates.

      localizeEventCoordinates: (event) ->
        if event

If event already has localized **x**, use it instead of absolute **x**

          x = (if event.localX? then event.localX else event.x)
          event.localX = x - (@origin?.x or 0)

If event already has localized **y**, use it instead of absolute **y**

          y = (if event.localY? then event.localY else event.y)
          event.localY = y - (origin?.y or 0)

        return this
---

### #getEventRegions(event)
* Returns: [Object][Object] - named set of matching regions

Helper method, to get element regions that match the event.

      getEventRegions: (event) ->

Proceed only if event coordinates are localized

        if event and (x = event.localX)? and (y = event.localY)?
          result = {}

Walk through the element regions

          for name, $ of @regions

and add the region to the result if event localized coordinates are within
the region rectangle.

            if $[0] <= x <= ($[0] + $[2]) and $[1] <= y <= ($[1] + $[3])
              result[name] = $

        return result

---

## LISTENERS
### #mousemoveCaptureListener(event)
* Returns: [Element][Element]

Extendable capturing **mousemove** listener

      mousemoveCaptureListener: (event) ->

Store the event in the runtime for later and localize event coordinates

        @___runtime.mousemoveEvent = event
        @localizeEventCoordinates event

        return this

---

### #mousedownCaptureListener(event)
* Returns: [Element][Element]

Extendable capturing **mousedown** listener

      mousedownCaptureListener: (event) ->

Store the event in the runtime for later and localize event coordinates

        @___runtime.mousedownEvent = event
        @localizeEventCoordinates event

        return this

---

### #mouseupCaptureListener(event)
* Returns: [Element][Element]

Extendable capturing **mouseup** listener

      mouseupCaptureListener: (event) ->

Store the event in the runtime for later and localize event coordinates

        @___runtime.mouseupEvent = event
        @localizeEventCoordinates event

        return this

---

### #mousemoveListener(event)
* Returns: [Element][Element]

Extendable **mousemove** listener

      mousemoveListener: -> this

---

### #mousedownListener(event)
* Returns: [Element][Element]

Extendable **mousemove** listener

      mousedownListener: -> this

---

### #mouseupListener(event)
* Returns: [Element][Element]

Extendable **mousemove** listener

      mouseupListener: -> this

[Element]: ./element

[Parent]: ./index.litcoffee
[Evented]: https://nhzio.github.com/ecl/evented.html

# CLASS: Element
* Extends: [Evented][Evented]
* Parent: [Index][Parent]

A visual element.

---

    module.exports = class Element extends require 'ecl/dist/evented'

## CONSTRUCTOR

### new Element()

Creates an Element instance.

      constructor: ->
        super

Register validating listeners for each **type** from the list.

        for type in ['mousemove', 'mousedown', 'mouseup']

Localize the **type** variable.

          do (type) =>

Add capturing listener which will cancel and stop the event
if the event type is not enabled.

            @addListener type:type, capture:yes, listener: (event) ->
              event.cancel().stop() unless @events?[type]

Add normal listener which will cancel and stop the event
if the event type is not enabled.

            @addListener type:type, capture:no, listener: (event) ->
              event.cancel().stop() unless @events?[type]

Register extendable listeners for each **type** from the list.

        for type in ['mousemove', 'mousedown', 'mouseup']

Add capturing extendable listener

          @addListener type, this["#{type}CaptureListener"], yes

Add normal extendable listener

          @addListener type, this["#{type}Listener"], no

#### PARAMETERS
* **args** - named arguments

---

## PROPERTIES

---

## METHODS
### #localizeEventCoordinates(event) ->
* Returns: [Element][Element]

Helper method, to localize event coordinates.

      localizeEventCoordinates: (event) ->
        if event

If event already has localized **x**, use it instead of absolute **x**

          x = (if event.localX? then event.localX else event.x)
          event.localX = x - (@origin?.x or 0)

If event already has localized **y**, use it instead of absolute **y**

          y = (if event.localY? then event.localY else event.y)
          event.localY = y - (origin?.y or 0)

        return this
---

### #getEventRegions(event)
* Returns: [Object][Object] - named set of matching regions

Helper method, to get element regions that match the event.

      getEventRegions: (event) ->

Proceed only if event coordinates are localized

        if event and (x = event.localX)? and (y = event.localY)?
          result = {}

Walk through the element regions

          for name, $ of @regions

and add the region to the result if event localized coordinates are within
the region rectangle.

            if $[0] <= x <= ($[0] + $[2]) and $[1] <= y <= ($[1] + $[3])
              result[name] = $

        return result

---

## LISTENERS
### #mousemoveCaptureListener(event)
* Returns: [Element][Element]

Extendable capturing **mousemove** listener

      mousemoveCaptureListener: (event) ->

Store the event in the runtime for later

        @___runtime.mousemoveEvent = event
        return this

---

### #mousedownCaptureListener(event)
* Returns: [Element][Element]

Extendable capturing **mousedown** listener

      mousedownCaptureListener: (event) ->

Store the event in the runtime for later

        @___runtime.mousedownEvent = event
        return this

---

### #mouseupCaptureListener(event)
* Returns: [Element][Element]

Extendable capturing **mouseup** listener

      mouseupCaptureListener: (event) ->

Store the event in the runtime for later

        @___runtime.mouseupEvent = event
        return this

---

### #mousemoveListener(event)
* Returns: [Element][Element]

Extendable **mousemove** listener

      mousemoveListener: -> this

---

### #mousedownListener(event)
* Returns: [Element][Element]

Extendable **mousemove** listener

      mousedownListener: -> this

---

### #mouseupListener(event)
* Returns: [Element][Element]

Extendable **mousemove** listener

      mouseupListener: -> this

[Element]: ./element

[Parent]: ./index.litcoffee
[Evented]: https://nhzio.github.com/ecl/evented.html


- Clean-up of WrappedModule

- Clean-up of WrappedModule

    vm = require "vm"
    path = require "path"
    _ = require "underscore"
    Membrane = require "./membrane"

    class WrappedModule

        constructor: (@libName, @modulePaths, @policyObj) ->
            @modModule = (require "module")
            @fileName = @modModule._findPath @libName, @modulePaths
            @requestLib = @fileName || @libName
            @builtIn = @requestLib.indexOf(".js") == -1
            @pathName = path.dirname @fileName

        load: (requireFunc = @membranedRequire) ->
            throw new Error "`require` must be a function" if typeof requireFunc != "function"
            module.paths = [@pathName].concat(@modModule._nodeModulePaths(@pathName))

            if @builtIn
                r = require @requestLib
            else
                wrappedMod = new @modModule(@libName, this)
                wrappedMod.require = requireFunc
                wrappedMod.load @requestLib
                r = wrappedMod.exports

Return a membraned variant of the public API interface.

            return r if not @policyObj
            return new Membrane(r, @policyObj, @requestLib) if (typeof r) == "function"
            return @wrapObjectWithMembrane(@requestLib.replace(".js",""), r)

        membranedRequire: (libName) =>
            mod = new WrappedModule libName, module.paths, @policyObj

            return require(libName) if mod.builtIn or not @policyObj?.wrapWithMembrane?(libName)

Lets load the new `Module` for the requested library.

            return mod.load()

The last step is to create a wrapper function that will carefully wrap each
exported API call within a membrane.

            @wrapObjectWithMembrane(libName, libexports)

        wrapObjectWithMembrane: (libName, obj) ->
            _.object(_.map obj, @buildMembraneWrapper libName)

        buildMembraneWrapper: (libName) =>
            (propObj, propName) => [propName, new Membrane(propObj, @policyObj, "#{libName}.#{propName}")]

    module.exports = WrappedModule

    vm = require "vm"
    path = require "path"
    _ = require "underscore"
    Membrane = require "./membrane"
    Require = require

    class WrappedModule

        constructor: (@libName, @modulePaths, @policyObj) ->
            @modModule = (require "module")
            @module = new  @modModule(@libName, this)
            @fileName = @modModule._findPath @libName, @modulePaths
            @pathName = path.dirname @fileName

        load: (requireFunc = @membranedRequire) ->
            throw new Error "`require` must be a function" if typeof requireFunc != "function"
            module.paths = [@pathName].concat(@modModule._nodeModulePaths(@pathName))
            @module.require = requireFunc
            @module.load @fileName
            r = @module.exports

Return a membraned variant of the public API interface.

            return r if not @policyObj
            return new Membrane(r, @policyObj, r.toString()) if (typeof r) == "function"
            return @wrapObjectWithMembrane(@fileName.replace(".js",""), r) if (typeof r) == "object"
            throw new Error "unimplemented case in #{__filename}"

        membranedRequire: (libName) =>
            mod = new WrappedModule libName, module.paths, @policyObj
            if not mod.fileName or @policyObj?.skip?(libName)
                libexports = Require libName
            else

Lets load the new `Module` for the requested library.

                libexports = mod.load @membranedRequire

If the library is only used within the (outer) membrane, i.e., it is not
referenced in the policy, we return immediately.

            return libexports unless @policyObj?.mustWrap?(libName)

The last step is to create a wrapper function that will carefully wrap each
exported API call within a membrane.

            @wrapObjectWithMembrane(libName, libexports)

        wrapObjectWithMembrane: (libName, obj) ->
            _.object(_.map obj, @buildMembraneWrapper libName)

        buildMembraneWrapper: (libName) =>
            (propObj, propName) => [propName, new Membrane(propObj, @policyObj, "#{libName}.#{propName}")]

    module.exports = WrappedModule


releaseCaptureListener is ready

releaseCaptureListener is ready

# TEST CLASS: Component
* Parent: [Index][Parent]

---

    should = require 'should'
    module.exports = (Component, name='Component') ->

## CONSTRUCTOR

      describe name, ->
        it 'should be a class', -> Component.should.be.a.class

        describe '#constructor(args)', ->
          it 'should return an instance of Component', ->
            (new Component).should.be.an.instanceof Component

---

## LISTENERS

Mousemove capturing listener

      describe '#mousemoveCaptureListener', ->
        it 'should return the component', ->
          (component = new Component)
            .mousemoveCaptureListener()
            .should.be.equal component

        it 'should set the state to active if component is grabbed', ->
          component = new Component
          component.___runtime.grab = true
          component.state = null
          component.mousemoveCaptureListener({})
          component.state.should.be.equal 'active'

        it 'should broadcast drag event with drag offset', (done) ->
          component = new Component events:drag:true
          component.___runtime.grab = true
          component.___runtime.grabEvent = x:10, y:10
          component.broadcastEvent = (event) ->
            event.offsetX.should.be.equal 10
            event.offsetY.should.be.equal 5
            done()
          component.mousemoveCaptureListener x:20, y:15

        it 'should broadcast drag event with drag offset using previous drag', (done) ->
          component = new Component events:drag:true
          component.___runtime.grab = true
          component.___runtime.dragEvent = x:10, y:10
          component.broadcastEvent = (event) ->
            event.offsetX.should.be.equal 10
            event.offsetY.should.be.equal 5
            done()
          component.mousemoveCaptureListener x:20, y:15

        it 'should set the component state to hover', ->
          component = new Component
            origin  : x:0, y:0
            regions : hover: [0,0,1,1]
          component.mousemoveCaptureListener x:0.5, y:0.5
          component.state.should.be.equal 'hover'

        it 'should set the component state to hover', ->
          component = new Component
            origin  : x:0, y:0
            regions : normal: [0,0,1,1]
          component.mousemoveCaptureListener x:0.5, y:0.5
          component.state.should.be.equal 'normal'

        it 'should set the component state to hover preceeding normal', ->
          component = new Component
            origin  : x:0, y:0
            regions : normal: [0,0,1,1], hover: [0,0,1,1]
          component.mousemoveCaptureListener x:0.5, y:0.5
          component.state.should.be.equal 'hover'

Drag capturing listener

      describe '#dragCaptureListener', ->
        it 'should return the component', ->
          (component = new Component)
            .mousemoveCaptureListener()
            .should.be.equal component

        it 'should save the event in #___runtime', ->
          (component = new Component)
            .dragCaptureListener 'test'
            .___runtime.dragEvent.should.be.equal 'test'

        it 'should localize the event coordinates', ->
          (component = new Component origin: x:10, y:25)
            .dragCaptureListener (event = x:20, y:30)

          event.localX.should.be.equal 10
          event.localY.should.be.equal 5

Grab capturing listener

      describe '#grabCaptureListener', ->
        it 'should return the component', ->
          (component = new Component)
            .grabCaptureListener()
            .should.be.equal component

        it 'should save the event in #___runtime', ->
          (component = new Component)
            .grabCaptureListener 'test'
            .___runtime.grabEvent.should.be.equal 'test'

        it 'should localize the event coordinates', ->
          (component = new Component origin: x:10, y:25)
            .grabCaptureListener (event = x:20, y:30)

          event.localX.should.be.equal 10
          event.localY.should.be.equal 5

Release capturing listener

      describe '#releaseCaptureListener', ->
        it 'should return the component', ->
          (component = new Component)
            .releaseCaptureListener()
            .should.be.equal component

        it 'should save the event in #___runtime', ->
          (component = new Component)
            .releaseCaptureListener 'test'
            .___runtime.releaseEvent.should.be.equal 'test'

        it 'should localize the event coordinates', ->
          (component = new Component origin: x:10, y:25)
            .releaseCaptureListener (event = x:20, y:30)

          event.localX.should.be.equal 10
          event.localY.should.be.equal 5

Mousedown listener

      describe '#mousedownListener', ->
        it 'should return the component', ->
          (component = new Component)
            .mousedownListener()
            .should.be.equal component

        it 'should set grab flag in #___runtime', ->
          (component = new Component state:'active', events:grab:true)
            .mousedownListener {}
            .___runtime.grab.should.be.true

Drag listener

      describe '#dragListener', ->
        it 'should return the component', ->
          (component = new Component)
            .dragListener()
            .should.be.equal component

Grab listener

      describe '#grabListener', ->
        it 'should return the component', ->
          (component = new Component)
            .grabListener()
            .should.be.equal component

Release listener

      describe '#releaseListener', ->
        it 'should return the component', ->
          (component = new Component)
            .releaseListener()
            .should.be.equal component

[Component#constructor]: ../component.litcoffee#constructor
[Parent]: ./index.litcoffee

# TEST CLASS: Component
* Parent: [Index][Parent]

---

    should = require 'should'
    module.exports = (Component, name='Component') ->

## CONSTRUCTOR

      describe name, ->
        it 'should be a class', -> Component.should.be.a.class

        describe '#constructor(args)', ->
          it 'should return an instance of Component', ->
            (new Component).should.be.an.instanceof Component

---

## LISTENERS

Mousemove capturing listener

      describe '#mousemoveCaptureListener', ->
        it 'should return the component', ->
          (component = new Component)
            .mousemoveCaptureListener()
            .should.be.equal component

        it 'should set the state to active if component is grabbed', ->
          component = new Component
          component.___runtime.grab = true
          component.state = null
          component.mousemoveCaptureListener({})
          component.state.should.be.equal 'active'

        it 'should broadcast drag event with drag offset', (done) ->
          component = new Component events:drag:true
          component.___runtime.grab = true
          component.___runtime.grabEvent = x:10, y:10
          component.broadcastEvent = (event) ->
            event.offsetX.should.be.equal 10
            event.offsetY.should.be.equal 5
            done()
          component.mousemoveCaptureListener x:20, y:15

        it 'should broadcast drag event with drag offset using previous drag', (done) ->
          component = new Component events:drag:true
          component.___runtime.grab = true
          component.___runtime.dragEvent = x:10, y:10
          component.broadcastEvent = (event) ->
            event.offsetX.should.be.equal 10
            event.offsetY.should.be.equal 5
            done()
          component.mousemoveCaptureListener x:20, y:15

        it 'should set the component state to hover', ->
          component = new Component
            origin  : x:0, y:0
            regions : hover: [0,0,1,1]
          component.mousemoveCaptureListener x:0.5, y:0.5
          component.state.should.be.equal 'hover'

        it 'should set the component state to hover', ->
          component = new Component
            origin  : x:0, y:0
            regions : normal: [0,0,1,1]
          component.mousemoveCaptureListener x:0.5, y:0.5
          component.state.should.be.equal 'normal'

        it 'should set the component state to hover preceeding normal', ->
          component = new Component
            origin  : x:0, y:0
            regions : normal: [0,0,1,1], hover: [0,0,1,1]
          component.mousemoveCaptureListener x:0.5, y:0.5
          component.state.should.be.equal 'hover'

Drag capturing listener

      describe '#dragCaptureListener', ->
        it 'should return the component', ->
          (component = new Component)
            .mousemoveCaptureListener()
            .should.be.equal component

        it 'should save the event in #___runtime', ->
          (component = new Component)
            .dragCaptureListener 'test'
            .___runtime.dragEvent.should.be.equal 'test'

        it 'should localize the event coordinates', ->
          (component = new Component origin: x:10, y:15)
            .dragCaptureListener (event = x:20, y:30)

          event.localX.should.be.equal 10
          event.localY.should.be.equal 15

Grab capturing listener

      describe '#grabCaptureListener', ->
        it 'should return the component', ->
          (component = new Component)
            .grabCaptureListener()
            .should.be.equal component

Release capturing listener

      describe '#releaseCaptureListener', ->
        it 'should return the component', ->
          (component = new Component)
            .releaseCaptureListener()
            .should.be.equal component

Mousedown listener

      describe '#mousedownListener', ->
        it 'should return the component', ->
          (component = new Component)
            .mousedownListener()
            .should.be.equal component

        it 'should set grab flag in #___runtime', ->
          (component = new Component state:'active', events:grab:true)
            .mousedownListener {}
            .___runtime.grab.should.be.true

Drag listener

      describe '#dragListener', ->
        it 'should return the component', ->
          (component = new Component)
            .dragListener()
            .should.be.equal component

Grab listener

      describe '#grabListener', ->
        it 'should return the component', ->
          (component = new Component)
            .grabListener()
            .should.be.equal component

Release listener

      describe '#releaseListener', ->
        it 'should return the component', ->
          (component = new Component)
            .releaseListener()
            .should.be.equal component

[Component#constructor]: ../component.litcoffee#constructor
[Parent]: ./index.litcoffee


Nuke the firepad logo

Nuke the firepad logo

Site Initialisation
===================

Firstly, we put up a container for bits published by the various components.

    window.Happiness = {}

We defer all core initialisation until post-pageload.

    $ ->

Editor Setup
------------

The first thing we do as part of init is prepare the code window for editing.

      Happiness.EditWindow = ace.edit "editor"
      Happiness.EditWindow.setTheme "ace/theme/textmate"
      Happiness.EditWindow.getSession().setMode "ace/mode/python"

Let's get rid of that obnoxious logo while we're at it.

      $('.powered-by-firepad').remove()

Site Initialisation
===================

Firstly, we put up a container for bits published by the various components.

    window.Happiness = {}

We defer all core initialisation until post-pageload.

    $ ->

Editor Setup
------------

The first thing we do as part of init is prepare the code window for editing.

      editor = ace.edit "editor"
      editor.setTheme "ace/theme/textmate"
      editor.getSession().setMode "ace/mode/python"


increase ttl for queue keepalive

increase ttl for queue keepalive

# Super secret queue methods

    @QueueMethods =
      popAndServeNextTicket: ->

Move the current connection to the processed queue

TODO: get postID

        queueMeta = QueueMeta.findOne()

Update object, extended at various point for updating the QueueMeta in one swoop

        update =
          $set: {}

If `theOnlyConnectionAllowedIn` is set to something, check if the connection
has expired and process the connection if it has.

        if queueMeta.theOnlyConnectionAllowedIn isnt undefined

          previousConnection = queueMeta.theOnlyConnectionAllowedIn
          previousConnectionDidntPosted = not queueMeta.hasCurrentConnectionPosted

Return if timeCurrentTicketExpires is in the future (hasn't expired)

          hasntExpired = queueMeta.timeCurrentTicketExpires > moment.utc().toDate()
          return if hasntExpired

Okay then, the current connection has expired, time to get bumped.
Insert the processed connection into the ProcessedQueue

          try

Calculate how long the connection had to wait in line.

            waitTimeSeconds = moment.utc().diff (moment.utc queueMeta.theOnlyConnectionAllowedIn.timeEnqueued), 'seconds'

Make the processed object.

            processed =
              connection: queueMeta.theOnlyConnectionAllowedIn
              waitTimeSeconds: waitTimeSeconds

Insert the processed connection to `QueueProcessed`

            QueueProcessed.insert processed
          catch err
            console.log err

Remove the connection from the `Queue`

          criteria = _id: queueMeta.currentlyServingQueueId
          Queue.remove criteria

Update `QueueMeta` stats and ticket number.

          try
            totalWaitTimeSeconds = queueMeta.totalWaitTimeSeconds + waitTimeSeconds
            currentlyServingTicketNumber = queueMeta.currentlyServingTicketNumber + 1
            _.extend update.$set,
              currentlyServingTicketNumber: currentlyServingTicketNumber
              hasCurrentConnectionPosted: no
              totalWaitTimeSeconds: totalWaitTimeSeconds
          catch err
            console.log err

Lookup the lowest ticket # waiting in the `Queue`

        nextConnection = Queue.findOne {}, { sort: { 'ticketNumber': 1 } }

Set the allowed connection and expireTime if one exists

If there is a nextConnection (i.e. someone waiting in line), then serve them.
Otherwise clear out theOnlyConnectionAllowedIn.

        if nextConnection?
          timeCurrentTicketExpires = moment.utc()
          timeCurrentTicketExpires.add 1, 'minutes'
          _.extend update.$set,
            theOnlyConnectionAllowedIn: nextConnection
            timeCurrentTicketExpires: timeCurrentTicketExpires.toDate()
            currentlyServingTicketNumber: nextConnection.ticketNumber
            currentlyServingQueueId: nextConnection._id

If there is no nextConnection, unset theOnlyConnectionAllowedIn.
Note, fake data is filled in to pass schema, even though we're $unset'ing

        else
          update.$unset = theOnlyConnectionAllowedIn: ""

        criteria = _id: queueMeta._id

Delete `update.$set` if it's empty

        if _.isEmpty update.$set
          delete update.$set

If `update` isn't empty, update!

        if not _.isEmpty update
          QueueMeta.update criteria, update

TODO: keep it DRY; logic isn't exactly shared and want to keep update atomic to
avoid extraneous DDP messages.

## Disconnect dead connections, remove from queue

      cleanUpDeadConnections: ->

A connection is dead if keepAlive > 5 minutes ago

        timeFiveMinutesAgoUtc = moment.utc().subtract('5', 'minutes').toDate()
        criteria =
          timeKeepAlive:
            $lt: timeFiveMinutesAgoUtc

        deadQueue = Queue.find criteria
        deadQueue.forEach (queue) ->
          criteria =
            _id: queue._id
          Queue.remove criteria

Calculate how long the connection had to wait in line.

          waitTimeSeconds = moment.utc().diff (moment.utc queue.timeEnqueued), 'seconds'

Make the processed object.

          processed =
            connection: queue
            waitTimeSeconds: waitTimeSeconds
            diconnect: yes
          QueueProcessed.insert processed

          queueMeta = QueueMeta.findOne()

          totalWaitTimeSeconds = queueMeta.totalWaitTimeSeconds + waitTimeSeconds

          criteria =
            _id: queueMeta._id
          action =
            $set:
              totalWaitTimeSeconds: totalWaitTimeSeconds
          QueueMeta.update criteria, action

# Super secret queue methods

    @QueueMethods =
      popAndServeNextTicket: ->

Move the current connection to the processed queue

TODO: get postID

        queueMeta = QueueMeta.findOne()

Update object, extended at various point for updating the QueueMeta in one swoop

        update =
          $set: {}

If `theOnlyConnectionAllowedIn` is set to something, check if the connection
has expired and process the connection if it has.

        if queueMeta.theOnlyConnectionAllowedIn isnt undefined

          previousConnection = queueMeta.theOnlyConnectionAllowedIn
          previousConnectionDidntPosted = not queueMeta.hasCurrentConnectionPosted

Return if timeCurrentTicketExpires is in the future (hasn't expired)

          hasntExpired = queueMeta.timeCurrentTicketExpires > moment.utc().toDate()
          return if hasntExpired

Okay then, the current connection has expired, time to get bumped.
Insert the processed connection into the ProcessedQueue

          try

Calculate how long the connection had to wait in line.

            waitTimeSeconds = moment.utc().diff (moment.utc queueMeta.theOnlyConnectionAllowedIn.timeEnqueued), 'seconds'

Make the processed object.

            processed =
              connection: queueMeta.theOnlyConnectionAllowedIn
              waitTimeSeconds: waitTimeSeconds

Insert the processed connection to `QueueProcessed`

            QueueProcessed.insert processed
          catch err
            console.log err

Remove the connection from the `Queue`

          criteria = _id: queueMeta.currentlyServingQueueId
          Queue.remove criteria

Update `QueueMeta` stats and ticket number.

          try
            totalWaitTimeSeconds = queueMeta.totalWaitTimeSeconds + waitTimeSeconds
            currentlyServingTicketNumber = queueMeta.currentlyServingTicketNumber + 1
            _.extend update.$set,
              currentlyServingTicketNumber: currentlyServingTicketNumber
              hasCurrentConnectionPosted: no
              totalWaitTimeSeconds: totalWaitTimeSeconds
          catch err
            console.log err

Lookup the lowest ticket # waiting in the `Queue`

        nextConnection = Queue.findOne {}, { sort: { 'ticketNumber': 1 } }

Set the allowed connection and expireTime if one exists

If there is a nextConnection (i.e. someone waiting in line), then serve them.
Otherwise clear out theOnlyConnectionAllowedIn.

        if nextConnection?
          timeCurrentTicketExpires = moment.utc()
          timeCurrentTicketExpires.add 1, 'minutes'
          _.extend update.$set,
            theOnlyConnectionAllowedIn: nextConnection
            timeCurrentTicketExpires: timeCurrentTicketExpires.toDate()
            currentlyServingTicketNumber: nextConnection.ticketNumber
            currentlyServingQueueId: nextConnection._id

If there is no nextConnection, unset theOnlyConnectionAllowedIn.
Note, fake data is filled in to pass schema, even though we're $unset'ing

        else
          update.$unset = theOnlyConnectionAllowedIn: ""

        criteria = _id: queueMeta._id

Delete `update.$set` if it's empty

        if _.isEmpty update.$set
          delete update.$set

If `update` isn't empty, update!

        if not _.isEmpty update
          QueueMeta.update criteria, update

TODO: keep it DRY; logic isn't exactly shared and want to keep update atomic to
avoid extraneous DDP messages.

## Disconnect dead connections, remove from queue

      cleanUpDeadConnections: ->

A connection is dead if keepAlive > 5 minutes ago

        timeTwoMinutesAgoUtc = moment.utc().subtract('2', 'minutes').toDate()
        criteria =
          timeKeepAlive:
            $lt: timeTwoMinutesAgoUtc

        deadQueue = Queue.find criteria
        deadQueue.forEach (queue) ->
          criteria =
            _id: queue._id
          Queue.remove criteria

Calculate how long the connection had to wait in line.

          waitTimeSeconds = moment.utc().diff (moment.utc queue.timeEnqueued), 'seconds'

Make the processed object.

          processed =
            connection: queue
            waitTimeSeconds: waitTimeSeconds
            diconnect: yes
          QueueProcessed.insert processed

          queueMeta = QueueMeta.findOne()

          totalWaitTimeSeconds = queueMeta.totalWaitTimeSeconds + waitTimeSeconds

          criteria =
            _id: queueMeta._id
          action =
            $set:
              totalWaitTimeSeconds: totalWaitTimeSeconds
          QueueMeta.update criteria, action


Defer buildMatchers to configure call instead of in Commander parser func

This means using the languages option when calling Docco programmatically will
work properly.

Docco
=====

**Docco** is a quick-and-dirty documentation generator, written in
[Literate CoffeeScript](http://coffeescript.org/#literate).
It produces an HTML document that displays your comments intermingled with your
code. All prose is passed through
[Markdown](http://daringfireball.net/projects/markdown/syntax), and code is
passed through [Highlight.js](http://highlightjs.org/) syntax highlighting.
This page is the result of running Docco against its own
[source file](https://github.com/jashkenas/docco/blob/master/docco.litcoffee).

1. Install Docco with **npm**: `sudo npm install -g docco`

2. Run it against your code: `docco src/*.coffee`

There is no "Step 3". This will generate an HTML page for each of the named
source files, with a menu linking to the other pages, saving the whole mess
into a `docs` folder (configurable).

The [Docco source](http://github.com/jashkenas/docco) is available on GitHub,
and is released under the [MIT license](http://opensource.org/licenses/MIT).

Docco can be used to process code written in any programming language. If it
doesn't handle your favorite yet, feel free to
[add it to the list](https://github.com/jashkenas/docco/blob/master/resources/languages.json).
Finally, the ["literate" style](http://coffeescript.org/#literate) of *any*
language is also supported — just tack an `.md` extension on the end:
`.coffee.md`, `.py.md`, and so on.

Partners in Crime:
------------------

* If Node.js doesn't run on your platform, or you'd prefer a more
convenient package, get [Ryan Tomayko](http://github.com/rtomayko)'s
[Rocco](http://rtomayko.github.io/rocco/rocco.html), the **Ruby** port that's
available as a gem.

* If you're writing shell scripts, try
[Shocco](http://rtomayko.github.io/shocco/), a port for the **POSIX shell**,
also by Mr. Tomayko.

* If **Python** is more your speed, take a look at
[Nick Fitzgerald](http://github.com/fitzgen)'s [Pycco](http://fitzgen.github.io/pycco/).

* For **Clojure** fans, [Fogus](http://blog.fogus.me/)'s
[Marginalia](http://fogus.me/fun/marginalia/) is a bit of a departure from
"quick-and-dirty", but it'll get the job done.

* There's a **Go** port called [Gocco](http://nikhilm.github.io/gocco/),
written by [Nikhil Marathe](https://github.com/nikhilm).

* Your all you **PHP** buffs out there, Fredi Bach's
[sourceMakeup](http://jquery-jkit.com/sourcemakeup/) (we'll let the faux pas
with respect to our naming scheme slide), should do the trick nicely.

* **Lua** enthusiasts can get their fix with
[Robert Gieseke](https://github.com/rgieseke)'s [Locco](http://rgieseke.github.io/locco/).

* And if you happen to be a **.NET**
aficionado, check out [Don Wilson](https://github.com/dontangg)'s
[Nocco](http://dontangg.github.io/nocco/).

* Going further afield from the quick-and-dirty, [Groc](http://nevir.github.io/groc/)
is a **CoffeeScript** fork of Docco that adds a searchable table of contents,
and aims to gracefully handle large projects with complex hierarchies of code.

Note that not all ports will support all Docco features ... yet.

Main Documentation Generation Functions
---------------------------------------

Generate the documentation for our configured source file by copying over static
assets, reading all the source files in, splitting them up into prose+code
sections, highlighting each file in the appropriate language, and printing them
out in an HTML template.

    document = (options = {}, callback) ->
      config = configure options

      fs.mkdirs config.output, ->

        callback or= (error) -> throw error if error
        copyAsset  = (file, callback) ->
          fs.copy file, path.join(config.output, path.basename(file)), callback
        complete   = ->
          copyAsset config.css, (error) ->
            if error then callback error
            else if fs.existsSync config.public then copyAsset config.public, callback
            else callback()

        files = config.sources.slice()

        nextFile = ->
          source = files.shift()
          fs.readFile source, (error, buffer) ->
            return callback error if error

            code = buffer.toString()
            sections = parse source, code, config
            format source, sections, config
            write source, sections, config
            if files.length then nextFile() else complete()

        nextFile()

Given a string of source code, **parse** out each block of prose and the code that
follows it — by detecting which is which, line by line — and then create an
individual **section** for it. Each section is an object with `docsText` and
`codeText` properties, and eventually `docsHtml` and `codeHtml` as well.

    parse = (source, code, config = {}) ->
      lines    = code.split '\n'
      sections = []
      lang     = getLanguage source, config
      hasCode  = docsText = codeText = ''

      save = ->
        sections.push {docsText, codeText}
        hasCode = docsText = codeText = ''

Our quick-and-dirty implementation of the literate programming style. Simply
invert the prose and code relationship on a per-line basis, and then continue as
normal below.

      if lang.literate
        isText = maybeCode = yes
        for line, i in lines
          lines[i] = if maybeCode and match = /^([ ]{4}|[ ]{0,3}\t)/.exec line
            isText = no
            line[match[0].length..]
          else if maybeCode = /^\s*$/.test line
            if isText then lang.symbol else ''
          else
            isText = yes
            lang.symbol + ' ' + line

      for line in lines
        if line.match(lang.commentMatcher) and not line.match(lang.commentFilter)
          save() if hasCode
          docsText += (line = line.replace(lang.commentMatcher, '')) + '\n'
          save() if /^(---+|===+)$/.test line
        else
          hasCode = yes
          codeText += line + '\n'
      save()

      sections

To **format** and highlight the now-parsed sections of code, we use **Highlight.js**
over stdio, and run the text of their corresponding comments through
**Markdown**, using [Marked](https://github.com/chjj/marked).

    format = (source, sections, config) ->
      language = getLanguage source, config
      for section, i in sections
        code = highlight(language.name, section.codeText).value
        code = code.replace(/\s+$/, '')
        section.codeHtml = "

#{code}

"
        section.docsHtml = marked(section.docsText)

Once all of the code has finished highlighting, we can **write** the resulting
documentation file by passing the completed HTML sections into the template,
and rendering it to the specified output path.

    write = (source, sections, config) ->

      destination = (file) ->
        path.join(config.output, path.basename(file, path.extname(file)) + '.html')

The **title** of the file is either the first heading in the prose, or the
name of the source file.

      first = marked.lexer(sections[0].docsText)[0]
      hasTitle = first and first.type is 'heading' and first.depth is 1
      title = if hasTitle then first.text else path.basename source

      html = config.template {sources: config.sources, css: path.basename(config.css),
        title, hasTitle, sections, path, destination,}

      console.log "docco: #{source} -> #{destination source}"
      fs.writeFileSync destination(source), html

Configuration
-------------

Default configuration **options**. All of these may be extended by
user-specified options.

    defaults =
      layout:     'parallel'
      output:     'docs'
      template:   null
      css:        null
      extension:  null
      languages:  {}

**Configure** this particular run of Docco. We might use a passed-in external
template, or one of the built-in **layouts**. We only attempt to process
source files for languages for which we have definitions.

    configure = (options) ->
      config = _.extend {}, defaults, _.pick(options, _.keys(defaults)...)

      config.languages = buildMatchers config.languages
      if options.template
        config.layout = null
      else
        dir = config.layout = path.join __dirname, 'resources', config.layout
        config.public       = path.join dir, 'public' if fs.existsSync path.join dir, 'public'
        config.template     = path.join dir, 'docco.jst'
        config.css          = options.css or path.join dir, 'docco.css'
      config.template = _.template fs.readFileSync(config.template).toString()

      config.sources = options.args.filter((source) ->
        lang = getLanguage source, config
        console.warn "docco: skipped unknown type (#{path.basename source})" unless lang
        lang
      ).sort()

      config

Helpers & Initial Setup
-----------------------

Require our external dependencies.

    _           = require 'underscore'
    fs          = require 'fs-extra'
    path        = require 'path'
    marked      = require 'marked'
    commander   = require 'commander'
    {highlight} = require 'highlight.js'

Enable nicer typography with marked.

    marked.setOptions smartypants: yes

Languages are stored in JSON in the file `resources/languages.json`.
Each item maps the file extension to the name of the language and the
`symbol` that indicates a line comment. To add support for a new programming
language to Docco, just add it to the file.

    languages = JSON.parse fs.readFileSync(path.join(__dirname, 'resources', 'languages.json'))

Build out the appropriate matchers and delimiters for each language.

    buildMatchers = (languages) ->
      for ext, l of languages

Does the line begin with a comment?

        l.commentMatcher = ///^\s*#{l.symbol}\s?///

Ignore [hashbangs](http://en.wikipedia.org/wiki/Shebang_%28Unix%29) and interpolations...

        l.commentFilter = /(^#![/]|^\s*#\{)/
      languages
    languages = buildMatchers languages

A function to get the current language we're documenting, based on the
file extension. Detect and tag "literate" `.ext.md` variants.

    getLanguage = (source, config) ->
      ext  = config.extension or path.extname(source) or path.basename(source)
      lang = config.languages[ext] or languages[ext]
      if lang and lang.name is 'markdown'
        codeExt = path.extname(path.basename(source, ext))
        if codeExt and codeLang = languages[codeExt]
          lang = _.extend {}, codeLang, {literate: yes}
      lang

Keep it DRY. Extract the docco **version** from `package.json`

    version = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'))).version

Command Line Interface
----------------------

Finally, let's define the interface to run Docco from the command line.

We accept customised language formats as a command-line argument in the form
`ext:langname:commentsymbol,ext:langname:commentsymbol`.

    parseLanguages = (langs) ->
        return {} unless _.isString langs
        _.object _.map langs.split(','), (s) ->
            [ext, name, symbol, literate] = s.split(':')
            literate ?= false
            [ext, {name, symbol, literate}]

Parse options using [Commander](https://github.com/visionmedia/commander.js).

    run = (args = process.argv) ->
      c = defaults
      commander.version(version)
        .usage('[options] files')
        .option('-L, --languages [langs]','set custom language comment styles', parseLanguages)
        .option('-l, --layout [name]',    'choose a layout (parallel, linear or classic)', c.layout)
        .option('-o, --output [path]',    'output to a given folder', c.output)
        .option('-c, --css [file]',       'use a custom css file', c.css)
        .option('-t, --template [file]',  'use a custom .jst template', c.template)
        .option('-e, --extension [ext]',  'assume a file extension for all inputs', c.extension)
        .parse(args)
        .name = "docco"
      if commander.args.length
        document commander
      else
        console.log commander.helpInformation()

Public API
----------

    Docco = module.exports = {run, document, parse, format, version}

Docco
=====

**Docco** is a quick-and-dirty documentation generator, written in
[Literate CoffeeScript](http://coffeescript.org/#literate).
It produces an HTML document that displays your comments intermingled with your
code. All prose is passed through
[Markdown](http://daringfireball.net/projects/markdown/syntax), and code is
passed through [Highlight.js](http://highlightjs.org/) syntax highlighting.
This page is the result of running Docco against its own
[source file](https://github.com/jashkenas/docco/blob/master/docco.litcoffee).

1. Install Docco with **npm**: `sudo npm install -g docco`

2. Run it against your code: `docco src/*.coffee`

There is no "Step 3". This will generate an HTML page for each of the named
source files, with a menu linking to the other pages, saving the whole mess
into a `docs` folder (configurable).

The [Docco source](http://github.com/jashkenas/docco) is available on GitHub,
and is released under the [MIT license](http://opensource.org/licenses/MIT).

Docco can be used to process code written in any programming language. If it
doesn't handle your favorite yet, feel free to
[add it to the list](https://github.com/jashkenas/docco/blob/master/resources/languages.json).
Finally, the ["literate" style](http://coffeescript.org/#literate) of *any*
language is also supported — just tack an `.md` extension on the end:
`.coffee.md`, `.py.md`, and so on.

Partners in Crime:
------------------

* If Node.js doesn't run on your platform, or you'd prefer a more
convenient package, get [Ryan Tomayko](http://github.com/rtomayko)'s
[Rocco](http://rtomayko.github.io/rocco/rocco.html), the **Ruby** port that's
available as a gem.

* If you're writing shell scripts, try
[Shocco](http://rtomayko.github.io/shocco/), a port for the **POSIX shell**,
also by Mr. Tomayko.

* If **Python** is more your speed, take a look at
[Nick Fitzgerald](http://github.com/fitzgen)'s [Pycco](http://fitzgen.github.io/pycco/).

* For **Clojure** fans, [Fogus](http://blog.fogus.me/)'s
[Marginalia](http://fogus.me/fun/marginalia/) is a bit of a departure from
"quick-and-dirty", but it'll get the job done.

* There's a **Go** port called [Gocco](http://nikhilm.github.io/gocco/),
written by [Nikhil Marathe](https://github.com/nikhilm).

* Your all you **PHP** buffs out there, Fredi Bach's
[sourceMakeup](http://jquery-jkit.com/sourcemakeup/) (we'll let the faux pas
with respect to our naming scheme slide), should do the trick nicely.

* **Lua** enthusiasts can get their fix with
[Robert Gieseke](https://github.com/rgieseke)'s [Locco](http://rgieseke.github.io/locco/).

* And if you happen to be a **.NET**
aficionado, check out [Don Wilson](https://github.com/dontangg)'s
[Nocco](http://dontangg.github.io/nocco/).

* Going further afield from the quick-and-dirty, [Groc](http://nevir.github.io/groc/)
is a **CoffeeScript** fork of Docco that adds a searchable table of contents,
and aims to gracefully handle large projects with complex hierarchies of code.

Note that not all ports will support all Docco features ... yet.

Main Documentation Generation Functions
---------------------------------------

Generate the documentation for our configured source file by copying over static
assets, reading all the source files in, splitting them up into prose+code
sections, highlighting each file in the appropriate language, and printing them
out in an HTML template.

    document = (options = {}, callback) ->
      config = configure options

      fs.mkdirs config.output, ->

        callback or= (error) -> throw error if error
        copyAsset  = (file, callback) ->
          fs.copy file, path.join(config.output, path.basename(file)), callback
        complete   = ->
          copyAsset config.css, (error) ->
            if error then callback error
            else if fs.existsSync config.public then copyAsset config.public, callback
            else callback()

        files = config.sources.slice()

        nextFile = ->
          source = files.shift()
          fs.readFile source, (error, buffer) ->
            return callback error if error

            code = buffer.toString()
            sections = parse source, code, config
            format source, sections, config
            write source, sections, config
            if files.length then nextFile() else complete()

        nextFile()

Given a string of source code, **parse** out each block of prose and the code that
follows it — by detecting which is which, line by line — and then create an
individual **section** for it. Each section is an object with `docsText` and
`codeText` properties, and eventually `docsHtml` and `codeHtml` as well.

    parse = (source, code, config = {}) ->
      lines    = code.split '\n'
      sections = []
      lang     = getLanguage source, config
      hasCode  = docsText = codeText = ''

      save = ->
        sections.push {docsText, codeText}
        hasCode = docsText = codeText = ''

Our quick-and-dirty implementation of the literate programming style. Simply
invert the prose and code relationship on a per-line basis, and then continue as
normal below.

      if lang.literate
        isText = maybeCode = yes
        for line, i in lines
          lines[i] = if maybeCode and match = /^([ ]{4}|[ ]{0,3}\t)/.exec line
            isText = no
            line[match[0].length..]
          else if maybeCode = /^\s*$/.test line
            if isText then lang.symbol else ''
          else
            isText = yes
            lang.symbol + ' ' + line

      for line in lines
        if line.match(lang.commentMatcher) and not line.match(lang.commentFilter)
          save() if hasCode
          docsText += (line = line.replace(lang.commentMatcher, '')) + '\n'
          save() if /^(---+|===+)$/.test line
        else
          hasCode = yes
          codeText += line + '\n'
      save()

      sections

To **format** and highlight the now-parsed sections of code, we use **Highlight.js**
over stdio, and run the text of their corresponding comments through
**Markdown**, using [Marked](https://github.com/chjj/marked).

    format = (source, sections, config) ->
      language = getLanguage source, config
      for section, i in sections
        code = highlight(language.name, section.codeText).value
        code = code.replace(/\s+$/, '')
        section.codeHtml = "

#{code}

"
        section.docsHtml = marked(section.docsText)

Once all of the code has finished highlighting, we can **write** the resulting
documentation file by passing the completed HTML sections into the template,
and rendering it to the specified output path.

    write = (source, sections, config) ->

      destination = (file) ->
        path.join(config.output, path.basename(file, path.extname(file)) + '.html')

The **title** of the file is either the first heading in the prose, or the
name of the source file.

      first = marked.lexer(sections[0].docsText)[0]
      hasTitle = first and first.type is 'heading' and first.depth is 1
      title = if hasTitle then first.text else path.basename source

      html = config.template {sources: config.sources, css: path.basename(config.css),
        title, hasTitle, sections, path, destination,}

      console.log "docco: #{source} -> #{destination source}"
      fs.writeFileSync destination(source), html

Configuration
-------------

Default configuration **options**. All of these may be extended by
user-specified options.

    defaults =
      layout:     'parallel'
      output:     'docs'
      template:   null
      css:        null
      extension:  null
      languages:  {}

**Configure** this particular run of Docco. We might use a passed-in external
template, or one of the built-in **layouts**. We only attempt to process
source files for languages for which we have definitions.

    configure = (options) ->
      config = _.extend {}, defaults, _.pick(options, _.keys(defaults)...)

      if options.template
        config.layout = null
      else
        dir = config.layout = path.join __dirname, 'resources', config.layout
        config.public       = path.join dir, 'public' if fs.existsSync path.join dir, 'public'
        config.template     = path.join dir, 'docco.jst'
        config.css          = options.css or path.join dir, 'docco.css'
      config.template = _.template fs.readFileSync(config.template).toString()

      config.sources = options.args.filter((source) ->
        lang = getLanguage source, config
        console.warn "docco: skipped unknown type (#{path.basename source})" unless lang
        lang
      ).sort()

      config

Helpers & Initial Setup
-----------------------

Require our external dependencies.

    _           = require 'underscore'
    fs          = require 'fs-extra'
    path        = require 'path'
    marked      = require 'marked'
    commander   = require 'commander'
    {highlight} = require 'highlight.js'

Enable nicer typography with marked.

    marked.setOptions smartypants: yes

Languages are stored in JSON in the file `resources/languages.json`.
Each item maps the file extension to the name of the language and the
`symbol` that indicates a line comment. To add support for a new programming
language to Docco, just add it to the file.

    languages = JSON.parse fs.readFileSync(path.join(__dirname, 'resources', 'languages.json'))

Build out the appropriate matchers and delimiters for each language.

    buildMatchers = (languages) ->
      for ext, l of languages

Does the line begin with a comment?

        l.commentMatcher = ///^\s*#{l.symbol}\s?///

Ignore [hashbangs](http://en.wikipedia.org/wiki/Shebang_%28Unix%29) and interpolations...

        l.commentFilter = /(^#![/]|^\s*#\{)/
      languages
    languages = buildMatchers languages

A function to get the current language we're documenting, based on the
file extension. Detect and tag "literate" `.ext.md` variants.

    getLanguage = (source, config) ->
      ext  = config.extension or path.extname(source) or path.basename(source)
      lang = config.languages[ext] or languages[ext]
      if lang and lang.name is 'markdown'
        codeExt = path.extname(path.basename(source, ext))
        if codeExt and codeLang = languages[codeExt]
          lang = _.extend {}, codeLang, {literate: yes}
      lang

Keep it DRY. Extract the docco **version** from `package.json`

    version = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'))).version

Command Line Interface
----------------------

Finally, let's define the interface to run Docco from the command line.

We accept customised language formats as a command-line argument in the form
`ext:langname:commentsymbol,ext:langname:commentsymbol`.

    parseLanguages = (langs) ->
        return {} unless _.isString langs
        buildMatchers _.object _.map langs.split(','), (s) ->
            [ext, name, symbol, literate] = s.split(':')
            literate ?= false
            [ext, {name, symbol, literate}]

Parse options using [Commander](https://github.com/visionmedia/commander.js).

    run = (args = process.argv) ->
      c = defaults
      commander.version(version)
        .usage('[options] files')
        .option('-L, --languages [langs]','set custom language comment styles', parseLanguages)
        .option('-l, --layout [name]',    'choose a layout (parallel, linear or classic)', c.layout)
        .option('-o, --output [path]',    'output to a given folder', c.output)
        .option('-c, --css [file]',       'use a custom css file', c.css)
        .option('-t, --template [file]',  'use a custom .jst template', c.template)
        .option('-e, --extension [ext]',  'assume a file extension for all inputs', c.extension)
        .parse(args)
        .name = "docco"
      if commander.args.length
        document commander
      else
        console.log commander.helpInformation()

Public API
----------

    Docco = module.exports = {run, document, parse, format, version}


Refactor code

Refactor code

Dependencies
============

    fs     = require "fs"
    path   = require "path"
    {exec} = require "child_process"
    VOSCO  = require "vosco"

Sanity Checks
-------------

VOSCO must always be run with **root** previliges. It is expected to run with `sudo` command by logged in user. VOSCO is designed to manage system wide configurations and needs read/write access to many restricted files. The program will stop unless the user id is zero.

    await exec "id -u", defer(error, userId)
    unless parseInt(userId) is 0
      console.error "VOSCO must be run as root user"
      process.exit 1

Initialize VOSCO
----------------

Create a new VOSCO instance called `vosco` which will be doing all the hard work. No need to set environment variables before running unless you're testing or doing something different using VOSCO.

    vosco = do ->
      repo_path = process.env.VOSCO_ROOT_DIR || '/'
      repo_opts =
        author_name : process.env.USER
        author_email: "#{process.env.USER}@localhost"
      return new VOSCO repo_path, repo_opts

Shell Mode / Script Mode
------------------------

The shell mode is interactive. It will guide users using helpful menus and messages. This mode is difficult and not suitable for scripting. Script mode is suitable for scripting and for non-interactive use. Output form this mode is always clean and easy to parse using other programs.

    shell  = require("./lib/shell")(vosco)
    script = require("./lib/script")(vosco)

If no arguments are given, we assume that user wishes to enter an interactive shell to run VOSCO commands. Otherwise assume user needs to run specific commands using script mode. Show the help text if user enters an invalid command.

    command = process.argv[2]
    args    = process.argv.slice 3

    if command is undefined
      shell.init()
    else if typeof script[command] is 'function'
      script[command].apply script, args
    else do ->
      filePath = path.resolve __dirname, "help-text.txt"
      helpText = fs.readFileSync filePath
      console.log helpText.toString()

Dependencies
============

    fs     = require "fs"
    path   = require "path"
    {exec} = require "child_process"
    VOSCO  = require "vosco"

    Shell  = require "./lib/shell"
    Script = require "./lib/script"

Sanity Checks
-------------

VOSCO must always be run with **root** previliges. It is expected to run with `sudo` command by logged in user. VOSCO is designed to manage system wide configurations and needs read/write access to many restricted files. The program will stop unless the user id is zero.

    await exec "id -u", defer(error, userId)
    unless parseInt(userId) is 0
      console.error "VOSCO must be run as root user"
      process.exit 1

Initialize VOSCO
----------------

    vosco = do ->
      repo_path = process.env.VOSCO_ROOT_DIR || '/'
      repo_opts =
        author_name : process.env.USER
        author_email: "#{process.env.USER}@localhost"
      return new VOSCO repo_path, repo_opts

    shell  = Shell(vosco)
    script = Script(vosco)

Script or Interactive
---------------------

If no arguments are given, we assume that user wishes to enter an interactive shell to run VOSCO commands. Otherwise assume user needs to run specific commands.

    command = process.argv[2]
    args    = process.argv.slice 3

    if command is undefined
      shell.init()
    else if typeof script[command] is 'function'
      script[command].apply script, args
    else do ->
      filePath = path.resolve __dirname, "help-text.txt"
      helpText = fs.readFileSync filePath
      console.log helpText.toString()