Added access to 'this' for advice functions

Policy
======

    _ = require "underscore"

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

            @policy =

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

                wrapWithMembrane: (libName) -> false

        disable: (lib) -> this

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

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

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

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

        build: () =>
            @libsToWrap = []

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

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

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

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

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

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

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

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

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

            @policy.functionCall = (dTgt, dryThis, dryArgs, calcResult, fullName) =>
                if dryThis != undefined and fullName.indexOf("/") != -1
                    fullName = "#{dryThis.constructor.name}.#{dTgt.name}"
                relevantRules = _.chain(@rules).filter(strEqual(fullName))

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

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

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

            @policy

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

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

            @actions = []

The default return function [1..1]:

            @ret = (v) -> v

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

            @conditions = [ -> true]

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

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

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

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

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

    module.exports = Policy

Policy
======

    _ = require "underscore"

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

            @policy =

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

                wrapWithMembrane: (libName) -> false

        disable: (lib) -> this

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

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

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

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

        build: () =>
            @libsToWrap = []

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

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

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

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

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

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

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

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

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

            @policy.functionCall = (dTgt, dryThis, dryArgs, calcResult, fullName) =>
                if dryThis != undefined and fullName.indexOf("/") != -1
                    fullName = "#{dryThis.constructor.name}.#{dTgt.name}"
                relevantRules = _.chain(@rules).filter(strEqual(fullName))

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

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

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

            @policy

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

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

            @actions = []

The default return function [1..1]:

            @ret = (v) -> v

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

            @conditions = [ -> true]

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

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

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

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

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

    module.exports = Policy


Switch to .io domains for gh-pages links

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
        for line, i in lines
          lines[i] = if /^\s*$/.test line
            ''
          else if match = (/^([ ]{4}|\t)/).exec line
            line[match[0].length..]
          else
            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
          prev = 'text'
        else
          hasCode = yes
          codeText += line + '\n'
          prev = 'code'
      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

**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'

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.

    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*#\{)/

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 = 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.
Parse options using [Commander](https://github.com/visionmedia/commander.js).

    run = (args = process.argv) ->
      c = defaults
      commander.version(version)
        .usage('[options] files')
        .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, 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.com/rocco/rocco.html), the **Ruby** port that's
available as a gem.

