Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
###
"use strict"

Quo.gesture.add
  name    : "rotation"
  events  : "rotate,rotating,rotateLeft,rotateRight".split(",")
  handler : do (gm = Quo.gesture) ->

    TRIGGER_ANGLE             = 5
    IMPOSIBLE_ROTATION_FACTOR = 20

    _target         = null
    _num_rotations  = 0
    _start          = null
    _last           = null

    start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0
        _start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > IMPOSIBLE_ROTATION_FACTOR
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null

    _sign = (num) -> if num < 0 then -1 else 1

    _rotation = (A, B) ->
```

Response:
/*
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
*/
"use strict";
Quo.gesture.add({
  name: "rotation",
  events: "rotate,rotating,rotateLeft,rotateRight".split(","),
  handler: (function(gm) {
    var IMPOSIBLE_ROTATION_FACTOR, TRIGGER_ANGLE, _last, _num_rotations, _rotation, _sign, _start, _target, end, move, start;
    TRIGGER_ANGLE = 5;
    IMPOSIBLE_ROTATION_FACTOR = 20;
    _target = null;
    _num_rotations = 0;
    _start = null;
    _last = null;
    start = function(target, data) {
      if (data.length === 2) {
        _target = target;
        _num_rotations = 0;
        return _start = _rotation(data[0], data[1]);
      }
    };
    move = function(target, data) {
      var delta;
      if (_start && data.length === 2) {
        delta = _rotation(data[0], data[1]) - _start;
        if (_last && Math.abs(_last.delta - delta) > IMPOSIBLE_ROTATION_FACTOR) {
          delta += 360 * _sign(_last.delta);
        }
        if (Math.abs(delta) > 360) {
          _num_rotations++;
          delta -= 360 * _sign(_last.delta);
        }
        _last = {
          touches: data,
          delta: delta,
          rotationsCount: _num_rotations
        };
        return _check(true);
      }
    };
    end = function(target, data) {
      if (_start && _last) {
        _check(false);
        _target = null;
        _num_rotations = 0;
        _start = null;
        _last = null;
        return _start = null;
      }
    };
    _sign = function(num) {
      if (num < 0) {
        return -1;
      } else {
        return 1;
      }
    };
    return _rotation = function(A, B) {};
  })(Quo.gesture)
});


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
/*
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
*/
"use strict";
Quo.gesture.add({
  name: "rotation",
  events: "rotate,rotating,rotateLeft,rotateRight".split(","),
  handler: (function(gm) {
    var IMPOSIBLE_ROTATION_FACTOR, TRIGGER_ANGLE, _last, _num_rotations, _rotation, _sign, _start, _target, end, move, start;
    TRIGGER_ANGLE = 5;
    IMPOSIBLE_ROTATION_FACTOR = 20;
    _target = null;
    _num_rotations = 0;
    _start = null;
    _last = null;
    start = function(target, data) {
      if (data.length === 2) {
        _target = target;
        _num_rotations = 0;
        return _start = _rotation(data[0], data[1]);
      }
    };
    move = function(target, data) {
      var delta;
      if (_start && data.length === 2) {
        delta = _rotation(data[0], data[1]) - _start;
        if (_last && Math.abs(_last.delta - delta) > IMPOSIBLE_ROTATION_FACTOR) {
          delta += 360 * _sign(_last.delta);
        }
        if (Math.abs(delta) > 360) {
          _num_rotations++;
          delta -= 360 * _sign(_last.delta);
        }
        _last = {
          touches: data,
          delta: delta,
          rotationsCount: _num_rotations
        };
        return _check(true);
      }
    };
    end = function(target, data) {
      if (_start && _last) {
        _check(false);
        _target = null;
        _num_rotations = 0;
        _start = null;
        _last = null;
        return _start = null;
      }
    };
    _sign = function(num) {
      if (num < 0) {
        return -1;
      } else {
        return 1;
      }
    };
    return _rotation = function(A, B) {};
  })(Quo.gesture)
});
```

Response:
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
###
"use strict"

Quo.gesture.add
  name    : "rotation"
  events  : "rotate,rotating,rotateLeft,rotateRight".split(",")
  handler : do (gm = Quo.gesture) ->

    TRIGGER_ANGLE             = 5
    IMPOSIBLE_ROTATION_FACTOR = 20

    _target         = null
    _num_rotations  = 0
    _start          = null
    _last           = null

    start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0
        _start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > IMPOSIBLE_ROTATION_FACTOR
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null

    _sign = (num) -> if num < 0 then -1 else 1

    _rotation = (A, B) ->


Prompt:
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
###
"use strict"

Quo.gesture.add
  name    : "rotation"
  events  : "rotate,rotating,rotateLeft,rotateRight".split(",")
  handler : do (gm = Quo.gesture) ->

    TRIGGER_ANGLE             = 5
    IMPOSIBLE_ROTATION_FACTOR = 20

    _target         = null
    _num_rotations  = 0
    _start          = null
    _last           = null

    start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0

Response:
_start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > IMPOSIBLE_ROTATION_FACTOR
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null

    _sign = (num) -> if num < 0 then -1 else 1

    _rotation = (A, B) ->


Response:
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
###
"use strict"

Quo.gesture.add
  name    : "rotation"
  events  : ["rotate", "rotating", "rotateLeft", "rotateRight"]
  handler : do (gm = Quo.gesture) ->

    TRIGGER_ANGLE             = 5
    IMPOSIBLE_ROTATION_FACTOR = 20

    _target         = null
    _num_rotations  = 0
    _start          = null
    _last           = null

    start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0
        _start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > IMPOSIBLE_ROTATION_FACTOR
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null

    _sign = (num) -> if num < 0 then -1 else 1

    _rotation = (A, B) ->


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
###
"use strict"

Quo.gesture.add
  name    : "rotation"
  events  : ["rotate", "rotating", "rotateLeft", "rotateRight"]
  handler : do (gm = Quo.gesture) ->

    TRIGGER_ANGLE             = 5
    IMPOSIBLE_ROTATION_FACTOR = 20

    _target         = null
    _num_rotations  = 0
    _start          = null
    _last           = null

    start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0
        _start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > IMPOSIBLE_ROTATION_FACTOR
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null

    _sign = (num) -> if num < 0 then -1 else 1

    _rotation = (A, B) ->
```

Response:
/*
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
*/
"use strict";
Quo.gesture.add({
  name: "rotation",
  events: ["rotate", "rotating", "rotateLeft", "rotateRight"],
  handler: (function(gm) {
    var IMPOSIBLE_ROTATION_FACTOR, TRIGGER_ANGLE, _last, _num_rotations, _rotation, _sign, _start, _target, end, move, start;
    TRIGGER_ANGLE = 5;
    IMPOSIBLE_ROTATION_FACTOR = 20;
    _target = null;
    _num_rotations = 0;
    _start = null;
    _last = null;
    start = function(target, data) {
      if (data.length === 2) {
        _target = target;
        _num_rotations = 0;
        return _start = _rotation(data[0], data[1]);
      }
    };
    move = function(target, data) {
      var delta;
      if (_start && data.length === 2) {
        delta = _rotation(data[0], data[1]) - _start;
        if (_last && Math.abs(_last.delta - delta) > IMPOSIBLE_ROTATION_FACTOR) {
          delta += 360 * _sign(_last.delta);
        }
        if (Math.abs(delta) > 360) {
          _num_rotations++;
          delta -= 360 * _sign(_last.delta);
        }
        _last = {
          touches: data,
          delta: delta,
          rotationsCount: _num_rotations
        };
        return _check(true);
      }
    };
    end = function(target, data) {
      if (_start && _last) {
        _check(false);
        _target = null;
        _num_rotations = 0;
        _start = null;
        _last = null;
        return _start = null;
      }
    };
    _sign = function(num) {
      if (num < 0) {
        return -1;
      } else {
        return 1;
      }
    };
    return _rotation = function(A, B) {};
  })(Quo.gesture)
});


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
/*
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
*/
"use strict";
Quo.gesture.add({
  name: "rotation",
  events: ["rotate", "rotating", "rotateLeft", "rotateRight"],
  handler: (function(gm) {
    var IMPOSIBLE_ROTATION_FACTOR, TRIGGER_ANGLE, _last, _num_rotations, _rotation, _sign, _start, _target, end, move, start;
    TRIGGER_ANGLE = 5;
    IMPOSIBLE_ROTATION_FACTOR = 20;
    _target = null;
    _num_rotations = 0;
    _start = null;
    _last = null;
    start = function(target, data) {
      if (data.length === 2) {
        _target = target;
        _num_rotations = 0;
        return _start = _rotation(data[0], data[1]);
      }
    };
    move = function(target, data) {
      var delta;
      if (_start && data.length === 2) {
        delta = _rotation(data[0], data[1]) - _start;
        if (_last && Math.abs(_last.delta - delta) > IMPOSIBLE_ROTATION_FACTOR) {
          delta += 360 * _sign(_last.delta);
        }
        if (Math.abs(delta) > 360) {
          _num_rotations++;
          delta -= 360 * _sign(_last.delta);
        }
        _last = {
          touches: data,
          delta: delta,
          rotationsCount: _num_rotations
        };
        return _check(true);
      }
    };
    end = function(target, data) {
      if (_start && _last) {
        _check(false);
        _target = null;
        _num_rotations = 0;
        _start = null;
        _last = null;
        return _start = null;
      }
    };
    _sign = function(num) {
      if (num < 0) {
        return -1;
      } else {
        return 1;
      }
    };
    return _rotation = function(A, B) {};
  })(Quo.gesture)
});
```

Response:
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
###
"use strict"

Quo.gesture.add
  name    : "rotation"
  events  : ["rotate", "rotating", "rotateLeft", "rotateRight"]
  handler : do (gm = Quo.gesture) ->

    TRIGGER_ANGLE             = 5
    IMPOSIBLE_ROTATION_FACTOR = 20

    _target         = null
    _num_rotations  = 0
    _start          = null
    _last           = null

    start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0
        _start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > IMPOSIBLE_ROTATION_FACTOR
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null

    _sign = (num) -> if num < 0 then -1 else 1

    _rotation = (A, B) ->


Prompt:
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
###
"use strict"

Quo.gesture.add
  name    : "rotation"
  events  : ["rotate", "rotating", "rotateLeft", "rotateRight"]
  handler : do (gm = Quo.gesture) ->

    TRIGGER_ANGLE             = 5
    IMPOSIBLE_ROTATION_FACTOR = 20

    _target         = null
    _num_rotations  = 0
    _start          = null
    _last           = null

    start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0

Response:
_start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > IMPOSIBLE_ROTATION_FACTOR
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null

    _sign = (num) -> if num < 0 then -1 else 1

    _rotation = (A, B) ->


Response:
###
# Copyright (c) 2013-2018 the original author or authors.
#
# Licensed under the MIT License (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.opensource.org/licenses/mit-license.php
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
# either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
###

cyclotronDirectives.directive 'tableauWidget', ->
    {
        restrict: 'CA'

        link: ($scope, element, $attrs) ->
            $element = $(element)
            $scope.actualHeight = $element.height()
            $scope.actualWidth = $element.width()
            #$viz = $element.find('.tableauViz')
            #$viz.attr('height', actualHeight)
            #$viz.attr('width', actualWidth)
    }


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
###
# Copyright (c) 2013-2018 the original author or authors.
#
# Licensed under the MIT License (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.opensource.org/licenses/mit-license.php
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
# either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
###

cyclotronDirectives.directive 'tableauWidget', ->
    {
        restrict: 'CA'

        link: ($scope, element, $attrs) ->
            $element = $(element)
            $scope.actualHeight = $element.height()
            $scope.actualWidth = $element.width()
            #$viz = $element.find('.tableauViz')
            #$viz.attr('height', actualHeight)
            #$viz.attr('width', actualWidth)
    }
```

Response:
/*
 * Copyright (c) 2013-2018 the original author or authors.
 *
 * Licensed under the MIT License (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.opensource.org/licenses/mit-license.php
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific
 * language governing permissions and limitations under the License.
 */
cyclotronDirectives.directive('tableauWidget', function() {
  return {
    restrict: 'CA',
    link: function($scope, element, $attrs) {
      var $element;
      $element = $(element);
      $scope.actualHeight = $element.height();
      return $scope.actualWidth = $element.width();
    }
  };
});

//$viz = $element.find('.tableauViz')
//$viz.attr('height', actualHeight)
//$viz.attr('width', actualWidth)


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
/*
 * Copyright (c) 2013-2018 the original author or authors.
 *
 * Licensed under the MIT License (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.opensource.org/licenses/mit-license.php
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific
 * language governing permissions and limitations under the License.
 */
cyclotronDirectives.directive('tableauWidget', function() {
  return {
    restrict: 'CA',
    link: function($scope, element, $attrs) {
      var $element;
      $element = $(element);
      $scope.actualHeight = $element.height();
      return $scope.actualWidth = $element.width();
    }
  };
});

//$viz = $element.find('.tableauViz')
//$viz.attr('height', actualHeight)
//$viz.attr('width', actualWidth)
```

Response:
###
# Copyright (c) 2013-2018 the original author or authors.
#
# Licensed under the MIT License (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.opensource.org/licenses/mit-license.php
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
# either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
###

cyclotronDirectives.directive 'tableauWidget', ->
    {
        restrict: 'CA'

        link: ($scope, element, $attrs) ->
            $element = $(element)
            $scope.actualHeight = $element.height()
            $scope.actualWidth = $element.width()
            #$viz = $element.find('.tableauViz')
            #$viz.attr('height', actualHeight)
            #$viz.attr('width', actualWidth)
    }


Prompt:
###
# Copyright (c) 2013-2018 the original author or authors.
#
# Licensed under the MIT License (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.opensource.org/licenses/mit-license.php
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
# either express or implied. See the License for the specific
# language governing permissions and limitations under the License.

Response:
###

cyclotronDirectives.directive 'tableauWidget', ->
    {
        restrict: 'CA'

        link: ($scope, element, $attrs) ->
            $element = $(element)
            $scope.actualHeight = $element.height()
            $scope.actualWidth = $element.width()
            #$viz = $element.find('.tableauViz')
            #$viz.attr('height', actualHeight)
            #$viz.attr('width', actualWidth)
    }


Response:
# polyfill in case we're on old node js, which naturally doesn't have exotic
# built in string methods like .endsWith()
require('string.prototype.endswith')

# initialize the compiler
require('./src/load_compiler')

_l = require 'lodash'
React = require 'react'

{Doc} = require './src/doc'
core = require './src/core'
{foreachPdom} = require './src/pdom'
Dynamic = require './src/dynamic'
evalPdom = require './src/eval-pdom'
{pdomToReact} = require './src/editor/pdom-to-react'
util = require './src/util'