* If you're writing shell scripts, try
[Shocco](http://rtomayko.github.com/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.com/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.com/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.com/locco/).

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

* Going further afield from the quick-and-dirty, [Groc](http://nevir.github.com/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
        for line, i in lines
          lines[i] = if /^\s*$/.test line
            ''
          else if match = (/^([ ]{4}|\t)/).exec line
            line[match[0].length..]
          else
            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
          prev = 'text'
        else
          hasCode = yes
          codeText += line + '\n'
          prev = 'code'
      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

**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'

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.

    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*#\{)/

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 = 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.
Parse options using [Commander](https://github.com/visionmedia/commander.js).

    run = (args = process.argv) ->
      c = defaults
      commander.version(version)
        .usage('[options] files')
        .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, version}


Update 010_Basics.litcoffee

Update 010_Basics.litcoffee

Базовые свойства CloudState
==============================

Идея
------------------------------

CloudState - позволяет организовать синхронизацию состояний между несколькими узлами (сервера, браузерами), используя
в качестве канала библиотеку socket.io.

Для передачи состояния, на одном из компьютеров создается один главный (origin) объект состояния, и к нему
подключаются clone-объекты.  Оrigin является самостоятельным объектом, и может работать без clone.  Clone является
подчиненым объектом, и не может менять своё состояние без подключение к origin объекту.

Все изменения состояния origin передаются на clone-объекты, через вызов setter-методов - их имен начинаются с подчерка.

Все команды полученные clone-объектом из jscript-кода, передаются на origin для исполнения.

Для кода использующего CloudState объекты, практически не видна разница работает ли он с Origin или Clone.

    require './_globals'
    socketIO = require 'socket.io'
    socketIOClient = require 'socket.io-client'
    CloudState = require '../src/CloudState'

    serverSocket = clientSocket = null

    describe '010 Basics:', ->

      afterEach ->
        @serverSocket.close() if @serverSocket
        @clientSocket.close() if @clientSocket

Классы Origin и Clone
------------------------------

При наследовании от класса CloudState

      it '010', ->

        class X extends CloudState

в самом *конце описания* нового класса, необходимо вызвать статический метод makeOriginAndClone()

          @makeOriginAndClone()

этот метод создаст два производных класса, привязанных к новому классу.  Класс <имя класс>.Origin

          expect(X.Origin).toBeDefined()

и класс <имя класс>.Clone.

Эти классы должны быть использованы для создания объектов.

          expect(X.Clone).toBeDefined()

Методы
------------------------------

Структура данных и методы в классе наследнике CloudState определяются, так же, и для любого класса

      it '020', ->

        class X extends CloudState

          constructor: ->
            super()
            @field1 = ''
            return

          method1: ->
            @field1 = 'a value'
            return

и не забываем вызвать makeOriginAndClone()

          @makeOriginAndClone()

НЕ ПРАВИЛЬНО! Создавать объекты напряму из класса

        expect(-> x = new X(); return).toThrow(new Error 'It\'s wrong to create a new instance of remote state directly.  Use <className>.Origin or <className>.Clone.(connect | listen)')

Через операцию new можно создавать объекты только подкласса Origin

        x = new X.Origin()
        expect(x.field1).toBe ''
        x.method1()
        expect(x.field1).toBe 'a value'

Именование свойств и методов
------------------------------

CloudState оринетирован на работу с AngularJS.  Плюс не желательно чтоб методы CloudState путались с методами классов,
которые реализуют remote state для конкретных задач. Поэтому выполняется следующее соглашение:

      # TODO: Показать как работает digest при обновлениях

      it '030', ->

        class X extends CloudState
          @setters
            setV: (v) -> @v = v; return
          action: -> return
          @makeOriginAndClone()

методы классов (статические) CloudState, Origin и Clone - просто методы

          expect(CloudState.setters).toBeDefined()
          expect(CloudState.makeOriginAndClone).toBeDefined()
          expect(X.Clone.connect).toBeDefined()
          expect(X.Clone.listen).toBeDefined()

внутрение переменные называются с двумя $ в начале, чтоб angular игнорировал их при выводе объекта состояния целиком

          x = new X.Origin()
          expect(x.$$blocked).toBeDefined()

общие методы CloudState, начинаются с двух подчерков

          expect(x.__connect).toBeDefined()

методы изменения состояний, начинаются с подчерка

          expect(x._setV).toBeDefined()

методы объекта - без изменений

          expect(x.action).toBeDefined()

Наследование классов состояния
------------------------------

Можно наследоваться от класса, которые унаследован от CloudState

      it '040', ->

        class X extends CloudState

          constructor: ->
            @field1 = ''
            return

          method1: ->
            @field1 = 'a value'
            return

          @makeOriginAndClone()

        class Y extends X

          constructor: ->
            super()
            @field2 = ''
            return

          method2: ->
            @field2 = 'a value'
            return

          @makeOriginAndClone()

        y = new Y.Origin()
        expect(y.field1).toBe ''
        expect(y.field2).toBe ''
        y.method1()
        y.method2()
        expect(y.field1).toBe 'a value'
        expect(y.field2).toBe 'a value'

        # TODO: Block direct class instantiation

НЕ ПРАВИЛЬНО! Создавать классы Clone напрямую.  Их надо создавать через методы listen

      it '050', (done) ->

        class X extends CloudState

          @makeOriginAndClone()

        x = new X.Origin()

сперва создает X.Origin объект, который слушает на порту

        x.__listen (@serverSocket = socketIO(3990)), '/origin'

потом подключаем к X.Clone объект

        X.Clone.connect (@clientSocket = socketIOClient.connect('http://localhost:3990/origin')), (err, clone) ->

          if err then done.fail(err); return

          expect(clone).toBeDefined()
          expect(clone).not.toBeNull()

          done()
          return

или connect к Origin объекту

      it '060', (done) ->

        class X extends CloudState

          @makeOriginAndClone()

сперва воздаем X.Clone, который слушает на порту когда появится X.Origin

        X.Clone.listen (@serverSocket = socketIO(3990)), '/clone', (err, clone) ->

          if err then done.fail(err); return

          expect(clone).toBeDefined()
          expect(clone).not.toBeNull()

          done()
          return

потом создаем X.Origin, который подключается к X.Clone

        x = new X.Origin()
        x.__connect (@clientSocket = socketIOClient.connect('http://localhost:3990/clone'))

Базовые свойства CloudState
==============================

Идея
------------------------------

CloudState - позволяет орагнизовать синхронизацию состояний между несколькими узлами (сервера, браузерами), используя
в качестве канала библиотеку socket.io.

Для передачи состояния, на одном из компьютеров создается один главный (origin) объект состояния, и к нему
подключаются clone-объекты.  Оrigin является самостоятельным объектом, и может работать без clone.  Clone является
подчиненым объектом, и не может менять своё состояние без подключение к origin объекту.

Все изменения состояния origin передаются на clone-объекты, через вызов setter-методов - их имен начинаются с подчерка.

Все команды полученные clone-объектом из jscript-кода, передаются на origin для исполнения.

Для кода использующего CloudState объекты, практически не видна разница работает ли он с Origin или Clone.

    require './_globals'
    socketIO = require 'socket.io'
    socketIOClient = require 'socket.io-client'
    CloudState = require '../src/CloudState'

    serverSocket = clientSocket = null

    describe '010 Basics:', ->

      afterEach ->
        @serverSocket.close() if @serverSocket
        @clientSocket.close() if @clientSocket

Классы Origin и Clone
------------------------------

При наследовании от класса CloudState

      it '010', ->

        class X extends CloudState

в самам *конце описания* нового класса, необходимо вызвать статический метод makeOriginAndClone()

          @makeOriginAndClone()

этот метод создаст два производных класса, привязанных к новому классу.  Класс <имя класс>.Origin

          expect(X.Origin).toBeDefined()

и класс <имя класс>.Clone.

Эти классы должны быть использованы для создания объектов.

          expect(X.Clone).toBeDefined()

Методы
------------------------------

Структура данных и методы в классе наследнике CloudState определяются, так же, и для любого класса

      it '020', ->

        class X extends CloudState

          constructor: ->
            super()
            @field1 = ''
            return

          method1: ->
            @field1 = 'a value'
            return

и не забываем вызвать makeOriginAndClone()

          @makeOriginAndClone()

НЕ ПРАВИЛЬНО! Создавать объекты напряму из класса

        expect(-> x = new X(); return).toThrow(new Error 'It\'s wrong to create a new instance of remote state directly.  Use <className>.Origin or <className>.Clone.(connect | listen)')

Через операцию new можно создавать объекты только подкласса Origin

        x = new X.Origin()
        expect(x.field1).toBe ''
        x.method1()
        expect(x.field1).toBe 'a value'

Именование свойств и методов
------------------------------

CloudState оринетирован на работу с AngularJS.  Плюс не желательно чтоб методы CloudState путались с методами классов,
которые реализуют remote state для конкретных задач. Поэтому выполняется следующее соглашение:

      # TODO: Показать как работает digest при обновлениях

      it '030', ->

        class X extends CloudState
          @setters
            setV: (v) -> @v = v; return
          action: -> return
          @makeOriginAndClone()

методы классов (статические) CloudState, Origin и Clone - просто методы

          expect(CloudState.setters).toBeDefined()
          expect(CloudState.makeOriginAndClone).toBeDefined()
          expect(X.Clone.connect).toBeDefined()
          expect(X.Clone.listen).toBeDefined()

внутрение переменные называются с двумя $ в начале, чтоб angular игнорировал их при выводе объекта состояния целиком

          x = new X.Origin()
          expect(x.$$blocked).toBeDefined()

общие методы CloudState, начинаются с двух подчерков

          expect(x.__connect).toBeDefined()

методы изменения состояний, начинаются с подчерка

          expect(x._setV).toBeDefined()

методы объекта - без изменений

          expect(x.action).toBeDefined()

Наследование классов состояния
------------------------------

Можно наследоваться от класса, которые унаследован от CloudState

      it '040', ->

        class X extends CloudState

          constructor: ->
            @field1 = ''
            return

          method1: ->
            @field1 = 'a value'
            return

          @makeOriginAndClone()

        class Y extends X

          constructor: ->
            super()
            @field2 = ''
            return

          method2: ->
            @field2 = 'a value'
            return

          @makeOriginAndClone()

        y = new Y.Origin()
        expect(y.field1).toBe ''
        expect(y.field2).toBe ''
        y.method1()
        y.method2()
        expect(y.field1).toBe 'a value'
        expect(y.field2).toBe 'a value'

        # TODO: Block direct class instantiation

НЕ ПРАВИЛЬНО! Создавать классы Clone напрямую.  Их надо создавать через методы listen

      it '050', (done) ->

        class X extends CloudState

          @makeOriginAndClone()

        x = new X.Origin()

сперва создает X.Origin объект, который слушает на порту

        x.__listen (@serverSocket = socketIO(3990)), '/origin'

потом подключаем к X.Clone объект

        X.Clone.connect (@clientSocket = socketIOClient.connect('http://localhost:3990/origin')), (err, clone) ->

          if err then done.fail(err); return

          expect(clone).toBeDefined()
          expect(clone).not.toBeNull()

          done()
          return

или connect к Origin объекту

      it '060', (done) ->

        class X extends CloudState

          @makeOriginAndClone()

сперва воздаем X.Clone, который слушает на порту когда появится X.Origin

        X.Clone.listen (@serverSocket = socketIO(3990)), '/clone', (err, clone) ->

          if err then done.fail(err); return

          expect(clone).toBeDefined()
          expect(clone).not.toBeNull()

          done()
          return

потом создаем X.Origin, который подключается к X.Clone

        x = new X.Origin()
        x.__connect (@clientSocket = socketIOClient.connect('http://localhost:3990/clone'))


source-map

source-map

# Webpack Configuration

[Webpack](https://github.com/webpack/webpack) handles asset compilation (Sass, CoffeeScript, etc).
It also manages loading via JavaScript `require`, Sass `@import`, and CSS `url()`.

First, require the dependencies:

    webpack = require('webpack')
    fs      = require('fs')
    path    = require('path')
    _       = require('lodash')

Define an empty configuration:

    module.exports = {}

Entry bundles, i.e. package source paths. See [docs](http://webpack.github.io/docs/configuration.html#entry).

    entries = module.exports.entry =
      "main"            : "./src/scripts/main.litcoffee"
      "styles"          : "./src/styles/styles.scss"
      "vendor/es5-shim" : "./bower_components/es5-shim/es5-shim.js"
      "vendor/es5-sham" : "./bower_components/es5-shim/es5-sham.js"

Define compiled distribution output directory:

    outputDir = path.join(__dirname, "dist", "assets")

## Loaders

Define how files should be loaded (required) based on the extension.

### Scripts

Process CoffeeScript and JSX.

    jsLoaders = ["jsx"]
    scriptModLoaders = [
      { test: /\.coffee$/   , loaders: jsLoaders.concat(["coffee"]) }
      { test: /\.litcoffee$/, loaders: jsLoaders.concat(["coffee?literate"]) }
      { test: /\.js$/       , loaders: jsLoaders }
    ]

### Styles

Process Sass and use Autoprefixer.

    cssLoaders = ['style', 'css', 'autoprefixer-loader?last 2 versions']
    styleModLoaders = [
      { test: /\.scss$/, loaders: cssLoaders.concat([
          "sass?precision=10&outputStyle=expanded&sourceMap=true&includePaths[]=" + path.resolve(__dirname, './bower_components')]) }
      { test: /\.css$/ , loaders: cssLoaders }
    ]

### Static assets

Embed data-URLs into CSS and JS for small images and `.woff` fonts:

    staticModLoaders = [
      { test: /\.gif$/ , loader: "url?limit=10000&mimetype=image/gif" }
      { test: /\.jpg$/ , loader: "url?limit=10000&mimetype=image/jpg" }
      { test: /\.png$/ , loader: "url?limit=10000&mimetype=image/png" }
      { test: /\.woff$/, loader: "url?limit=10000&mimetype=application/font-woff" }
      { test: /\.ttf$/ , loader: "file?mimetype=application/vnd.ms-fontobject" }
      { test: /\.eot$/ , loader: "file?mimetype=application/x-font-ttf" }
      { test: /\.svg$/ , loader: "file?mimetype=image/svg+xml" }
    ]

### Output CSS to `.css` files

`ExtractTextPlugin` is an experimental plugin to output CSS in `.css` and not as `.js` files with embedded CSS strings.

Require the plugin:

    ExtractTextPlugin = require("extract-text-webpack-plugin")

Set `styleModLoaders` to use the plugin:

    styleModLoaders = styleModLoaders.map (e) ->
      { test: e.test, loader: ExtractTextPlugin.extract(e.loaders.slice(1).join('!')) }

Create an instance of the extractTextPlugin:

    extractTextPlugin = new ExtractTextPlugin("[name].css", allChunks: true)

### Define macro variables

`DefinePlugin` defines variables to be substituted in the assets (a la macro).

Define `__PRODUCTION__: false` variable (set to true on `useProductionSettings()`):

    definePlugin = new webpack.DefinePlugin(
      __PRODUCTION__: JSON.stringify(false)
    )

### Other options

    _.merge module.exports,

Set compilation target to "web". See [docs](http://webpack.github.io/docs/configuration.html#target).

      target: "web"

Set development options by default:

      debug: true
      # We are watching in Gulp, so tell webpack not to watch
      watch: false
      # watchDelay: 300
      devtool: 'source-map'

Output options:

      output:
        path         : outputDir
        publicPath   : "/assets/"
        filename     : "[name].js"
        chunkFilename: "[name].[id].[chunkhash].js"

Look for required files in bower and node

      resolve:
        modulesDirectories: ['bower_components', 'node_modules']

Define how modules should be loaded based on path extension:

      module:
        loaders: styleModLoaders.concat(scriptModLoaders).concat(staticModLoaders)
        noParse: /\.min\.js$/

Define the plugins:

      plugins: [

`definePlugin` defines variables to be substituted in the assets (a la macro):

        definePlugin

`extractTextPlugin` (defined above) will compile CSS to a .css file, as opposed to inlining it as a string in a .js file.

        extractTextPlugin
      ]

## Production overrides

Export a method that applies production settings (used in gulpfile):

      mergeProductionConfig: ->

Production plugins:

Set `__PRODUCTION__` to true in the `DefinePlugin` instance:

        definePlugin.definitions.__PRODUCTION__ = JSON.stringify(true)

Tell `ExtractTextPlugin` to append hashes (BROKEN, see [plugin issue #9](https://github.com/webpack/extract-text-webpack-plugin/issues/9)):

        extractTextPlugin.filename = '[name]-[hash].css'

Merge in production config (deep merge):

        _.merge @,

Disable development settings:

          debug: false
          watch: false
          devtool: null

Add content hashes to the output filenames:

          output:
            filename: "[name]-[hash].js"

          plugins: @plugins.concat [

Minify JavaScript with UglifyJS:

            new webpack.optimize.UglifyJsPlugin()

Generate asset -> asset-hash manifest:

            generateManifestPlugin = (compiler) ->
              @plugin 'done', (stats) ->
                stats = stats.toJson()

Set target path extension to `.css` for style assets, because we use `ExtractTextPlugin`:

                assetStats = stats.assetsByChunkName
                setCssExt = (p) -> p.replace(/\.js$/, '.css')
                for entryName, entryPath of assetStats when /\.(?:scss|sass|css)$/.test(entries[entryName])
                  if _.isArray(entryPath)
                    assetStats[entryName] = entryPath.map (p) -> setCssExt(p)
                  else
                    assetStats[entryName] = setCssExt(entryPath)

Write asset-ref -> asset-hash manifest to outputDir/stats.json

                fs.writeFileSync(path.join(outputDir, "asset-stats.json"), JSON.stringify(stats.assetsByChunkName, null, 2))

          ]

# Webpack Configuration

[Webpack](https://github.com/webpack/webpack) handles asset compilation (Sass, CoffeeScript, etc).
It also manages loading via JavaScript `require`, Sass `@import`, and CSS `url()`.

First, require the dependencies:

    webpack = require('webpack')
    fs      = require('fs')
    path    = require('path')
    _       = require('lodash')

Define an empty configuration:

    module.exports = {}

Entry bundles, i.e. package source paths. See [docs](http://webpack.github.io/docs/configuration.html#entry).

    entries = module.exports.entry =
      "main"            : "./src/scripts/main.litcoffee"
      "styles"          : "./src/styles/styles.scss"
      "vendor/es5-shim" : "./bower_components/es5-shim/es5-shim.js"
      "vendor/es5-sham" : "./bower_components/es5-shim/es5-sham.js"

Define compiled distribution output directory:

    outputDir = path.join(__dirname, "dist", "assets")

## Loaders

Define how files should be loaded (required) based on the extension.

### Scripts

Process CoffeeScript and JSX.

    jsLoaders = ["jsx"]
    scriptModLoaders = [
      { test: /\.coffee$/   , loaders: jsLoaders.concat(["coffee"]) }
      { test: /\.litcoffee$/, loaders: jsLoaders.concat(["coffee?literate"]) }
      { test: /\.js$/       , loaders: jsLoaders }
    ]

### Styles

Process Sass and use Autoprefixer.

    cssLoaders = ['style', 'css', 'autoprefixer-loader?last 2 versions']
    styleModLoaders = [
      { test: /\.scss$/, loaders: cssLoaders.concat([
          "sass?precision=10&outputStyle=expanded&includePaths[]=" + path.resolve(__dirname, './bower_components')]) }
      { test: /\.css$/ , loaders: cssLoaders }
    ]

### Static assets

Embed data-URLs into CSS and JS for small images and `.woff` fonts:

    staticModLoaders = [
      { test: /\.gif$/ , loader: "url?limit=10000&mimetype=image/gif" }
      { test: /\.jpg$/ , loader: "url?limit=10000&mimetype=image/jpg" }
      { test: /\.png$/ , loader: "url?limit=10000&mimetype=image/png" }
      { test: /\.woff$/, loader: "url?limit=10000&mimetype=application/font-woff" }
      { test: /\.ttf$/ , loader: "file?mimetype=application/vnd.ms-fontobject" }
      { test: /\.eot$/ , loader: "file?mimetype=application/x-font-ttf" }
      { test: /\.svg$/ , loader: "file?mimetype=image/svg+xml" }
    ]

### Output CSS to `.css` files

`ExtractTextPlugin` is an experimental plugin to output CSS in `.css` and not as `.js` files with embedded CSS strings.

Require the plugin:

    ExtractTextPlugin = require("extract-text-webpack-plugin")

Set `styleModLoaders` to use the plugin:

    styleModLoaders = styleModLoaders.map (e) ->
      { test: e.test, loader: ExtractTextPlugin.extract(e.loaders.slice(1).join('!')) }

Create an instance of the extractTextPlugin:

    extractTextPlugin = new ExtractTextPlugin("[name].css", allChunks: true)

### Define macro variables

`DefinePlugin` defines variables to be substituted in the assets (a la macro).

Define `__PRODUCTION__: false` variable (set to true on `useProductionSettings()`):

    definePlugin = new webpack.DefinePlugin(
      __PRODUCTION__: JSON.stringify(false)
    )

### Other options

    _.merge module.exports,

Set compilation target to "web". See [docs](http://webpack.github.io/docs/configuration.html#target).

      target: "web"

Set development options by default:

      debug: true
      # We are watching in Gulp, so tell webpack not to watch
      watch: false
      # watchDelay: 300

Output options:

      output:
        path         : outputDir
        publicPath   : "/assets/"
        filename     : "[name].js"
        chunkFilename: "[name].[id].[chunkhash].js"

Look for required files in bower and node

      resolve:
        modulesDirectories: ['bower_components', 'node_modules']

Define how modules should be loaded based on path extension:

      module:
        loaders: styleModLoaders.concat(scriptModLoaders).concat(staticModLoaders)
        noParse: /\.min\.js$/

Define the plugins:

      plugins: [

`definePlugin` defines variables to be substituted in the assets (a la macro):

        definePlugin

`extractTextPlugin` (defined above) will compile CSS to a .css file, as opposed to inlining it as a string in a .js file.

        extractTextPlugin
      ]

## Production overrides

Export a method that applies production settings (used in gulpfile):

      mergeProductionConfig: ->

Production plugins:

Set `__PRODUCTION__` to true in the `DefinePlugin` instance:

        definePlugin.definitions.__PRODUCTION__ = JSON.stringify(true)

Tell `ExtractTextPlugin` to append hashes (BROKEN, see [plugin issue #9](https://github.com/webpack/extract-text-webpack-plugin/issues/9)):

        extractTextPlugin.filename = '[name]-[hash].css'

Merge in production config (deep merge):

        _.merge @,

Disable development settings:

          debug: false
          watch: false
          devtool: null

Add content hashes to the output filenames:

          output:
            filename: "[name]-[hash].js"

          plugins: @plugins.concat [

Minify JavaScript with UglifyJS:

            new webpack.optimize.UglifyJsPlugin()

Generate asset -> asset-hash manifest:

            generateManifestPlugin = (compiler) ->
              @plugin 'done', (stats) ->
                stats = stats.toJson()

Set target path extension to `.css` for style assets, because we use `ExtractTextPlugin`:

                assetStats = stats.assetsByChunkName
                for entryName, entryPath of assetStats
                  if /\.(?:scss|sass|css)$/.test(entries[entryName])
                    assetStats[entryName] = entryPath.replace(/\.js$/, '.css')

Write asset-ref -> asset-hash manifest to outputDir/stats.json

                fs.writeFileSync(path.join(outputDir, "asset-stats.json"), JSON.stringify(stats.assetsByChunkName, null, 2))

          ]


Add constraint to defining resources

Add constraint to defining resources

# UBER and Hyperdescribe

The goal of this document is to outline how Hyperdescribe would be used to describe a UBER document according to the [current specs](https://rawgithub.com/mamund/media-types/e034e9d9eae7fb4455f25c928cb84cd513f9472c/uber-hypermedia.html). This document will look at the JSON variant of the UBER format.

    _ = require 'underscore'

    cleanItem = (data) ->
      _.reduce data, (total, value, key) ->
        total[key] = value if value? and value.length != 0
        total
      , {}

## Types

Even though UBER really only has one data element, `data`, this data element can be treated differently depending on the context. This section will look at each of these different types along with the conditions for those types and the means to describe them with Hyperdescribe.

### Transitions

In Hyperdescribe, there are two types of transitions:

1. Links
2. Actions

In the UBER spec, though, links and actions are not separated in this way, so this document will specify how it is determined whether an item is a link or an action.

#### Links

Items in UBER that are considered links in Hyperdescribe are items with `read` as the action. If the `@action` attribute is absent and the `@url` attribute is present, the action is assumed to be `read`. Additionally, if the action specified is not listed in the spec, it should be treated as `read`. This is according to the UBER spec.

For an item to be considered a link, it MUST have a `@url` attribute, it MUST NOT have any data, and it MUST be a `read` action.

    #getPropertyName = (data) ->
    #  if data.id? then id else data.name

    hasData = (data, level) ->
      data.data? and data.data?.length != 0

    isReadAction = (data) ->
      (!data.action? or
        data.action == 'read' or
        data.action not in _.keys(availableActions))

    isLink = (data, level) ->
      data.url? and !hasData(data, level) and isReadAction(data)

    mapLink = (data) ->
      linkUrl = if data.model? then data.url + data.model else data.url

      link =
        id: data.id
        name: data.name
        rel: data.rel
        #property: getPropertyName(data)
        transclude: data.transclude
        types: data.accepting
        label: data.value

      link.href = if data.model? then data.url + data.model else data.url
      link.template = true if data.model?

      link

#### Actions

UBER only specifies available actions and also provides a mapping of these actions to their corresponding HTTP verbs (see [section 4.1.1](https://rawgithub.com/mamund/media-types/master/uber-hypermedia.html#_mapping_uber_tt_action_tt_values_to_http_methods)).

    availableActions =
      append: 'POST'
      partial: 'PATCH'
      read: 'GET'
      remove: 'DELETE'
      replace: 'PUT'

Items that are considered actions MUST have an `@action` attribute, MUST have a `@url`, MAY have a `@model`, and MUST use an avaiable action from the spec.

    isAction = (data, level) ->
      data.action? and
        data.url? and
        data.action in _.keys(availableActions)

According to 4.1.1, there are only three actions that modify the body of the message sent:

* append
* partial
* replace

Since `read` actions are handled by links, `remove` is the only action that needs special treatment.

    modifiesBody = [
      'append'
      'partial'
      'replace'
    ]

    parseBodyModel = (model) ->
      items = model.split('&').map (item) ->
        [key, value] = item.split('=')
        { name: key, type: "text", mapsTo: value[1..-2] }

    mapAction = (data) ->
      action =
        name: data.name
        rel: data.rel
        method: availableActions[data.action]
        sendAs: data.sending

If an action is one that does not modify the body, the model is added to the action's `@url` attribute and template is set to `true`, which conveys it is templated action.

      if data.action not in modifiesBody and data.model?
        action.url = data.url + data.model
        action.template = true

If the action does modify the body, the model is parsed and fields are created.

      if data.action in modifiesBody
        action.url = data.url
        action.fields = parseBodyModel(data.model)
      cleanItem(action)

### Properties

An item that is considered a property of a resource MUST have a `@value`, MUST NOT be at the root level (or in other words, MUST be a child element), MUST NOT be a transition, and MUST NOT have a `@data` attribute.

    isTransition = (data, level) ->
      isLink(data, level) or isAction(data, level)

    isProperty = (data, level) ->
      data.value? and level != 0 and !isTransition(data, level) and !hasData(data, level)

Currently, with regards to mapping to Hyperdescribe, the only relevant values will be `@name` and `@value`.

    mapProperty = (data) ->
      cleanItem
        name: data.name
        value: data.value

### Resources

An item considered a resource MUST NOT have an `@action` attribute and MUST have a `@data` attribute. Any `@value` attribute will be ignored. Like the `data` element in UBER, Hyperdescribe can handle nested resources.

    isResource = (data, level) ->
      !data.action? and hasData(data, level)

Mapping a resource from UBER to Hyperdescribe requires finding all of the links, actions, and properties, along with all nested resources. Once those are all found, they can then be mapped to how

    mapResource = (data, level) ->
      links = data.data.filter (d) -> isLink(d, level)
      actions = data.data.filter (d) -> isAction(d, level)
      resources = data.data.filter (d) -> isResource(d, level)
      properties = data.data.filter (d) -> isProperty(d, level)

      hLinks = links.map (link) -> mapLink(link)
      hActions = actions.map (action) -> mapAction(action)
      hResources = resources.map (resource) -> mapResource(resource, level + 1)
      hProperties = properties.map (property) -> mapProperty(property)

      cleanItem
        name: data.name
        links: hLinks
        actions: hActions
        resources: hResources
        properties: hProperties

## UBER Document

Mapping an UBER document to Hyperdescribe requires treating the root `@uber` element as a resource. Since each resource can have nested resources, Hyperdescribe should map each resource recursively.

    mapUberDocument = module.exports = (uber) -> mapResource(uber.uber, 0)

## Issues

1. There is currently no way to tell whether a nested link should be a property of the resource (e.g. the `avatarUrl` in the example in the spec) or just a normal link.
2. Is there any way to specify schema.org information for an UBER document?

# UBER and Hyperdescribe

The goal of this document is to outline how Hyperdescribe would be used to describe a UBER document according to the [current specs](https://rawgithub.com/mamund/media-types/e034e9d9eae7fb4455f25c928cb84cd513f9472c/uber-hypermedia.html). This document will look at the JSON variant of the UBER format.

    _ = require 'underscore'

    cleanItem = (data) ->
      _.reduce data, (total, value, key) ->
        total[key] = value if value? and value.length != 0
        total
      , {}

## Types

Even though UBER really only has one data element, `data`, this data element can be treated differently depending on the context. This section will look at each of these different types along with the conditions for those types and the means to describe them with Hyperdescribe.

### Transitions

In Hyperdescribe, there are two types of transitions:

1. Links
2. Actions

In the UBER spec, though, links and actions are not separated in this way, so this document will specify how it is determined whether an item is a link or an action.

#### Links

Items in UBER that are considered links in Hyperdescribe are items with `read` as the action. If the `@action` attribute is absent and the `@url` attribute is present, the action is assumed to be `read`. Additionally, if the action specified is not listed in the spec, it should be treated as `read`. This is according to the UBER spec.

For an item to be considered a link, it MUST have a `@url` attribute, it MUST NOT have any data, and it MUST be a `read` action.

    #getPropertyName = (data) ->
    #  if data.id? then id else data.name

    hasData = (data, level) ->
      data.data? and data.data?.length != 0

    isReadAction = (data) ->
      (!data.action? or
        data.action == 'read' or
        data.action not in _.keys(availableActions))

    isLink = (data, level) ->
      data.url? and !hasData(data, level) and isReadAction(data)

    mapLink = (data) ->
      linkUrl = if data.model? then data.url + data.model else data.url

      link =
        id: data.id
        name: data.name
        rel: data.rel
        #property: getPropertyName(data)
        transclude: data.transclude
        types: data.accepting
        label: data.value

      link.href = if data.model? then data.url + data.model else data.url
      link.template = true if data.model?

      link

#### Actions

UBER only specifies available actions and also provides a mapping of these actions to their corresponding HTTP verbs (see [section 4.1.1](https://rawgithub.com/mamund/media-types/master/uber-hypermedia.html#_mapping_uber_tt_action_tt_values_to_http_methods)).

    availableActions =
      append: 'POST'
      partial: 'PATCH'
      read: 'GET'
      remove: 'DELETE'
      replace: 'PUT'

Items that are considered actions MUST have an `@action` attribute, MUST have a `@url`, MAY have a `@model`, and MUST use an avaiable action from the spec.

    isAction = (data, level) ->
      data.action? and
        data.url? and
        data.action in _.keys(availableActions)

According to 4.1.1, there are only three actions that modify the body of the message sent:

* append
* partial
* replace

Since `read` actions are handled by links, `remove` is the only action that needs special treatment.

    modifiesBody = [
      'append'
      'partial'
      'replace'
    ]

    parseBodyModel = (model) ->
      items = model.split('&').map (item) ->
        [key, value] = item.split('=')
        { name: key, type: "text", mapsTo: value[1..-2] }

    mapAction = (data) ->
      action =
        name: data.name
        rel: data.rel
        method: availableActions[data.action]
        sendAs: data.sending

If an action is one that does not modify the body, the model is added to the action's `@url` attribute and template is set to `true`, which conveys it is templated action.

      if data.action not in modifiesBody and data.model?
        action.url = data.url + data.model
        action.template = true

If the action does modify the body, the model is parsed and fields are created.

      if data.action in modifiesBody
        action.url = data.url
        action.fields = parseBodyModel(data.model)
      cleanItem(action)

### Properties

An item that is considered a property of a resource MUST have a `@value`, MUST NOT be at the root level (or in other words, MUST be a child element), MUST NOT be a transition, and MUST NOT have a `@data` attribute.

    isTransition = (data, level) ->
      isLink(data, level) or isAction(data, level)

    isProperty = (data, level) ->
      data.value? and level != 0 and !isTransition(data, level) and !hasData(data, level)

Currently, with regards to mapping to Hyperdescribe, the only relevant values will be `@name` and `@value`.

    mapProperty = (data) ->
      cleanItem
        name: data.name
        value: data.value

### Resources

An item considered a resource MUST NOT have an `@action` attribute and MUST have a `@data` attribute. Like the `data` element in UBER, Hyperdescribe can handle nested resources.

    isResource = (data, level) ->
      !data.action? and hasData(data, level)

Mapping a resource from UBER to Hyperdescribe requires finding all of the links, actions, and properties, along with all nested resources. Once those are all found, they can then be mapped to how

    mapResource = (data, level) ->
      links = data.data.filter (d) -> isLink(d, level)
      actions = data.data.filter (d) -> isAction(d, level)
      resources = data.data.filter (d) -> isResource(d, level)
      properties = data.data.filter (d) -> isProperty(d, level)

      hLinks = links.map (link) -> mapLink(link)
      hActions = actions.map (action) -> mapAction(action)
      hResources = resources.map (resource) -> mapResource(resource, level + 1)
      hProperties = properties.map (property) -> mapProperty(property)

      cleanItem
        name: data.name
        links: hLinks
        actions: hActions
        resources: hResources
        properties: hProperties

## UBER Document

Mapping an UBER document to Hyperdescribe requires treating the root `@uber` element as a resource. Since each resource can have nested resources, Hyperdescribe should map each resource recursively.

    mapUberDocument = module.exports = (uber) -> mapResource(uber.uber, 0)

## Issues

1. There is currently no way to tell whether a nested link should be a property of the resource (e.g. the `avatarUrl` in the example in the spec) or just a normal link.
2. Is there any way to specify schema.org information for an UBER document?


<script> coffeescript files fixed

<script> coffeescript files fixed

# script

    'use strict'

    fs = require 'fs-extra'
    os = require 'os'
    utils = require 'src/utils'
    pathUtils = require 'path'
    {getFilePath} = require './links'

    uid = 0
    realpath = fs.realpathSync './'
    tmpdir = os.tmpdir()

    isCoffee = (path) -> /\.(?:coffee|litcoffee|coffee\.md)$/.test(path)
    getScriptPath = (filename) ->
        extname = (filename and pathUtils.extname(filename)) or '.js'
        "build/scripts/#{uid++}#{extname}"

    module.exports = (File) -> (file) ->
        if file instanceof File.Iterator
            return

        scripts = []

        for tag in file.node.queryAll('script')
            omit = false
            for attr of tag.attrs
                if attr not in ['src', 'href', 'filename']
                    omit = true
                    break
            if omit
                continue

            tag.parent = null

            {src} = tag.attrs
            src ||= tag.attrs.href

            if src
                src = getFilePath File, file, src
                path = getScriptPath src
                fs.copySync src, path
                scripts.push path
            else
                # tag body
                str = tag.stringifyChildren()
                path = getScriptPath tag.attrs.filename
                if isCoffee(path)
                    str = "`module.exports = function(){`\n\n#{str}\n\n`};`"
                else
                    str = "module.exports = function(){\n\n#{str}\n\n};"
                fs.outputFileSync path, str
                scripts.push path

        file.scripts = new File.Scripts file, scripts

        return

# Glossary

- [script](#neftscript)

# script

    'use strict'

    fs = require 'fs-extra'
    os = require 'os'
    utils = require 'src/utils'
    pathUtils = require 'path'
    {getFilePath} = require './links'

    uid = 0
    realpath = fs.realpathSync './'
    tmpdir = os.tmpdir()

    isCoffee = (path) -> /\.(?:coffee|litcoffee|coffee\.md)$/.test(path)
    getScriptPath = (filename) ->
        extname = (filename and pathUtils.extname(filename)) or '.js'
        "build/scripts/#{uid++}.js"

    module.exports = (File) -> (file) ->
        if file instanceof File.Iterator
            return

        scripts = []

        for tag in file.node.queryAll('script')
            omit = false
            for attr of tag.attrs
                if attr not in ['src', 'href', 'filename']
                    omit = true
                    break
            if omit
                continue

            tag.parent = null

            {src} = tag.attrs
            src ||= tag.attrs.href

            if src
                src = getFilePath File, file, src
                path = getScriptPath src
                fs.copySync src, path
                scripts.push path
            else
                # tag body
                str = tag.stringifyChildren()
                path = getScriptPath tag.attrs.filename
                if isCoffee(path)
                    str = "`module.exports = function(){`\n\n#{str}\n\n`};`"
                else
                    str = "module.exports = function(){\n\n#{str}\n\n};"
                fs.outputFileSync path, str
                scripts.push path

        file.scripts = new File.Scripts file, scripts

        return

# Glossary

- [script](#neftscript)


Use eachSeries instead of each

Use eachSeries instead of each

While processing dependencies in parallel would be awesome, it is not to be ...

The only way to ensure that a dependency is fully loaded before moving on to
the next one is to load the dependencies serially.

    Array.prototype.last = -> this[this.length - 1]

    q     = require 'q'
    fs    = require 'fs'
    async = require 'async'

    microtime = require 'microtime'

    logger = require './logger'

    classes     = { }
    available   = { }
    initialized = { }

    class Madul

      constructor: (madul_name, class_name) ->
        @debug = (msg, data) -> logger.debug msg, data
        @info  = (msg, data) -> logger.info  msg, data
        @warn  = (msg, data) -> logger.warn  msg, data
        @error = (msg, data) -> logger.error msg, data

        @clazz       = class_name || arguments.callee.caller.name
        @madul_name  = madul_name

        classes[@clazz] = madul_name

        initialized[@clazz] = false unless initialized[@clazz] == true

        logger.trace "Instantiating #{@clazz}"

      do_wrap: (method) =>
        callMe = @[method]

        @["_#{method}"] = @[method]

        @[method] = =>
          deferred = q.defer()
          start    = microtime.now()
          update   = start

          respond = (state, data) =>
            deferred[state] data

            if state == 'reject'
              logger.rejected @clazz, method, microtime.now() - start, data

            if process.env.MADUL_LOG_LEVEL > 4
              if state == 'resolve'
                logger.resolved @clazz, method, microtime.now() - start, data
              else if state == 'notify'
                logger.notify @clazz, method, microtime.now() - update, data
                update = microtime.now()

          @done   = (out) => respond 'resolve', out
          @fail   = (err) => respond 'reject',  err
          @update = (out) => respond 'notify',  out

          args = Array.prototype.slice.call arguments

          logger.trace "Invoking #{@clazz}.#{method}()", args

          @["_#{method}"].apply null, args

          deferred.promise

      wrap_methods: => @pub?.forEach (method) => @do_wrap method

      hydrate: (deps, done) =>
        load = (name, path, loaded) =>
          mod = require path

          if typeof mod == 'function'
            new mod name
              .initialize @ctor_params?[name]
              .then (mod) =>
                available[name] = mod
                loaded true
          else
            available[name] = mod
            loaded true

        check_directory = (path, dep, loaded) =>
          fs.readdir path, (err, files) =>
            if err?
              done type: 'ERROR', info: err
            else
              async.each files, (f, next) =>
                depth = "#{path}/#{f}"

                fs.stat depth, (e, s) =>
                  if s.isDirectory() && f[0] != '.'
                    check_directory depth, dep, => next()
                  else if s.isFile() && f.substring(0, f.length - 3) == dep
                    load f.substring(0, f.length - 3), depth, => loaded true
                  else
                    next()
              , => loaded true

        add_dependency = (name, mod) =>
          n = name.replace /\W+/g, '_'
          @[n] = mod

        async.eachSeries deps, (d, next) =>
          if @[d]? == false
            if available[d]? == true
              add_dependency d, available[d]
              next()
            else
              try
                available[d] = require d
                add_dependency d, available[d]
                next()
              catch e
                pkg = "#{process.cwd()}/node_modules/#{d}/package.json"

                fs.stat pkg, (err, stat) =>
                  if stat?.isFile()
                    fs.readFile pkg, 'utf8', (err, data) =>
                      json = JSON.parse data
                      main = json.main || json._main

                      available[d] = require "#{process.cwd()}/node_modules/#{d}/#{main}"

                      add_dependency d, available[d]
                      next()
                  else
                    check_directory "#{process.cwd()}/dist", d, (loaded) =>
                      if loaded
                        add_dependency d, available[d]
                        next()
          else
            next()
        , done

      finish_up: (resolve, args) =>
        if typeof @post_initialize == 'function'
          @do_wrap 'post_initialize'
          @post_initialize(args)
            .then =>
              available[classes[@clazz]] = @
              resolve @
        else
          available[classes[@clazz]] = @
          resolve @

      initialize: (args = { }, wrap = true) =>
        deferred = q.defer()

        if initialized[@clazz] == false
          initialized[@clazz] = true

          @wrap_methods() if wrap

          if @deps?
            @hydrate @deps, => @finish_up deferred.resolve, args
          else
            @finish_up deferred.resolve, args
        else
          process.nextTick => deferred.resolve available[classes[@clazz]]

        deferred.promise

    module.exports = Madul

    Array.prototype.last = -> this[this.length - 1]

    q     = require 'q'
    fs    = require 'fs'
    async = require 'async'

    microtime = require 'microtime'

    logger = require './logger'

    classes     = { }
    available   = { }
    initialized = { }

    class Madul

      constructor: (madul_name, class_name) ->
        @debug = (msg, data) -> logger.debug msg, data
        @info  = (msg, data) -> logger.info  msg, data
        @warn  = (msg, data) -> logger.warn  msg, data
        @error = (msg, data) -> logger.error msg, data

        @clazz       = class_name || arguments.callee.caller.name
        @madul_name  = madul_name

        classes[@clazz] = madul_name

        initialized[@clazz] = false unless initialized[@clazz] == true

        logger.trace "Instantiating #{@clazz}"

      do_wrap: (method) =>
        callMe = @[method]

        @["_#{method}"] = @[method]

        @[method] = =>
          deferred = q.defer()
          start    = microtime.now()
          update   = start

          respond = (state, data) =>
            deferred[state] data

            if state == 'reject'
              logger.rejected @clazz, method, microtime.now() - start, data

            if process.env.MADUL_LOG_LEVEL > 4
              if state == 'resolve'
                logger.resolved @clazz, method, microtime.now() - start, data
              else if state == 'notify'
                logger.notify @clazz, method, microtime.now() - update, data
                update = microtime.now()

          @done   = (out) => respond 'resolve', out
          @fail   = (err) => respond 'reject',  err
          @update = (out) => respond 'notify',  out

          args = Array.prototype.slice.call arguments

          logger.trace "Invoking #{@clazz}.#{method}()", args

          @["_#{method}"].apply null, args

          deferred.promise

      wrap_methods: => @pub?.forEach (method) => @do_wrap method

      hydrate: (deps, done) =>
        load = (name, path, loaded) =>
          mod = require path

          if typeof mod == 'function'
            new mod name
              .initialize @ctor_params?[name]
              .then (mod) =>
                available[name] = mod
                loaded true
          else
            available[name] = mod
            loaded true

        check_directory = (path, dep, loaded) =>
          fs.readdir path, (err, files) =>
            if err?
              done type: 'ERROR', info: err
            else
              async.each files, (f, next) =>
                depth = "#{path}/#{f}"

                fs.stat depth, (e, s) =>
                  if s.isDirectory() && f[0] != '.'
                    check_directory depth, dep, => next()
                  else if s.isFile() && f.substring(0, f.length - 3) == dep
                    load f.substring(0, f.length - 3), depth, => loaded true
                  else
                    next()
              , => loaded true

        add_dependency = (name, mod) =>
          n = name.replace /\W+/g, '_'
          @[n] = mod

        async.each deps, (d, next) =>
          if @[d]? == false
            if available[d]? == true
              add_dependency d, available[d]
              next()
            else
              try
                available[d] = require d
                add_dependency d, available[d]
                next()
              catch e
                pkg = "#{process.cwd()}/node_modules/#{d}/package.json"

                fs.stat pkg, (err, stat) =>
                  if stat?.isFile()
                    fs.readFile pkg, 'utf8', (err, data) =>
                      json = JSON.parse data
                      main = json.main || json._main

                      available[d] = require "#{process.cwd()}/node_modules/#{d}/#{main}"

                      add_dependency d, available[d]
                      next()
                  else
                    check_directory "#{process.cwd()}/dist", d, (loaded) =>
                      if loaded
                        add_dependency d, available[d]
                        next()
          else
            next()
        , done

      finish_up: (resolve, args) =>
        if typeof @post_initialize == 'function'
          @do_wrap 'post_initialize'
          @post_initialize(args)
            .then =>
              available[classes[@clazz]] = @
              resolve @
        else
          available[classes[@clazz]] = @
          resolve @

      initialize: (args = { }, wrap = true) =>
        deferred = q.defer()

        if initialized[@clazz] == false
          initialized[@clazz] = true

          @wrap_methods() if wrap

          if @deps?
            @hydrate @deps, => @finish_up deferred.resolve, args
          else
            @finish_up deferred.resolve, args
        else
          process.nextTick => deferred.resolve available[classes[@clazz]]

        deferred.promise

    module.exports = Madul


Fix typo check for proper end case

Fix typo check for proper end case

**SUPER IMPORTANT** Since we're using `@grid` directly now, and `@grid`
is an array, we need ot make sure we're checking for `@grid.length - 1`
or else `Carver` will never think it's done.

    Module = require './module'

    class Carver extends Module
      pub: [ 'carve_path' ]

      grid:  undefined
      row:   0
      col:   0
      steps: 0
      path:  [ ]

      previous_direction: undefined
      total_distance:     0
      director:           undefined
      farthest_right:
        row: 0
        col: 0

      directions:
        LEFT:  0
        RIGHT: 1
        UP:    2
        DOWN:  3

      initialize: (grid, starting_row, director) =>
        @grid  = grid
        @path  = [ ]
        @row   = starting_row
        @col   = 0

        @farthest_right     = row: @row, col: 0
        @previous_direction = undefined

        @steps          = 0
        @total_distance = 0

        @director = director

        @grid[@row][@col] = true
        @path.push row: @row, col: @col

        super()

      update_steps: (dir) =>
        if @previous_direction?
          if @previous_direction == @directions[dir]
            ++@steps
          else
            @steps = 0
        else
          @previous_direction = @directions[dir]
          @steps = 0

      neighbor: (x = 0, y = 0) => @grid[@row + x][@col + y]

      carve_path: =>
        neighbors = [ ]
        width     = @grid[0].length
        height    = @grid.length

        neighbors.push 'UP'    if @row > 0          && @neighbor(-1,  0) == false
        neighbors.push 'DOWN'  if @row < height - 2 && @neighbor( 1,  0) == false
        neighbors.push 'LEFT'  if @col > 0          && @neighbor( 0, -1) == false
        neighbors.push 'RIGHT' if @col < width      && @neighbor( 0,  1) == false

        if neighbors.length == 0
          @col = @farthest_right.col
          @row = @farthest_right.row

          @carve_path()
        else
          direction = @director neighbors

          switch @directions[direction]
            when @directions.RIGHT then @grid[@row][++@col] = true
            when @directions.LEFT  then @grid[@row][--@col] = true
            when @directions.UP    then @grid[--@row][@col] = true
            when @directions.DOWN  then @grid[++@row][@col] = true
            when undefined         then return @carve_path()

          @update_steps direction

          if @col > @farthest_right.col
            @farthest_right.col = @col
            @farthest_right.row = @row

          if @farthest_right.col < @grid[0].length - 1
            @path.push row: @row, col: @col, direction: direction

            stats =
              position:
                row: @row
                col: @col
              steps: @steps
              direction: direction
              distance: ++@total_distance

            @update stats

            @carve_path()
          else
            @done @path

    module.exports = Carver

    Module = require './module'

    class Carver extends Module
      pub: [ 'carve_path' ]

      grid:  undefined
      row:   0
      col:   0
      steps: 0
      path:  [ ]

      previous_direction: undefined
      total_distance:     0
      director:           undefined
      farthest_right:
        row: 0
        col: 0

      directions:
        LEFT:  0
        RIGHT: 1
        UP:    2
        DOWN:  3

      initialize: (grid, starting_row, director) =>
        @grid  = grid
        @path  = [ ]
        @row   = starting_row
        @col   = 0

        @farthest_right     = row: @row, col: 0
        @previous_direction = undefined

        @steps          = 0
        @total_distance = 0

        @director = director

        @grid[@row][@col] = true
        @path.push row: @row, col: @col

        super()

      update_steps: (dir) =>
        if @previous_direction?
          if @previous_direction == @directions[dir]
            ++@steps
          else
            @steps = 0
        else
          @previous_direction = @directions[dir]
          @steps = 0

      neighbor: (x = 0, y = 0) => @grid[@row + x][@col + y]

      carve_path: =>
        neighbors = [ ]
        width     = @grid[0].length
        height    = @grid.length

        neighbors.push 'UP'    if @row > 0          && @neighbor(-1,  0) == false
        neighbors.push 'DOWN'  if @row < height - 2 && @neighbor( 1,  0) == false
        neighbors.push 'LEFT'  if @col > 0          && @neighbor( 0, -1) == false
        neighbors.push 'RIGHT' if @col < width      && @neighbor( 0,  1) == false

        if neighbors.length == 0
          @col = @farthest_right.col
          @row = @farthest_right.row

          @carve_path()
        else
          direction = @director neighbors

          switch @directions[direction]
            when @directions.RIGHT then @grid[@row][++@col] = true
            when @directions.LEFT  then @grid[@row][--@col] = true
            when @directions.UP    then @grid[--@row][@col] = true
            when @directions.DOWN  then @grid[++@row][@col] = true
            when undefined         then return @carve_path()

          @update_steps direction

          if @col > @farthest_right.col
            @farthest_right.col = @col
            @farthest_right.row = @row

          if @farthest_right.col < @gred[0].length
            @path.push row: @row, col: @col, direction: direction

            stats =
              position:
                row: @row
                col: @col
              steps: @steps
              direction: direction
              distance: ++@total_distance

            @update stats

            @carve_path()
          else
            @done @path

    module.exports = Carver


Each magic method invokation gets it's own promise

    q  = require 'q'
    fs = require 'fs'

    microtime = require 'microtime'

    logger = require './logger'

    available = { }
    loaded    = { }
    processed = { }

    class Module

      constructor: ->
        @debug = (msg, data) -> logger.debug msg, data
        @info  = (msg, data) -> logger.info  msg, data
        @warn  = (msg, data) -> logger.warn  msg, data
        @error = (msg, data) -> logger.error msg, data

        if arguments.length == 0 || arguments[0] == ''
          @clazz = arguments.callee.caller.name
        else
          @clazz = arguments[0]

        logger.trace "Instantiating #{@clazz}"

      wrap_methods: =>
        @pub?.forEach (method) =>
          callMe   = @[method]

          @["_#{method}"] = @[method]

          @[method] = =>
            deferred = q.defer()
            start    = microtime.now()
            update   = start

            respond = (state, data) =>
              process.nextTick =>
                deferred[state] data

                if state == 'reject'
                  logger.rejected @clazz, method, microtime.now() - start, data

                if process.env.MADUL_LOG_LEVEL > 4
                  if state == 'resolve'
                    logger.resolved @clazz, method, microtime.now() - start, data
                  else if state == 'notify'
                    logger.notify @clazz, method, microtime.now() - update, data
                    update = microtime.now()

            @done   = (out) => respond 'resolve', out
            @fail   = (err) => respond 'reject',  err
            @update = (out) => respond 'notify',  out

            args = Array.prototype.slice.call arguments

            logger.trace "Invoking #{@clazz}.#{method}()", args

            @["_#{method}"].apply null, args

            deferred.promise

      hydrate_dependencies: =>
        def = q.defer()
        good_to_go = false

        load = (name, path, cb) =>
          if available[name]? == false
            mod = require path

            if typeof mod == 'function'
              new mod()
                .initialize @ctor_params?[name]
                .then (mod) =>
                  available[name] = mod
                  cb()
            else
              available[name] = mod
              cb()
          else
            cb()

        check_directory = (path, dep, cb) =>
          fs.readdir path, (err, files) =>
            if err?
              def.reject type: 'ERROR', info: err
            else
              to_check = files.length
              checked = 0

              files.forEach (f) =>
                depth = "#{path}/#{f}"

                fs.lstat depth, (e, s) =>
                  if s.isDirectory()
                    check_directory depth, dep, =>
                      cb() if ++checked == to_check
                  else if s.isFile()
                    if f == 'index.js' || f.includes '.spec.'
                      cb() if ++checked == to_check
                    else
                      name = f.substring 0, f.length - 3

                      if name == dep
                        load name, depth, => cb() if ++checked == to_check
                      else
                        cb() if ++checked == to_check

        register_dependency = (name, mod) =>
          n = name.replace /\W+/g, '_'
          @[n] = mod

          def.notify type: 'NOTICE', loaded: n

          unless loaded[@clazz]?
            loaded[@clazz] = [ ]

          unless processed[@clazz]?
            processed[@clazz] = 0

          unless loaded[@clazz].indexOf(name) > -1
            loaded[@clazz].push name
            ++processed[@clazz]

          logger.trace 'Registered dependency', "#{@clazz}": "#{n}(file: #{name})"

          if processed[@clazz] >= @deps.length
            if loaded[@clazz].length >= @deps.length
              logger.trace "Loaded all dependencies: #{@clazz}", loaded[@clazz]
              def.resolve @
            else
              not_loaded = [ ]

              @deps.forEach (d) -> not_loaded.push(d) unless loaded[@clazz].indexOf(d) > -1

              logger.error "Failed loading dependencies for: #{@clazz}", not_loaded

              def.reject type: 'ERROR', not_loaded: not_loaded

        @deps?.forEach (d) =>
          if @[d]?
            good_to_go = true
          else
            if available[d]? == true
              register_dependency d, available[d]
            else
              try
                available[d] = require d
                register_dependency d, available[d]
              catch
                check_directory __dirname, d, =>
                  register_dependency d, available[d]

        if good_to_go && loaded[@clazz].length >= @deps.length
          process.nextTick => def.resolve @

        def.promise

      initialize: (wrap = true) =>
        deferred = q.defer()

        if @deps?
          @hydrate_dependencies()
            .then =>
              @wrap_methods() if wrap
              deferred.resolve @
            .fail (reason) => deferred.reject reason
        else
          process.nextTick =>
            @wrap_methods() if wrap
            deferred.resolve @

        deferred.promise

    module.exports = Module

    q  = require 'q'
    fs = require 'fs'

    microtime = require 'microtime'

    logger = require './logger'

    available = { }
    loaded    = { }
    processed = { }

    class Module

      constructor: ->
        @debug = (msg, data) -> logger.debug msg, data
        @info  = (msg, data) -> logger.info  msg, data
        @warn  = (msg, data) -> logger.warn  msg, data
        @error = (msg, data) -> logger.error msg, data

        if arguments.length == 0 || arguments[0] == ''
          @clazz = arguments.callee.caller.name
        else
          @clazz = arguments[0]

        logger.trace "Instantiating #{@clazz}"

      wrap_methods: =>
        @pub?.forEach (method) =>
          callMe   = @[method]
          deferred = q.defer()

          @["_#{method}"] = @[method]

          @[method] = =>
            start    = microtime.now()
            update   = start

            respond = (state, data) =>
              process.nextTick =>
                deferred[state] data

                if state == 'reject'
                  logger.rejected @clazz, method, microtime.now() - start, data

                if process.env.MADUL_LOG_LEVEL > 4
                  if state == 'resolve'
                    logger.resolved @clazz, method, microtime.now() - start, data
                  else if state == 'notify'
                    logger.notify @clazz, method, microtime.now() - update, data
                    update = microtime.now()

            @done   = (out) => respond 'resolve', out
            @fail   = (err) => respond 'reject',  err
            @update = (out) => respond 'notify',  out

            args = Array.prototype.slice.call arguments

            logger.trace "Invoking #{@clazz}.#{method}()", args

            @["_#{method}"].apply null, args

            deferred.promise

      hydrate_dependencies: =>
        def = q.defer()
        good_to_go = false

        load = (name, path, cb) =>
          if available[name]? == false
            mod = require path

            if typeof mod == 'function'
              new mod()
                .initialize @ctor_params?[name]
                .then (mod) =>
                  available[name] = mod
                  cb()
            else
              available[name] = mod
              cb()
          else
            cb()

        check_directory = (path, dep, cb) =>
          fs.readdir path, (err, files) =>
            if err?
              def.reject type: 'ERROR', info: err
            else
              to_check = files.length
              checked = 0

              files.forEach (f) =>
                depth = "#{path}/#{f}"

                fs.lstat depth, (e, s) =>
                  if s.isDirectory()
                    check_directory depth, dep, =>
                      cb() if ++checked == to_check
                  else if s.isFile()
                    if f == 'index.js' || f.includes '.spec.'
                      cb() if ++checked == to_check
                    else
                      name = f.substring 0, f.length - 3

                      if name == dep
                        load name, depth, => cb() if ++checked == to_check
                      else
                        cb() if ++checked == to_check

        register_dependency = (name, mod) =>
          n = name.replace /\W+/g, '_'
          @[n] = mod

          def.notify type: 'NOTICE', loaded: n

          unless loaded[@clazz]?
            loaded[@clazz] = [ ]

          unless processed[@clazz]?
            processed[@clazz] = 0

          unless loaded[@clazz].indexOf(name) > -1
            loaded[@clazz].push name
            ++processed[@clazz]

          logger.trace 'Registered dependency', "#{@clazz}": "#{n}(file: #{name})"

          if processed[@clazz] >= @deps.length
            if loaded[@clazz].length >= @deps.length
              logger.trace "Loaded all dependencies: #{@clazz}", loaded[@clazz]
              def.resolve @
            else
              not_loaded = [ ]

              @deps.forEach (d) -> not_loaded.push(d) unless loaded[@clazz].indexOf(d) > -1

              logger.error "Failed loading dependencies for: #{@clazz}", not_loaded

              def.reject type: 'ERROR', not_loaded: not_loaded

        @deps?.forEach (d) =>
          if @[d]?
            good_to_go = true
          else
            if available[d]? == true
              register_dependency d, available[d]
            else
              try
                available[d] = require d
                register_dependency d, available[d]
              catch
                check_directory __dirname, d, =>
                  register_dependency d, available[d]

        if good_to_go && loaded[@clazz].length >= @deps.length
          process.nextTick => def.resolve @

        def.promise

      initialize: (wrap = true) =>
        deferred = q.defer()

        if @deps?
          @hydrate_dependencies()
            .then =>
              @wrap_methods() if wrap
              deferred.resolve @
            .fail (reason) => deferred.reject reason
        else
          process.nextTick =>
            @wrap_methods() if wrap
            deferred.resolve @

        deferred.promise

    module.exports = Module