exports.get_components = (pd_json_obj) ->
    # parse and deserialize the doc
    doc = Doc.deserialize(pd_json_obj)
    doc.enterReadonlyMode()

    getCompiledComponentByUniqueKey = util.memoized_on _l.identity, (uniqueKey) ->
        componentBlockTree = doc.getBlockTreeByUniqueKey(uniqueKey)
        return undefined if not componentBlockTree?
        pdom = core.compileComponent(componentBlockTree, {
            templateLang: 'JSX'
            for_editor: false
            for_component_instance_editor: false
            getCompiledComponentByUniqueKey: getCompiledComponentByUniqueKey
        })

        core.foreachPdom pdom, (pd) ->
            pd.boxSizing = 'border-box'
            if pd.event_handlers?
                pd[event + "Attr"] = new Dynamic(code, undefined) for {event, code} in pd.event_handlers
                delete pd.event_handlers

        return pdom

    # compile the doc
    return _l.mapValues _l.keyBy(doc.getComponents(), 'name'), (component) ->
        return (props) ->

            pdom = evalPdom(
                {tag: component, props},
                getCompiledComponentByUniqueKey,
                'JSX',
                window.innerWidth


Prompt:
# polyfill in case we're on old node js, which naturally doesn't have exotic
# built in string methods like .endsWith()
require('string.prototype.endswith')

# initialize the compiler
require('./src/load_compiler')

_l = require 'lodash'
React = require 'react'

{Doc} = require './src/doc'
core = require './src/core'
{foreachPdom} = require './src/pdom'
Dynamic = require './src/dynamic'
evalPdom = require './src/eval-pdom'
{pdomToReact} = require './src/editor/pdom-to-react'
util = require './src/util'

exports.get_components = (pd_json_obj) ->
    # parse and deserialize the doc
    doc = Doc.deserialize(pd_json_obj)
    doc.enterReadonlyMode()

    getCompiledComponentByUniqueKey = util.memoized_on _l.identity, (uniqueKey) ->
        componentBlockTree = doc.getBlockTreeByUniqueKey(uniqueKey)

Response:
return undefined if not componentBlockTree?
        pdom = core.compileComponent(componentBlockTree, {
            templateLang: 'JSX'
            for_editor: false
            for_component_instance_editor: false
            getCompiledComponentByUniqueKey: getCompiledComponentByUniqueKey
        })

        core.foreachPdom pdom, (pd) ->
            pd.boxSizing = 'border-box'
            if pd.event_handlers?
                pd[event + "Attr"] = new Dynamic(code, undefined) for {event, code} in pd.event_handlers
                delete pd.event_handlers

        return pdom

    # compile the doc
    return _l.mapValues _l.keyBy(doc.getComponents(), 'name'), (component) ->
        return (props) ->

            pdom = evalPdom(
                {tag: component, props},
                getCompiledComponentByUniqueKey,
                'JSX',
                window.innerWidth


Response:
###
Requires https://github.com/erniebrodeur/ruby-beautify
###

"use strict"
Beautifier = require('./beautifier')

module.exports = class RubyBeautify extends Beautifier
  name: "Ruby Beautify"
  link: "https://github.com/erniebrodeur/ruby-beautify"
  isPreInstalled: false

  options: {
    Ruby:
      indent_size: true
      indent_char: true
  }

  beautify: (text, language, options) ->
    @run("rbeautify", [
      if options.indent_char is '\t' then "--tabs" else "--spaces"
      "--indent_count", options.indent_size
      @tempFile("input", text)
      ], help: {
        link: "https://github.com/erniebrodeur/ruby-beautify"
      })


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
###
Requires https://github.com/erniebrodeur/ruby-beautify
###

"use strict"
Beautifier = require('./beautifier')

module.exports = class RubyBeautify extends Beautifier
  name: "Ruby Beautify"
  link: "https://github.com/erniebrodeur/ruby-beautify"
  isPreInstalled: false

  options: {
    Ruby:
      indent_size: true
      indent_char: true
  }

  beautify: (text, language, options) ->
    @run("rbeautify", [
      if options.indent_char is '\t' then "--tabs" else "--spaces"
      "--indent_count", options.indent_size
      @tempFile("input", text)
      ], help: {
        link: "https://github.com/erniebrodeur/ruby-beautify"
      })
```

Response:
/*
Requires https://github.com/erniebrodeur/ruby-beautify
*/
"use strict";
var Beautifier, RubyBeautify;

Beautifier = require('./beautifier');

module.exports = RubyBeautify = (function() {
  class RubyBeautify extends Beautifier {
    beautify(text, language, options) {
      return this.run("rbeautify", [options.indent_char === '\t' ? "--tabs" : "--spaces", "--indent_count", options.indent_size, this.tempFile("input", text)], {
        help: {
          link: "https://github.com/erniebrodeur/ruby-beautify"
        }
      });
    }

  };

  RubyBeautify.prototype.name = "Ruby Beautify";

  RubyBeautify.prototype.link = "https://github.com/erniebrodeur/ruby-beautify";

  RubyBeautify.prototype.isPreInstalled = false;

  RubyBeautify.prototype.options = {
    Ruby: {
      indent_size: true,
      indent_char: true
    }
  };

  return RubyBeautify;

}).call(this);


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
/*
Requires https://github.com/erniebrodeur/ruby-beautify
*/
"use strict";
var Beautifier, RubyBeautify;

Beautifier = require('./beautifier');

module.exports = RubyBeautify = (function() {
  class RubyBeautify extends Beautifier {
    beautify(text, language, options) {
      return this.run("rbeautify", [options.indent_char === '\t' ? "--tabs" : "--spaces", "--indent_count", options.indent_size, this.tempFile("input", text)], {
        help: {
          link: "https://github.com/erniebrodeur/ruby-beautify"
        }
      });
    }

  };

  RubyBeautify.prototype.name = "Ruby Beautify";

  RubyBeautify.prototype.link = "https://github.com/erniebrodeur/ruby-beautify";

  RubyBeautify.prototype.isPreInstalled = false;

  RubyBeautify.prototype.options = {
    Ruby: {
      indent_size: true,
      indent_char: true
    }
  };

  return RubyBeautify;

}).call(this);
```

Response:
###
Requires https://github.com/erniebrodeur/ruby-beautify
###

"use strict"
Beautifier = require('./beautifier')

module.exports = class RubyBeautify extends Beautifier
  name: "Ruby Beautify"
  link: "https://github.com/erniebrodeur/ruby-beautify"
  isPreInstalled: false

  options: {
    Ruby:
      indent_size: true
      indent_char: true
  }

  beautify: (text, language, options) ->
    @run("rbeautify", [
      if options.indent_char is '\t' then "--tabs" else "--spaces"
      "--indent_count", options.indent_size
      @tempFile("input", text)
      ], help: {
        link: "https://github.com/erniebrodeur/ruby-beautify"
      })


Prompt:
###
Requires https://github.com/erniebrodeur/ruby-beautify
###

"use strict"
Beautifier = require('./beautifier')

module.exports = class RubyBeautify extends Beautifier
  name: "Ruby Beautify"
  link: "https://github.com/erniebrodeur/ruby-beautify"
  isPreInstalled: false

  options: {

Response:
Ruby:
      indent_size: true
      indent_char: true
  }

  beautify: (text, language, options) ->
    @run("rbeautify", [
      if options.indent_char is '\t' then "--tabs" else "--spaces"
      "--indent_count", options.indent_size
      @tempFile("input", text)
      ], help: {
        link: "https://github.com/erniebrodeur/ruby-beautify"
      })


Response:
initContentWindowGlobals = (contentWindow) ->
    if not contentWindow.pd__loaded_libs?
        contentWindow.pd__loaded_libs = new Set()
        contentWindow.pd__loading_libs = new Map()
        contentWindow.pd__dataForId = {}


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
initContentWindowGlobals = (contentWindow) ->
    if not contentWindow.pd__loaded_libs?
        contentWindow.pd__loaded_libs = new Set()
        contentWindow.pd__loading_libs = new Map()
        contentWindow.pd__dataForId = {}
```

Response:
var initContentWindowGlobals;

initContentWindowGlobals = function(contentWindow) {
  if (contentWindow.pd__loaded_libs == null) {
    contentWindow.pd__loaded_libs = new Set();
    contentWindow.pd__loading_libs = new Map();
    return contentWindow.pd__dataForId = {};
  }
};


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
var initContentWindowGlobals;

initContentWindowGlobals = function(contentWindow) {
  if (contentWindow.pd__loaded_libs == null) {
    contentWindow.pd__loaded_libs = new Set();
    contentWindow.pd__loading_libs = new Map();
    return contentWindow.pd__dataForId = {};
  }
};
```

Response:
initContentWindowGlobals = (contentWindow) ->
    if not contentWindow.pd__loaded_libs?
        contentWindow.pd__loaded_libs = new Set()
        contentWindow.pd__loading_libs = new Map()
        contentWindow.pd__dataForId = {}


Prompt:
initContentWindowGlobals = (contentWindow) ->
    if not contentWindow.pd__loaded_libs?

Response:
contentWindow.pd__loaded_libs = new Set()
        contentWindow.pd__loading_libs = new Map()
        contentWindow.pd__dataForId = {}


Response:
exports.loadDevLibrary = (contentWindow) ->
    initContentWindowGlobals(contentWindow)
    loadLibrary(contentWindow, '__internal_dev_lib_id', "#{devcodeserver}/bundle.js")


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
exports.loadDevLibrary = (contentWindow) ->
    initContentWindowGlobals(contentWindow)
    loadLibrary(contentWindow, '__internal_dev_lib_id', "#{devcodeserver}/bundle.js")
```

Response:
exports.loadDevLibrary = function(contentWindow) {
  initContentWindowGlobals(contentWindow);
  return loadLibrary(contentWindow, '__internal_dev_lib_id', `${devcodeserver}/bundle.js`);
};


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
exports.loadDevLibrary = function(contentWindow) {
  initContentWindowGlobals(contentWindow);
  return loadLibrary(contentWindow, '__internal_dev_lib_id', `${devcodeserver}/bundle.js`);
};
```

Response:
exports.loadDevLibrary = (contentWindow) ->
    initContentWindowGlobals(contentWindow)
    loadLibrary(contentWindow, '__internal_dev_lib_id', "#{devcodeserver}/bundle.js")


Response:
exports.loadProdLibrary = (contentWindow, id) ->
    initContentWindowGlobals(contentWindow)
    loadLibrary(contentWindow, id, "#{extcodeserver}/#{id}")

# NOTE: I'm doing window. here to guarantee our bundling process won't change the name of this function,
# since router.cjsx error handling searches for this function name to know if there was an error in user code
window?.__evalBundleWrapperForErrorDetector = (contentWindow, bundle) ->
    wrapBundle = (bundle) -> """
    {"use strict";
    #{bundle}
    ;\nreturn PagedrawSpecs;\n}
    """
    return (contentWindow.Function(wrapBundle(bundle)))()

# loadLibrary :: (contentWindow, id, url) -> Promise<{status: 'ok', data: any} | {status: 'net-err', error} | {status: 'user-err', userError}>
# status 'ok' == data successfully loaded
# status 'no-op' == data previously loaded
# status 'net-err' == no internet connection available
# status 'user-err' == user code has errors
# promise throws == pagedraw fucked up, crash


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
exports.loadProdLibrary = (contentWindow, id) ->
    initContentWindowGlobals(contentWindow)
    loadLibrary(contentWindow, id, "#{extcodeserver}/#{id}")

# NOTE: I'm doing window. here to guarantee our bundling process won't change the name of this function,
# since router.cjsx error handling searches for this function name to know if there was an error in user code
window?.__evalBundleWrapperForErrorDetector = (contentWindow, bundle) ->
    wrapBundle = (bundle) -> """
    {"use strict";
    #{bundle}
    ;\nreturn PagedrawSpecs;\n}
    """
    return (contentWindow.Function(wrapBundle(bundle)))()

# loadLibrary :: (contentWindow, id, url) -> Promise<{status: 'ok', data: any} | {status: 'net-err', error} | {status: 'user-err', userError}>
# status 'ok' == data successfully loaded
# status 'no-op' == data previously loaded
# status 'net-err' == no internet connection available
# status 'user-err' == user code has errors
# promise throws == pagedraw fucked up, crash
```

Response:
exports.loadProdLibrary = function(contentWindow, id) {
  initContentWindowGlobals(contentWindow);
  return loadLibrary(contentWindow, id, `${extcodeserver}/${id}`);
};

// NOTE: I'm doing window. here to guarantee our bundling process won't change the name of this function,
// since router.cjsx error handling searches for this function name to know if there was an error in user code
if (typeof window !== "undefined" && window !== null) {
  window.__evalBundleWrapperForErrorDetector = function(contentWindow, bundle) {
    var wrapBundle;
    wrapBundle = function(bundle) {
      return `{"use strict";
${bundle}
;\nreturn PagedrawSpecs;\n}`;
    };
    return (contentWindow.Function(wrapBundle(bundle)))();
  };
}

// loadLibrary :: (contentWindow, id, url) -> Promise<{status: 'ok', data: any} | {status: 'net-err', error} | {status: 'user-err', userError}>
// status 'ok' == data successfully loaded
// status 'no-op' == data previously loaded
// status 'net-err' == no internet connection available
// status 'user-err' == user code has errors
// promise throws == pagedraw fucked up, crash


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
exports.loadProdLibrary = function(contentWindow, id) {
  initContentWindowGlobals(contentWindow);
  return loadLibrary(contentWindow, id, `${extcodeserver}/${id}`);
};

// NOTE: I'm doing window. here to guarantee our bundling process won't change the name of this function,
// since router.cjsx error handling searches for this function name to know if there was an error in user code
if (typeof window !== "undefined" && window !== null) {
  window.__evalBundleWrapperForErrorDetector = function(contentWindow, bundle) {
    var wrapBundle;
    wrapBundle = function(bundle) {
      return `{"use strict";
${bundle}
;\nreturn PagedrawSpecs;\n}`;
    };
    return (contentWindow.Function(wrapBundle(bundle)))();
  };
}

// loadLibrary :: (contentWindow, id, url) -> Promise<{status: 'ok', data: any} | {status: 'net-err', error} | {status: 'user-err', userError}>
// status 'ok' == data successfully loaded
// status 'no-op' == data previously loaded
// status 'net-err' == no internet connection available
// status 'user-err' == user code has errors
// promise throws == pagedraw fucked up, crash
```

Response:
exports.loadProdLibrary = (contentWindow, id) ->
    initContentWindowGlobals(contentWindow)
    loadLibrary(contentWindow, id, "#{extcodeserver}/#{id}")

# NOTE: I'm doing window. here to guarantee our bundling process won't change the name of this function,
# since router.cjsx error handling searches for this function name to know if there was an error in user code
window?.__evalBundleWrapperForErrorDetector = (contentWindow, bundle) ->
    wrapBundle = (bundle) -> """
    {"use strict";
    #{bundle}
    ;\nreturn PagedrawSpecs;\n}
    """
    return (contentWindow.Function(wrapBundle(bundle)))()

# loadLibrary :: (contentWindow, id, url) -> Promise<{status: 'ok', data: any} | {status: 'net-err', error} | {status: 'user-err', userError}>
# status 'ok' == data successfully loaded
# status 'no-op' == data previously loaded
# status 'net-err' == no internet connection available
# status 'user-err' == user code has errors
# promise throws == pagedraw fucked up, crash


Prompt:
exports.loadProdLibrary = (contentWindow, id) ->
    initContentWindowGlobals(contentWindow)
    loadLibrary(contentWindow, id, "#{extcodeserver}/#{id}")

# NOTE: I'm doing window. here to guarantee our bundling process won't change the name of this function,
# since router.cjsx error handling searches for this function name to know if there was an error in user code
window?.__evalBundleWrapperForErrorDetector = (contentWindow, bundle) ->
    wrapBundle = (bundle) -> """
    {"use strict";

Response:
#{bundle}
    ;\nreturn PagedrawSpecs;\n}
    """
    return (contentWindow.Function(wrapBundle(bundle)))()

# loadLibrary :: (contentWindow, id, url) -> Promise<{status: 'ok', data: any} | {status: 'net-err', error} | {status: 'user-err', userError}>
# status 'ok' == data successfully loaded
# status 'no-op' == data previously loaded
# status 'net-err' == no internet connection available
# status 'user-err' == user code has errors
# promise throws == pagedraw fucked up, crash


Response:
loadLibrary = (contentWindow, id, url) ->
    new Promise (resolve, reject) ->
        if contentWindow.pd__loaded_libs.has(id)
            console.warn "Attempt to load already loaded library #{id}. Not loading."
            return resolve {status: 'no-op', data: contentWindow.pd__dataForId[id]}

        if (loading = contentWindow.pd__loading_libs.get(id))?
            console.warn "Attempt to load loading library #{id}. Waiting..."
            callback = (specs, errType, error, userError) ->
                if not err?
                then resolve({status: 'ok', data: specs})
                else resolve({status: errType, error, userError})
            loading.callbacks.push(callback)
        else
            contentWindow.pd__loading_libs.set(id, {callbacks: []})

            get_code = ->
                fetch(url).then((r) -> r.text()).then((bundle) ->
                    {error: null, bundle}
                ).catch (error) ->
                    {error}

            resolve_with_error = (errType, error, userError) ->
                resolve({status: errType, error: error, userError})
                callbacks = contentWindow.pd__loading_libs.get(id).callbacks
                contentWindow.pd__loading_libs.delete(id)
                callback(undefined, errType, error, userError) for callback in callbacks

            get_code().then(({error, bundle}) ->
                if error? then resolve_with_error('net-err', error, null)
                else
                    eval_result = window.__evalBundleWrapperForErrorDetector(contentWindow, bundle)
                    specs = if (typeof eval_result == 'object') and eval_result.default? then eval_result.default else eval_result

                    contentWindow.pd__loaded_libs.add(id)

                    # FIXME: This might leak too much memory
                    contentWindow.pd__dataForId[id] = specs

                    resolve({status: 'ok', data: specs})
                    callbacks = contentWindow.pd__loading_libs.get(id).callbacks
                    contentWindow.pd__loading_libs.delete(id)
                    callback(specs) for callback in callbacks
            ).catch (e) ->
                # we threw while evaluating user code.
                resolve_with_error('user-err', null, e)

connection_timeout = 20000
connection = {}


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
loadLibrary = (contentWindow, id, url) ->
    new Promise (resolve, reject) ->
        if contentWindow.pd__loaded_libs.has(id)
            console.warn "Attempt to load already loaded library #{id}. Not loading."
            return resolve {status: 'no-op', data: contentWindow.pd__dataForId[id]}

        if (loading = contentWindow.pd__loading_libs.get(id))?
            console.warn "Attempt to load loading library #{id}. Waiting..."
            callback = (specs, errType, error, userError) ->
                if not err?
                then resolve({status: 'ok', data: specs})
                else resolve({status: errType, error, userError})
            loading.callbacks.push(callback)
        else
            contentWindow.pd__loading_libs.set(id, {callbacks: []})

            get_code = ->
                fetch(url).then((r) -> r.text()).then((bundle) ->
                    {error: null, bundle}
                ).catch (error) ->
                    {error}

            resolve_with_error = (errType, error, userError) ->
                resolve({status: errType, error: error, userError})
                callbacks = contentWindow.pd__loading_libs.get(id).callbacks
                contentWindow.pd__loading_libs.delete(id)
                callback(undefined, errType, error, userError) for callback in callbacks

            get_code().then(({error, bundle}) ->
                if error? then resolve_with_error('net-err', error, null)
                else
                    eval_result = window.__evalBundleWrapperForErrorDetector(contentWindow, bundle)
                    specs = if (typeof eval_result == 'object') and eval_result.default? then eval_result.default else eval_result

                    contentWindow.pd__loaded_libs.add(id)

                    # FIXME: This might leak too much memory
                    contentWindow.pd__dataForId[id] = specs

                    resolve({status: 'ok', data: specs})
                    callbacks = contentWindow.pd__loading_libs.get(id).callbacks
                    contentWindow.pd__loading_libs.delete(id)
                    callback(specs) for callback in callbacks
            ).catch (e) ->
                # we threw while evaluating user code.
                resolve_with_error('user-err', null, e)

connection_timeout = 20000
connection = {}
```

Response:
var connection, connection_timeout, loadLibrary;

loadLibrary = function(contentWindow, id, url) {
  return new Promise(function(resolve, reject) {
    var callback, get_code, loading, resolve_with_error;
    if (contentWindow.pd__loaded_libs.has(id)) {
      console.warn(`Attempt to load already loaded library ${id}. Not loading.`);
      return resolve({
        status: 'no-op',
        data: contentWindow.pd__dataForId[id]
      });
    }
    if ((loading = contentWindow.pd__loading_libs.get(id)) != null) {
      console.warn(`Attempt to load loading library ${id}. Waiting...`);
      callback = function(specs, errType, error, userError) {
        if (typeof err === "undefined" || err === null) {
          return resolve({
            status: 'ok',
            data: specs
          });
        } else {
          return resolve({
            status: errType,
            error,
            userError
          });
        }
      };
      return loading.callbacks.push(callback);
    } else {
      contentWindow.pd__loading_libs.set(id, {
        callbacks: []
      });
      get_code = function() {
        return fetch(url).then(function(r) {
          return r.text();
        }).then(function(bundle) {
          return {
            error: null,
            bundle
          };
        }).catch(function(error) {
          return {error};
        });
      };
      resolve_with_error = function(errType, error, userError) {
        var callbacks, i, len, results;
        resolve({
          status: errType,
          error: error,
          userError
        });
        callbacks = contentWindow.pd__loading_libs.get(id).callbacks;
        contentWindow.pd__loading_libs.delete(id);
        results = [];
        for (i = 0, len = callbacks.length; i < len; i++) {
          callback = callbacks[i];
          results.push(callback(void 0, errType, error, userError));
        }
        return results;
      };
      return get_code().then(function({error, bundle}) {
        var callbacks, eval_result, i, len, results, specs;
        if (error != null) {
          return resolve_with_error('net-err', error, null);
        } else {
          eval_result = window.__evalBundleWrapperForErrorDetector(contentWindow, bundle);
          specs = (typeof eval_result === 'object') && (eval_result.default != null) ? eval_result.default : eval_result;
          contentWindow.pd__loaded_libs.add(id);
          // FIXME: This might leak too much memory
          contentWindow.pd__dataForId[id] = specs;
          resolve({
            status: 'ok',
            data: specs
          });
          callbacks = contentWindow.pd__loading_libs.get(id).callbacks;
          contentWindow.pd__loading_libs.delete(id);
          results = [];
          for (i = 0, len = callbacks.length; i < len; i++) {
            callback = callbacks[i];
            results.push(callback(specs));
          }
          return results;
        }
      }).catch(function(e) {
        // we threw while evaluating user code.
        return resolve_with_error('user-err', null, e);
      });
    }
  });
};

connection_timeout = 20000;

connection = {};


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
var connection, connection_timeout, loadLibrary;

loadLibrary = function(contentWindow, id, url) {
  return new Promise(function(resolve, reject) {
    var callback, get_code, loading, resolve_with_error;
    if (contentWindow.pd__loaded_libs.has(id)) {
      console.warn(`Attempt to load already loaded library ${id}. Not loading.`);
      return resolve({
        status: 'no-op',
        data: contentWindow.pd__dataForId[id]
      });
    }
    if ((loading = contentWindow.pd__loading_libs.get(id)) != null) {
      console.warn(`Attempt to load loading library ${id}. Waiting...`);
      callback = function(specs, errType, error, userError) {
        if (typeof err === "undefined" || err === null) {
          return resolve({
            status: 'ok',
            data: specs
          });
        } else {
          return resolve({
            status: errType,
            error,
            userError
          });
        }
      };
      return loading.callbacks.push(callback);
    } else {
      contentWindow.pd__loading_libs.set(id, {
        callbacks: []
      });
      get_code = function() {
        return fetch(url).then(function(r) {
          return r.text();
        }).then(function(bundle) {
          return {
            error: null,
            bundle
          };
        }).catch(function(error) {
          return {error};
        });
      };
      resolve_with_error = function(errType, error, userError) {
        var callbacks, i, len, results;
        resolve({
          status: errType,
          error: error,
          userError
        });
        callbacks = contentWindow.pd__loading_libs.get(id).callbacks;
        contentWindow.pd__loading_libs.delete(id);
        results = [];
        for (i = 0, len = callbacks.length; i < len; i++) {
          callback = callbacks[i];
          results.push(callback(void 0, errType, error, userError));
        }
        return results;
      };
      return get_code().then(function({error, bundle}) {
        var callbacks, eval_result, i, len, results, specs;
        if (error != null) {
          return resolve_with_error('net-err', error, null);
        } else {
          eval_result = window.__evalBundleWrapperForErrorDetector(contentWindow, bundle);
          specs = (typeof eval_result === 'object') && (eval_result.default != null) ? eval_result.default : eval_result;
          contentWindow.pd__loaded_libs.add(id);
          // FIXME: This might leak too much memory
          contentWindow.pd__dataForId[id] = specs;
          resolve({
            status: 'ok',
            data: specs
          });
          callbacks = contentWindow.pd__loading_libs.get(id).callbacks;
          contentWindow.pd__loading_libs.delete(id);
          results = [];
          for (i = 0, len = callbacks.length; i < len; i++) {
            callback = callbacks[i];
            results.push(callback(specs));
          }
          return results;
        }
      }).catch(function(e) {
        // we threw while evaluating user code.
        return resolve_with_error('user-err', null, e);
      });
    }
  });
};

connection_timeout = 20000;

connection = {};
```

Response:
loadLibrary = (contentWindow, id, url) ->
    new Promise (resolve, reject) ->
        if contentWindow.pd__loaded_libs.has(id)
            console.warn "Attempt to load already loaded library #{id}. Not loading."
            return resolve {status: 'no-op', data: contentWindow.pd__dataForId[id]}

        if (loading = contentWindow.pd__loading_libs.get(id))?
            console.warn "Attempt to load loading library #{id}. Waiting..."
            callback = (specs, errType, error, userError) ->
                if not err?
                then resolve({status: 'ok', data: specs})
                else resolve({status: errType, error, userError})
            loading.callbacks.push(callback)
        else
            contentWindow.pd__loading_libs.set(id, {callbacks: []})

            get_code = ->
                fetch(url).then((r) -> r.text()).then((bundle) ->
                    {error: null, bundle}
                ).catch (error) ->
                    {error}

            resolve_with_error = (errType, error, userError) ->
                resolve({status: errType, error: error, userError})
                callbacks = contentWindow.pd__loading_libs.get(id).callbacks
                contentWindow.pd__loading_libs.delete(id)
                callback(undefined, errType, error, userError) for callback in callbacks

            get_code().then(({error, bundle}) ->
                if error? then resolve_with_error('net-err', error, null)
                else
                    eval_result = window.__evalBundleWrapperForErrorDetector(contentWindow, bundle)
                    specs = if (typeof eval_result == 'object') and eval_result.default? then eval_result.default else eval_result

                    contentWindow.pd__loaded_libs.add(id)

                    # FIXME: This might leak too much memory
                    contentWindow.pd__dataForId[id] = specs

                    resolve({status: 'ok', data: specs})
                    callbacks = contentWindow.pd__loading_libs.get(id).callbacks
                    contentWindow.pd__loading_libs.delete(id)
                    callback(specs) for callback in callbacks
            ).catch (e) ->
                # we threw while evaluating user code.
                resolve_with_error('user-err', null, e)

connection_timeout = 20000
connection = {}


Prompt:
loadLibrary = (contentWindow, id, url) ->
    new Promise (resolve, reject) ->
        if contentWindow.pd__loaded_libs.has(id)
            console.warn "Attempt to load already loaded library #{id}. Not loading."
            return resolve {status: 'no-op', data: contentWindow.pd__dataForId[id]}

        if (loading = contentWindow.pd__loading_libs.get(id))?
            console.warn "Attempt to load loading library #{id}. Waiting..."
            callback = (specs, errType, error, userError) ->
                if not err?
                then resolve({status: 'ok', data: specs})
                else resolve({status: errType, error, userError})
            loading.callbacks.push(callback)
        else
            contentWindow.pd__loading_libs.set(id, {callbacks: []})

            get_code = ->
                fetch(url).then((r) -> r.text()).then((bundle) ->
                    {error: null, bundle}
                ).catch (error) ->
                    {error}

            resolve_with_error = (errType, error, userError) ->
                resolve({status: errType, error: error, userError})
                callbacks = contentWindow.pd__loading_libs.get(id).callbacks

Response:
contentWindow.pd__loading_libs.delete(id)
                callback(undefined, errType, error, userError) for callback in callbacks

            get_code().then(({error, bundle}) ->
                if error? then resolve_with_error('net-err', error, null)
                else
                    eval_result = window.__evalBundleWrapperForErrorDetector(contentWindow, bundle)
                    specs = if (typeof eval_result == 'object') and eval_result.default? then eval_result.default else eval_result

                    contentWindow.pd__loaded_libs.add(id)

                    # FIXME: This might leak too much memory
                    contentWindow.pd__dataForId[id] = specs

                    resolve({status: 'ok', data: specs})
                    callbacks = contentWindow.pd__loading_libs.get(id).callbacks
                    contentWindow.pd__loading_libs.delete(id)
                    callback(specs) for callback in callbacks
            ).catch (e) ->
                # we threw while evaluating user code.
                resolve_with_error('user-err', null, e)

connection_timeout = 20000
connection = {}


Response:
exports.subscribeToDevServer = (on_build) ->
    # library in development always has id == $0
    # when we add support for multiple libraries we'll need to
    # add support for more ids too, which should be of the format
    # $1, $2, $3...
    disconnect = ->
        if connection.timeout_timer? then clearInterval(connection.timeout_timer)
        connection.source?.close()
        delete connection.source
        on_build("0", ['disconnected'])

    connection.source = source = new window.EventSource("#{devcodeserver}/__webpack_hmr")
    source.onopen = -> connection.last_active = new Date()
    source.onerror = ->
        disconnect()
    source.onmessage = (event) ->
        connection.last_active = new Date()
        return if event.data == "\uD83D\uDC93" #dev server heartbeat
        try
            data = JSON.parse(event.data)
            on_build("$0", data.errors || []) if data.action == 'built'
        catch e
            console.warn("HR Error: #{e}")

    window.addEventListener("beforeunload", disconnect)

    connection.timeout_timer = setInterval((-> if connection.last_active? and new Date() - connection.last_active > connection_timeout then disconnect()), connection_timeout)

# publishDevLibrary :: (static_id) -> Promise<{status: 'ok', hash: string} | {status: 'net-err', error} | {status: 'user-err', error}>
# status 'ok'  == library was successfully uploaded
# status 'net-err' == Unable to reach the CLI
# status 'user-err' == user code has errors
# promise throws = pagedraw error, crash


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
exports.subscribeToDevServer = (on_build) ->
    # library in development always has id == $0
    # when we add support for multiple libraries we'll need to
    # add support for more ids too, which should be of the format
    # $1, $2, $3...
    disconnect = ->
        if connection.timeout_timer? then clearInterval(connection.timeout_timer)
        connection.source?.close()
        delete connection.source
        on_build("0", ['disconnected'])

    connection.source = source = new window.EventSource("#{devcodeserver}/__webpack_hmr")
    source.onopen = -> connection.last_active = new Date()
    source.onerror = ->
        disconnect()
    source.onmessage = (event) ->
        connection.last_active = new Date()
        return if event.data == "\uD83D\uDC93" #dev server heartbeat
        try
            data = JSON.parse(event.data)
            on_build("$0", data.errors || []) if data.action == 'built'
        catch e
            console.warn("HR Error: #{e}")

    window.addEventListener("beforeunload", disconnect)

    connection.timeout_timer = setInterval((-> if connection.last_active? and new Date() - connection.last_active > connection_timeout then disconnect()), connection_timeout)

# publishDevLibrary :: (static_id) -> Promise<{status: 'ok', hash: string} | {status: 'net-err', error} | {status: 'user-err', error}>
# status 'ok'  == library was successfully uploaded
# status 'net-err' == Unable to reach the CLI
# status 'user-err' == user code has errors
# promise throws = pagedraw error, crash
```

Response:
exports.subscribeToDevServer = function(on_build) {
  var disconnect, source;
  // library in development always has id == $0
  // when we add support for multiple libraries we'll need to
  // add support for more ids too, which should be of the format
  // $1, $2, $3...
  disconnect = function() {
    var ref;
    if (connection.timeout_timer != null) {
      clearInterval(connection.timeout_timer);
    }
    if ((ref = connection.source) != null) {
      ref.close();
    }
    delete connection.source;
    return on_build("0", ['disconnected']);
  };
  connection.source = source = new window.EventSource(`${devcodeserver}/__webpack_hmr`);
  source.onopen = function() {
    return connection.last_active = new Date();
  };
  source.onerror = function() {
    return disconnect();
  };
  source.onmessage = function(event) {
    var data, e;
    connection.last_active = new Date();
    if (event.data === "\uD83D\uDC93") { //dev server heartbeat
      return;
    }
    try {
      data = JSON.parse(event.data);
      if (data.action === 'built') {
        return on_build("$0", data.errors || []);
      }
    } catch (error) {
      e = error;
      return console.warn(`HR Error: ${e}`);
    }
  };
  window.addEventListener("beforeunload", disconnect);
  return connection.timeout_timer = setInterval((function() {
    if ((connection.last_active != null) && new Date() - connection.last_active > connection_timeout) {
      return disconnect();
    }
  }), connection_timeout);
};

// publishDevLibrary :: (static_id) -> Promise<{status: 'ok', hash: string} | {status: 'net-err', error} | {status: 'user-err', error}>
// status 'ok'  == library was successfully uploaded
// status 'net-err' == Unable to reach the CLI
// status 'user-err' == user code has errors
// promise throws = pagedraw error, crash


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
exports.subscribeToDevServer = function(on_build) {
  var disconnect, source;
  // library in development always has id == $0
  // when we add support for multiple libraries we'll need to
  // add support for more ids too, which should be of the format
  // $1, $2, $3...
  disconnect = function() {
    var ref;
    if (connection.timeout_timer != null) {
      clearInterval(connection.timeout_timer);
    }
    if ((ref = connection.source) != null) {
      ref.close();
    }
    delete connection.source;
    return on_build("0", ['disconnected']);
  };
  connection.source = source = new window.EventSource(`${devcodeserver}/__webpack_hmr`);
  source.onopen = function() {
    return connection.last_active = new Date();
  };
  source.onerror = function() {
    return disconnect();
  };
  source.onmessage = function(event) {
    var data, e;
    connection.last_active = new Date();
    if (event.data === "\uD83D\uDC93") { //dev server heartbeat
      return;
    }
    try {
      data = JSON.parse(event.data);
      if (data.action === 'built') {
        return on_build("$0", data.errors || []);
      }
    } catch (error) {
      e = error;
      return console.warn(`HR Error: ${e}`);
    }
  };
  window.addEventListener("beforeunload", disconnect);
  return connection.timeout_timer = setInterval((function() {
    if ((connection.last_active != null) && new Date() - connection.last_active > connection_timeout) {
      return disconnect();
    }
  }), connection_timeout);
};

// publishDevLibrary :: (static_id) -> Promise<{status: 'ok', hash: string} | {status: 'net-err', error} | {status: 'user-err', error}>
// status 'ok'  == library was successfully uploaded
// status 'net-err' == Unable to reach the CLI
// status 'user-err' == user code has errors
// promise throws = pagedraw error, crash
```

Response:
exports.subscribeToDevServer = (on_build) ->
    # library in development always has id == $0
    # when we add support for multiple libraries we'll need to
    # add support for more ids too, which should be of the format
    # $1, $2, $3...
    disconnect = ->
        if connection.timeout_timer? then clearInterval(connection.timeout_timer)
        connection.source?.close()
        delete connection.source
        on_build("0", ['disconnected'])

    connection.source = source = new window.EventSource("#{devcodeserver}/__webpack_hmr")
    source.onopen = -> connection.last_active = new Date()
    source.onerror = ->
        disconnect()
    source.onmessage = (event) ->
        connection.last_active = new Date()
        return if event.data == "\uD83D\uDC93" #dev server heartbeat
        try
            data = JSON.parse(event.data)
            on_build("$0", data.errors || []) if data.action == 'built'
        catch e
            console.warn("HR Error: #{e}")

    window.addEventListener("beforeunload", disconnect)

    connection.timeout_timer = setInterval((-> if connection.last_active? and new Date() - connection.last_active > connection_timeout then disconnect()), connection_timeout)

# publishDevLibrary :: (static_id) -> Promise<{status: 'ok', hash: string} | {status: 'net-err', error} | {status: 'user-err', error}>
# status 'ok'  == library was successfully uploaded
# status 'net-err' == Unable to reach the CLI
# status 'user-err' == user code has errors
# promise throws = pagedraw error, crash


Prompt:
exports.subscribeToDevServer = (on_build) ->
    # library in development always has id == $0
    # when we add support for multiple libraries we'll need to
    # add support for more ids too, which should be of the format
    # $1, $2, $3...
    disconnect = ->
        if connection.timeout_timer? then clearInterval(connection.timeout_timer)
        connection.source?.close()
        delete connection.source
        on_build("0", ['disconnected'])

    connection.source = source = new window.EventSource("#{devcodeserver}/__webpack_hmr")
    source.onopen = -> connection.last_active = new Date()
    source.onerror = ->
        disconnect()
    source.onmessage = (event) ->

Response:
connection.last_active = new Date()
        return if event.data == "\uD83D\uDC93" #dev server heartbeat
        try
            data = JSON.parse(event.data)
            on_build("$0", data.errors || []) if data.action == 'built'
        catch e
            console.warn("HR Error: #{e}")

    window.addEventListener("beforeunload", disconnect)

    connection.timeout_timer = setInterval((-> if connection.last_active? and new Date() - connection.last_active > connection_timeout then disconnect()), connection_timeout)

# publishDevLibrary :: (static_id) -> Promise<{status: 'ok', hash: string} | {status: 'net-err', error} | {status: 'user-err', error}>
# status 'ok'  == library was successfully uploaded
# status 'net-err' == Unable to reach the CLI
# status 'user-err' == user code has errors
# promise throws = pagedraw error, crash


Response:
exports.publishDevLibrary = (static_id) ->
    new Promise (resolve, reject) ->
        uploadLibraryData(static_id).then(({status, error, id}) ->
            if status =='internal-err' then reject(new Error("Internal error while uploading library"))
            else resolve({status, error, hash: id})
        )


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
exports.publishDevLibrary = (static_id) ->
    new Promise (resolve, reject) ->
        uploadLibraryData(static_id).then(({status, error, id}) ->
            if status =='internal-err' then reject(new Error("Internal error while uploading library"))
            else resolve({status, error, hash: id})
        )
```

Response:
exports.publishDevLibrary = function(static_id) {
  return new Promise(function(resolve, reject) {
    return uploadLibraryData(static_id).then(function({status, error, id}) {
      if (status === 'internal-err') {
        return reject(new Error("Internal error while uploading library"));
      } else {
        return resolve({
          status,
          error,
          hash: id
        });
      }
    });
  });
};


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
exports.publishDevLibrary = function(static_id) {
  return new Promise(function(resolve, reject) {
    return uploadLibraryData(static_id).then(function({status, error, id}) {
      if (status === 'internal-err') {
        return reject(new Error("Internal error while uploading library"));
      } else {
        return resolve({
          status,
          error,
          hash: id
        });
      }
    });
  });
};
```

Response:
exports.publishDevLibrary = (static_id) ->
    new Promise (resolve, reject) ->
        uploadLibraryData(static_id).then(({status, error, id}) ->
            if status =='internal-err' then reject(new Error("Internal error while uploading library"))
            else resolve({status, error, hash: id})
        )


Prompt:
exports.publishDevLibrary = (static_id) ->
    new Promise (resolve, reject) ->
        uploadLibraryData(static_id).then(({status, error, id}) ->

Response:
if status =='internal-err' then reject(new Error("Internal error while uploading library"))
            else resolve({status, error, hash: id})
        )


Response:
uploadLibraryData = (static_id) ->
    payload = { static_id, host: extcodeserver, metaserver: config.metaserver }
    fetch("#{devcodeserver}/exit_dev", {
        method: 'POST',
        headers: {"Content-Type": "application/json"},
        body: JSON.stringify(payload)
    }).then((response) ->
        if not response.ok then throw new Error()
        else return response.json()
    ).catch (error) ->
        return { status: 'net-err', error: new Error('Unable to connect to the CLI')}


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
uploadLibraryData = (static_id) ->
    payload = { static_id, host: extcodeserver, metaserver: config.metaserver }
    fetch("#{devcodeserver}/exit_dev", {
        method: 'POST',
        headers: {"Content-Type": "application/json"},
        body: JSON.stringify(payload)
    }).then((response) ->
        if not response.ok then throw new Error()
        else return response.json()
    ).catch (error) ->
        return { status: 'net-err', error: new Error('Unable to connect to the CLI')}
```

Response:
var uploadLibraryData;

uploadLibraryData = function(static_id) {
  var payload;
  payload = {
    static_id,
    host: extcodeserver,
    metaserver: config.metaserver
  };
  return fetch(`${devcodeserver}/exit_dev`, {
    method: 'POST',
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify(payload)
  }).then(function(response) {
    if (!response.ok) {
      throw new Error();
    } else {
      return response.json();
    }
  }).catch(function(error) {
    return {
      status: 'net-err',
      error: new Error('Unable to connect to the CLI')
    };
  });
};


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
var uploadLibraryData;

uploadLibraryData = function(static_id) {
  var payload;
  payload = {
    static_id,
    host: extcodeserver,
    metaserver: config.metaserver
  };
  return fetch(`${devcodeserver}/exit_dev`, {
    method: 'POST',
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify(payload)
  }).then(function(response) {
    if (!response.ok) {
      throw new Error();
    } else {
      return response.json();
    }
  }).catch(function(error) {
    return {
      status: 'net-err',
      error: new Error('Unable to connect to the CLI')
    };
  });
};
```

Response:
uploadLibraryData = (static_id) ->
    payload = { static_id, host: extcodeserver, metaserver: config.metaserver }
    fetch("#{devcodeserver}/exit_dev", {
        method: 'POST',
        headers: {"Content-Type": "application/json"},
        body: JSON.stringify(payload)
    }).then((response) ->
        if not response.ok then throw new Error()
        else return response.json()
    ).catch (error) ->
        return { status: 'net-err', error: new Error('Unable to connect to the CLI')}


Prompt:
uploadLibraryData = (static_id) ->
    payload = { static_id, host: extcodeserver, metaserver: config.metaserver }
    fetch("#{devcodeserver}/exit_dev", {
        method: 'POST',
        headers: {"Content-Type": "application/json"},

Response:
body: JSON.stringify(payload)
    }).then((response) ->
        if not response.ok then throw new Error()
        else return response.json()
    ).catch (error) ->
        return { status: 'net-err', error: new Error('Unable to connect to the CLI')}


Response:
exports.libraryCliAlive = ->
    fetch("#{devcodeserver}/are-you-alive").then((response) ->
        response.ok
    ).catch(-> false)


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
exports.libraryCliAlive = ->
    fetch("#{devcodeserver}/are-you-alive").then((response) ->
        response.ok
    ).catch(-> false)
```

Response:
exports.libraryCliAlive = function() {
  return fetch(`${devcodeserver}/are-you-alive`).then(function(response) {
    return response.ok;
  }).catch(function() {
    return false;
  });
};


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
exports.libraryCliAlive = function() {
  return fetch(`${devcodeserver}/are-you-alive`).then(function(response) {
    return response.ok;
  }).catch(function() {
    return false;
  });
};
```

Response:
exports.libraryCliAlive = ->
    fetch("#{devcodeserver}/are-you-alive").then((response) ->
        response.ok
    ).catch(-> false)


Prompt:
exports.libraryCliAlive = ->
    fetch("#{devcodeserver}/are-you-alive").then((response) ->

Response:
response.ok
    ).catch(-> false)


Response:
do ($$ = Quo) ->

    ELEMENT_ID = 1
    HANDLERS = {}
    EVENT_METHODS =
        preventDefault: "isDefaultPrevented"
        stopImmediatePropagation: "isImmediatePropagationStopped"
        stopPropagation: "isPropagationStopped"
    EVENTS_DESKTOP =
        touchstart: "mousedown"
        touchmove: "mousemove"
        touchend: "mouseup"
        touch: "click"
        doubletap: "dblclick"
        orientationchange: "resize"

    READY_EXPRESSION = /complete|loaded|interactive/

    $$.fn.on = (event, selector, callback) ->
        (if (selector is "undefined" or $$.toType(selector) is "function") then @bind(event, selector) else @delegate(selector, event, callback))

    $$.fn.off = (event, selector, callback) ->
        (if (selector is "undefined" or $$.toType(selector) is "function") then @unbind(event, selector) else @undelegate(selector, event, callback))

    $$.fn.ready = (callback) ->
        if READY_EXPRESSION.test(document.readyState)
            callback $$
        else
            $$.fn.addEvent document, "DOMContentLoaded", -> callback $$

    $$.Event = (type, touch) ->
        event = document.createEvent("Events")
        event.initEvent type, true, true, null, null, null, null, null, null, null, null, null, null, null, null
        if touch
            event[property] = touch[property] for property of touch
        event

    $$.fn.bind = (event, callback) ->
        @each ->
            _subscribe @, event, callback
            return


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
do ($$ = Quo) ->

    ELEMENT_ID = 1
    HANDLERS = {}
    EVENT_METHODS =
        preventDefault: "isDefaultPrevented"
        stopImmediatePropagation: "isImmediatePropagationStopped"
        stopPropagation: "isPropagationStopped"
    EVENTS_DESKTOP =
        touchstart: "mousedown"
        touchmove: "mousemove"
        touchend: "mouseup"
        touch: "click"
        doubletap: "dblclick"
        orientationchange: "resize"

    READY_EXPRESSION = /complete|loaded|interactive/

    $$.fn.on = (event, selector, callback) ->
        (if (selector is "undefined" or $$.toType(selector) is "function") then @bind(event, selector) else @delegate(selector, event, callback))

    $$.fn.off = (event, selector, callback) ->
        (if (selector is "undefined" or $$.toType(selector) is "function") then @unbind(event, selector) else @undelegate(selector, event, callback))

    $$.fn.ready = (callback) ->
        if READY_EXPRESSION.test(document.readyState)
            callback $$
        else
            $$.fn.addEvent document, "DOMContentLoaded", -> callback $$

    $$.Event = (type, touch) ->
        event = document.createEvent("Events")
        event.initEvent type, true, true, null, null, null, null, null, null, null, null, null, null, null, null
        if touch
            event[property] = touch[property] for property of touch
        event

    $$.fn.bind = (event, callback) ->
        @each ->
            _subscribe @, event, callback
            return
```

Response:
(function($$) {
  var ELEMENT_ID, EVENTS_DESKTOP, EVENT_METHODS, HANDLERS, READY_EXPRESSION;
  ELEMENT_ID = 1;
  HANDLERS = {};
  EVENT_METHODS = {
    preventDefault: "isDefaultPrevented",
    stopImmediatePropagation: "isImmediatePropagationStopped",
    stopPropagation: "isPropagationStopped"
  };
  EVENTS_DESKTOP = {
    touchstart: "mousedown",
    touchmove: "mousemove",
    touchend: "mouseup",
    touch: "click",
    doubletap: "dblclick",
    orientationchange: "resize"
  };
  READY_EXPRESSION = /complete|loaded|interactive/;
  $$.fn.on = function(event, selector, callback) {
    if (selector === "undefined" || $$.toType(selector) === "function") {
      return this.bind(event, selector);
    } else {
      return this.delegate(selector, event, callback);
    }
  };
  $$.fn.off = function(event, selector, callback) {
    if (selector === "undefined" || $$.toType(selector) === "function") {
      return this.unbind(event, selector);
    } else {
      return this.undelegate(selector, event, callback);
    }
  };
  $$.fn.ready = function(callback) {
    if (READY_EXPRESSION.test(document.readyState)) {
      return callback($$);
    } else {
      return $$.fn.addEvent(document, "DOMContentLoaded", function() {
        return callback($$);
      });
    }
  };
  $$.Event = function(type, touch) {
    var event, property;
    event = document.createEvent("Events");
    event.initEvent(type, true, true, null, null, null, null, null, null, null, null, null, null, null, null);
    if (touch) {
      for (property in touch) {
        event[property] = touch[property];
      }
    }
    return event;
  };
  return $$.fn.bind = function(event, callback) {
    return this.each(function() {
      _subscribe(this, event, callback);
    });
  };
})(Quo);


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
(function($$) {
  var ELEMENT_ID, EVENTS_DESKTOP, EVENT_METHODS, HANDLERS, READY_EXPRESSION;
  ELEMENT_ID = 1;
  HANDLERS = {};
  EVENT_METHODS = {
    preventDefault: "isDefaultPrevented",
    stopImmediatePropagation: "isImmediatePropagationStopped",
    stopPropagation: "isPropagationStopped"
  };
  EVENTS_DESKTOP = {
    touchstart: "mousedown",
    touchmove: "mousemove",
    touchend: "mouseup",
    touch: "click",
    doubletap: "dblclick",
    orientationchange: "resize"
  };
  READY_EXPRESSION = /complete|loaded|interactive/;
  $$.fn.on = function(event, selector, callback) {
    if (selector === "undefined" || $$.toType(selector) === "function") {
      return this.bind(event, selector);
    } else {
      return this.delegate(selector, event, callback);
    }
  };
  $$.fn.off = function(event, selector, callback) {
    if (selector === "undefined" || $$.toType(selector) === "function") {
      return this.unbind(event, selector);
    } else {
      return this.undelegate(selector, event, callback);
    }
  };
  $$.fn.ready = function(callback) {
    if (READY_EXPRESSION.test(document.readyState)) {
      return callback($$);
    } else {
      return $$.fn.addEvent(document, "DOMContentLoaded", function() {
        return callback($$);
      });
    }
  };
  $$.Event = function(type, touch) {
    var event, property;
    event = document.createEvent("Events");
    event.initEvent(type, true, true, null, null, null, null, null, null, null, null, null, null, null, null);
    if (touch) {
      for (property in touch) {
        event[property] = touch[property];
      }
    }
    return event;
  };
  return $$.fn.bind = function(event, callback) {
    return this.each(function() {
      _subscribe(this, event, callback);
    });
  };
})(Quo);
```

Response:
do ($$ = Quo) ->

    ELEMENT_ID = 1
    HANDLERS = {}
    EVENT_METHODS =
        preventDefault: "isDefaultPrevented"
        stopImmediatePropagation: "isImmediatePropagationStopped"
        stopPropagation: "isPropagationStopped"
    EVENTS_DESKTOP =
        touchstart: "mousedown"
        touchmove: "mousemove"
        touchend: "mouseup"
        touch: "click"
        doubletap: "dblclick"
        orientationchange: "resize"

    READY_EXPRESSION = /complete|loaded|interactive/

    $$.fn.on = (event, selector, callback) ->
        (if (selector is "undefined" or $$.toType(selector) is "function") then @bind(event, selector) else @delegate(selector, event, callback))

    $$.fn.off = (event, selector, callback) ->
        (if (selector is "undefined" or $$.toType(selector) is "function") then @unbind(event, selector) else @undelegate(selector, event, callback))

    $$.fn.ready = (callback) ->
        if READY_EXPRESSION.test(document.readyState)
            callback $$
        else
            $$.fn.addEvent document, "DOMContentLoaded", -> callback $$

    $$.Event = (type, touch) ->
        event = document.createEvent("Events")
        event.initEvent type, true, true, null, null, null, null, null, null, null, null, null, null, null, null
        if touch
            event[property] = touch[property] for property of touch
        event

    $$.fn.bind = (event, callback) ->
        @each ->
            _subscribe @, event, callback
            return


Prompt:
do ($$ = Quo) ->

    ELEMENT_ID = 1
    HANDLERS = {}
    EVENT_METHODS =
        preventDefault: "isDefaultPrevented"
        stopImmediatePropagation: "isImmediatePropagationStopped"
        stopPropagation: "isPropagationStopped"
    EVENTS_DESKTOP =
        touchstart: "mousedown"
        touchmove: "mousemove"
        touchend: "mouseup"
        touch: "click"
        doubletap: "dblclick"
        orientationchange: "resize"

    READY_EXPRESSION = /complete|loaded|interactive/

    $$.fn.on = (event, selector, callback) ->
        (if (selector is "undefined" or $$.toType(selector) is "function") then @bind(event, selector) else @delegate(selector, event, callback))

Response:
$$.fn.off = (event, selector, callback) ->
        (if (selector is "undefined" or $$.toType(selector) is "function") then @unbind(event, selector) else @undelegate(selector, event, callback))

    $$.fn.ready = (callback) ->
        if READY_EXPRESSION.test(document.readyState)
            callback $$
        else
            $$.fn.addEvent document, "DOMContentLoaded", -> callback $$

    $$.Event = (type, touch) ->
        event = document.createEvent("Events")
        event.initEvent type, true, true, null, null, null, null, null, null, null, null, null, null, null, null
        if touch
            event[property] = touch[property] for property of touch
        event

    $$.fn.bind = (event, callback) ->
        @each ->
            _subscribe @, event, callback
            return


Response:
$$.fn.unbind = (event, callback) ->
        @each ->
            _unsubscribe @, event, callback
            return

    $$.fn.delegate = (selector, event, callback) ->
        @each (i, element) ->
            _subscribe element, event, callback, selector, (fn) ->
                (e) ->
                    match = $$(e.target).closest(selector, element).get(0)
                    if match
                        evt = $$.extend(_createProxy(e),
                            currentTarget: match
                            liveFired: element
                        )
                        fn.apply match, [ evt ].concat([].slice.call(arguments, 1))
            return

    $$.fn.undelegate = (selector, event, callback) ->
        @each ->
            _unsubscribe @, event, callback, selector
            return

    $$.fn.trigger = (event, touch, originalEvent) ->
        event = $$.Event(event, touch) if $$.toType(event) is "string"
        event.originalEvent = originalEvent if originalEvent?
        @each ->
            @dispatchEvent event
            return

    $$.fn.addEvent = (element, event_name, callback) ->
        if element.addEventListener
            element.addEventListener event_name, callback, false
        else if element.attachEvent
            element.attachEvent "on" + event_name, callback
        else
            element["on" + event_name] = callback

    $$.fn.removeEvent = (element, event_name, callback) ->
        if element.removeEventListener
            element.removeEventListener event_name, callback, false
        else if element.detachEvent
            element.detachEvent "on" + event_name, callback
        else
            element["on" + event_name] = null


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
$$.fn.unbind = (event, callback) ->
        @each ->
            _unsubscribe @, event, callback
            return

    $$.fn.delegate = (selector, event, callback) ->
        @each (i, element) ->
            _subscribe element, event, callback, selector, (fn) ->
                (e) ->
                    match = $$(e.target).closest(selector, element).get(0)
                    if match
                        evt = $$.extend(_createProxy(e),
                            currentTarget: match
                            liveFired: element
                        )
                        fn.apply match, [ evt ].concat([].slice.call(arguments, 1))
            return

    $$.fn.undelegate = (selector, event, callback) ->
        @each ->
            _unsubscribe @, event, callback, selector
            return

    $$.fn.trigger = (event, touch, originalEvent) ->
        event = $$.Event(event, touch) if $$.toType(event) is "string"
        event.originalEvent = originalEvent if originalEvent?
        @each ->
            @dispatchEvent event
            return

    $$.fn.addEvent = (element, event_name, callback) ->
        if element.addEventListener
            element.addEventListener event_name, callback, false
        else if element.attachEvent
            element.attachEvent "on" + event_name, callback
        else
            element["on" + event_name] = callback

    $$.fn.removeEvent = (element, event_name, callback) ->
        if element.removeEventListener
            element.removeEventListener event_name, callback, false
        else if element.detachEvent
            element.detachEvent "on" + event_name, callback
        else
            element["on" + event_name] = null
```

Response:
$$.fn.unbind = function(event, callback) {
  return this.each(function() {
    _unsubscribe(this, event, callback);
  });
};

$$.fn.delegate = function(selector, event, callback) {
  return this.each(function(i, element) {
    _subscribe(element, event, callback, selector, function(fn) {
      return function(e) {
        var evt, match;
        match = $$(e.target).closest(selector, element).get(0);
        if (match) {
          evt = $$.extend(_createProxy(e), {
            currentTarget: match,
            liveFired: element
          });
          return fn.apply(match, [evt].concat([].slice.call(arguments, 1)));
        }
      };
    });
  });
};

$$.fn.undelegate = function(selector, event, callback) {
  return this.each(function() {
    _unsubscribe(this, event, callback, selector);
  });
};

$$.fn.trigger = function(event, touch, originalEvent) {
  if ($$.toType(event) === "string") {
    event = $$.Event(event, touch);
  }
  if (originalEvent != null) {
    event.originalEvent = originalEvent;
  }
  return this.each(function() {
    this.dispatchEvent(event);
  });
};

$$.fn.addEvent = function(element, event_name, callback) {
  if (element.addEventListener) {
    return element.addEventListener(event_name, callback, false);
  } else if (element.attachEvent) {
    return element.attachEvent("on" + event_name, callback);
  } else {
    return element["on" + event_name] = callback;
  }
};

$$.fn.removeEvent = function(element, event_name, callback) {
  if (element.removeEventListener) {
    return element.removeEventListener(event_name, callback, false);
  } else if (element.detachEvent) {
    return element.detachEvent("on" + event_name, callback);
  } else {
    return element["on" + event_name] = null;
  }
};


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
$$.fn.unbind = function(event, callback) {
  return this.each(function() {
    _unsubscribe(this, event, callback);
  });
};

$$.fn.delegate = function(selector, event, callback) {
  return this.each(function(i, element) {
    _subscribe(element, event, callback, selector, function(fn) {
      return function(e) {
        var evt, match;
        match = $$(e.target).closest(selector, element).get(0);
        if (match) {
          evt = $$.extend(_createProxy(e), {
            currentTarget: match,
            liveFired: element
          });
          return fn.apply(match, [evt].concat([].slice.call(arguments, 1)));
        }
      };
    });
  });
};

$$.fn.undelegate = function(selector, event, callback) {
  return this.each(function() {
    _unsubscribe(this, event, callback, selector);
  });
};

$$.fn.trigger = function(event, touch, originalEvent) {
  if ($$.toType(event) === "string") {
    event = $$.Event(event, touch);
  }
  if (originalEvent != null) {
    event.originalEvent = originalEvent;
  }
  return this.each(function() {
    this.dispatchEvent(event);
  });
};

$$.fn.addEvent = function(element, event_name, callback) {
  if (element.addEventListener) {
    return element.addEventListener(event_name, callback, false);
  } else if (element.attachEvent) {
    return element.attachEvent("on" + event_name, callback);
  } else {
    return element["on" + event_name] = callback;
  }
};

$$.fn.removeEvent = function(element, event_name, callback) {
  if (element.removeEventListener) {
    return element.removeEventListener(event_name, callback, false);
  } else if (element.detachEvent) {
    return element.detachEvent("on" + event_name, callback);
  } else {
    return element["on" + event_name] = null;
  }
};
```

Response:
$$.fn.unbind = (event, callback) ->
        @each ->
            _unsubscribe @, event, callback
            return

    $$.fn.delegate = (selector, event, callback) ->
        @each (i, element) ->
            _subscribe element, event, callback, selector, (fn) ->
                (e) ->
                    match = $$(e.target).closest(selector, element).get(0)
                    if match
                        evt = $$.extend(_createProxy(e),
                            currentTarget: match
                            liveFired: element
                        )
                        fn.apply match, [ evt ].concat([].slice.call(arguments, 1))
            return

    $$.fn.undelegate = (selector, event, callback) ->
        @each ->
            _unsubscribe @, event, callback, selector
            return

    $$.fn.trigger = (event, touch, originalEvent) ->
        event = $$.Event(event, touch) if $$.toType(event) is "string"
        event.originalEvent = originalEvent if originalEvent?
        @each ->
            @dispatchEvent event
            return

    $$.fn.addEvent = (element, event_name, callback) ->
        if element.addEventListener
            element.addEventListener event_name, callback, false
        else if element.attachEvent
            element.attachEvent "on" + event_name, callback
        else
            element["on" + event_name] = callback

    $$.fn.removeEvent = (element, event_name, callback) ->
        if element.removeEventListener
            element.removeEventListener event_name, callback, false
        else if element.detachEvent
            element.detachEvent "on" + event_name, callback
        else
            element["on" + event_name] = null


Prompt:
$$.fn.unbind = (event, callback) ->
        @each ->
            _unsubscribe @, event, callback
            return

    $$.fn.delegate = (selector, event, callback) ->
        @each (i, element) ->
            _subscribe element, event, callback, selector, (fn) ->
                (e) ->
                    match = $$(e.target).closest(selector, element).get(0)
                    if match
                        evt = $$.extend(_createProxy(e),
                            currentTarget: match
                            liveFired: element
                        )
                        fn.apply match, [ evt ].concat([].slice.call(arguments, 1))
            return

    $$.fn.undelegate = (selector, event, callback) ->
        @each ->
            _unsubscribe @, event, callback, selector
            return

Response:
$$.fn.trigger = (event, touch, originalEvent) ->
        event = $$.Event(event, touch) if $$.toType(event) is "string"
        event.originalEvent = originalEvent if originalEvent?
        @each ->
            @dispatchEvent event
            return

    $$.fn.addEvent = (element, event_name, callback) ->
        if element.addEventListener
            element.addEventListener event_name, callback, false
        else if element.attachEvent
            element.attachEvent "on" + event_name, callback
        else
            element["on" + event_name] = callback

    $$.fn.removeEvent = (element, event_name, callback) ->
        if element.removeEventListener
            element.removeEventListener event_name, callback, false
        else if element.detachEvent
            element.detachEvent "on" + event_name, callback
        else
            element["on" + event_name] = null


Response:
_subscribe = (element, event, callback, selector, delegate_callback) ->
        event = _environmentEvent(event)
        element_id = _getElementId(element)
        element_handlers = HANDLERS[element_id] or (HANDLERS[element_id] = [])
        delegate = delegate_callback and delegate_callback(callback, event)
        handler =
            event: event
            callback: callback
            selector: selector
            proxy: _createProxyCallback(delegate, callback, element)
            delegate: delegate
            index: element_handlers.length

        element_handlers.push handler
        $$.fn.addEvent element, handler.event, handler.proxy

    _unsubscribe = (element, event, callback, selector) ->
        event = _environmentEvent(event)
        element_id = _getElementId(element)
        _findHandlers(element_id, event, callback, selector).forEach (handler) ->
            delete HANDLERS[element_id][handler.index]

            $$.fn.removeEvent element, handler.event, handler.proxy

    _getElementId = (element) -> element._id or (element._id = ELEMENT_ID++)

    _environmentEvent = (event) ->
        environment_event = (if ($$.isMobile()) then event else EVENTS_DESKTOP[event])
        (environment_event) or event

    _createProxyCallback = (delegate, callback, element) ->
        callback = delegate or callback
        proxy = (event) ->
            result = callback.apply(element, [ event ].concat(event.data))
            event.preventDefault() if result is false
            result
        proxy

    _findHandlers = (element_id, event, fn, selector) ->
        (HANDLERS[element_id] or []).filter (handler) ->
            handler and (not event or handler.event is event) and (not fn or handler.callback is fn) and (not selector or handler.selector is selector)


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
_subscribe = (element, event, callback, selector, delegate_callback) ->
        event = _environmentEvent(event)
        element_id = _getElementId(element)
        element_handlers = HANDLERS[element_id] or (HANDLERS[element_id] = [])
        delegate = delegate_callback and delegate_callback(callback, event)
        handler =
            event: event
            callback: callback
            selector: selector
            proxy: _createProxyCallback(delegate, callback, element)
            delegate: delegate
            index: element_handlers.length

        element_handlers.push handler
        $$.fn.addEvent element, handler.event, handler.proxy

    _unsubscribe = (element, event, callback, selector) ->
        event = _environmentEvent(event)
        element_id = _getElementId(element)
        _findHandlers(element_id, event, callback, selector).forEach (handler) ->
            delete HANDLERS[element_id][handler.index]

            $$.fn.removeEvent element, handler.event, handler.proxy

    _getElementId = (element) -> element._id or (element._id = ELEMENT_ID++)

    _environmentEvent = (event) ->
        environment_event = (if ($$.isMobile()) then event else EVENTS_DESKTOP[event])
        (environment_event) or event

    _createProxyCallback = (delegate, callback, element) ->
        callback = delegate or callback
        proxy = (event) ->
            result = callback.apply(element, [ event ].concat(event.data))
            event.preventDefault() if result is false
            result
        proxy

    _findHandlers = (element_id, event, fn, selector) ->
        (HANDLERS[element_id] or []).filter (handler) ->
            handler and (not event or handler.event is event) and (not fn or handler.callback is fn) and (not selector or handler.selector is selector)
```

Response:
var _createProxyCallback, _environmentEvent, _findHandlers, _getElementId, _subscribe, _unsubscribe;

_subscribe = function(element, event, callback, selector, delegate_callback) {
  var delegate, element_handlers, element_id, handler;
  event = _environmentEvent(event);
  element_id = _getElementId(element);
  element_handlers = HANDLERS[element_id] || (HANDLERS[element_id] = []);
  delegate = delegate_callback && delegate_callback(callback, event);
  handler = {
    event: event,
    callback: callback,
    selector: selector,
    proxy: _createProxyCallback(delegate, callback, element),
    delegate: delegate,
    index: element_handlers.length
  };
  element_handlers.push(handler);
  return $$.fn.addEvent(element, handler.event, handler.proxy);
};

_unsubscribe = function(element, event, callback, selector) {
  var element_id;
  event = _environmentEvent(event);
  element_id = _getElementId(element);
  return _findHandlers(element_id, event, callback, selector).forEach(function(handler) {
    delete HANDLERS[element_id][handler.index];
    return $$.fn.removeEvent(element, handler.event, handler.proxy);
  });
};

_getElementId = function(element) {
  return element._id || (element._id = ELEMENT_ID++);
};

_environmentEvent = function(event) {
  var environment_event;
  environment_event = (($$.isMobile()) ? event : EVENTS_DESKTOP[event]);
  return environment_event || event;
};

_createProxyCallback = function(delegate, callback, element) {
  var proxy;
  callback = delegate || callback;
  proxy = function(event) {
    var result;
    result = callback.apply(element, [event].concat(event.data));
    if (result === false) {
      event.preventDefault();
    }
    return result;
  };
  return proxy;
};

_findHandlers = function(element_id, event, fn, selector) {
  return (HANDLERS[element_id] || []).filter(function(handler) {
    return handler && (!event || handler.event === event) && (!fn || handler.callback === fn) && (!selector || handler.selector === selector);
  });
};