bugfix delegate it's not _parent

bugfix delegate it's not _parent

--- lib/Context.coffee
+++ lib/Context.coffee
@@ -606,10 +606,10 @@
             #@logger.info 'delegation of method', method, args

             _parent = @parent
-            while _parent && !_parent[method] && _parent._parent
+            while _parent && !_parent[method] && _parent.parent
                 #@logger.info 'checking parent', _parent.id

-                _parent = _parent._parent
+                _parent = _parent.parent

             if _parent && _parent[method]
                 #@logger.info 'using parent', _parent.id
@@ -622,6 +622,7 @@
                     throw err

             else
+                #@logger.info 'missed', method
                 return success: false

         ##


Make rotational velocity play nice with mulitplayer

--- src/public/scripts/models/entity._.coffee
+++ src/public/scripts/models/entity._.coffee
@@ -28,7 +28,7 @@
 			@applyGravity = false

 			@velocity = new Three.Vector3(0, 0, 0)
-			@angularVelocity = new Three.Quaternion()
+			@angularVelocity = new Three.Euler(0, 0, 0, 'YXZ')

 			@forces = []
 			@angularForces = []
@@ -85,15 +85,14 @@
 			# Apply forces ...
 			if updatePosition

-				# Set our last position if we don't have one yet.
-				unless @_lastPosition?
-					@_lastPosition = @position.clone()
+				# Calculate our new position from the velocity.
+				@position.add(@velocity.clone().multiplyScalar(dt))

-				# Calculate our current velocity by subtracting our current position
-				# from our last position, and set our position as lastPosition to
-				# calculate the velocity in the next loop.
-				@velocity = @position.clone().sub(@_lastPosition).divideScalar(dt)
-				@_lastPosition = @position.clone()
+				# Rudimentary way to detect of we're on the planet surface. This should
+				# be replaced by collision detection.
+				if @position.length() < 300
+					@position.normalize().multiplyScalar(300)
+					@velocity.projectOnPlane(@position)

 				# Loop through all forces and calculate the acceleration.
 				acceleration = new Three.Vector3(0, 0, 0)
@@ -109,47 +108,43 @@
 				dragForce = @velocity.clone().normalize().negate().multiplyScalar(.5 * 1.2 * @drag * @velocity.lengthSq())
 				@velocity.add(dragForce.divideScalar(@mass))

-				# Calculate our new position from the velocity.
-				@position.add(@velocity.clone().multiplyScalar(dt))
-
-				# Rudimentary way to detect of we're on the planet surface. This should
-				# be replaced by collision detection.
-				if @position.length() < 300
-					@position.normalize().multiplyScalar(300)
-					@velocity.projectOnPlane(@position)
-
-			# ... and apply rotational forces
+			# ... and apply rotational forces. The method of applying rotational forces and
+			# mainly for using angular velocity may look a bit strange, but this does really
+			# seem to be the best way of doing it.
 			if updateRotation

-				# Set our last rotation if we don't have one yet.
-				unless @_lastRotation?
-					@_lastRotation = @rotation.clone()
+				# Calculate the change of rotation for this time step ...
+				angularDelta = @angularVelocity.clone()

-				# Calculate our current angular velocity by subtracting our current rotation
-				# from our last rotation, and set our rotation as lastRotation to
-				# calculate the angular velocity in the next loop.
-				rotationQuaternion = new Three.Quaternion().setFromEuler(@rotation)
-				lastRotationQuaternion = new Three.Quaternion().setFromEuler(@_lastRotation)
-
-				@angularVelocity = lastRotationQuaternion.clone().inverse().multiply(rotationQuaternion)
-				@_lastRotation = @rotation.clone()
+				angularDelta.x *= dt
+				angularDelta.y *= dt
+				angularDelta.z *= dt
+
+				angularDeltaQuaternion = new Three.Quaternion().setFromEuler(angularDelta)
+
+				# ... and multiply this delta with the current rotation to get the new rotation.
+				rotationQuaternion = new Three.Quaternion().setFromEuler(@rotation)
+				rotationQuaternion.multiply(angularDeltaQuaternion)
+				@rotation.setFromQuaternion(rotationQuaternion)

 				# Loop through all angular forces and calculate the angular acceleration.
-				angularAcceleration = new Three.Quaternion()
+				angularAccelerationQuaternion = new Three.Quaternion()
 				while force = @angularForces.pop()
 					forceQuaternion = new Three.Quaternion().setFromEuler(force)
-					angularAcceleration.multiply(forceQuaternion)
+					angularAccelerationQuaternion.multiply(forceQuaternion)

-				# Calculate our new rotation from the angular velocity and acceleration.
-				targetRotationQuaternion = rotationQuaternion.clone()
-				targetRotationQuaternion.slerp(rotationQuaternion.clone().multiply(angularAcceleration), dt)
-				targetRotationQuaternion.multiply(@angularVelocity)
+				angularAcceleration = new Three.Euler().setFromQuaternion(angularAccelerationQuaternion, 'YXZ')

-				# Add drag force to the rotation.
-				targetRotationQuaternion.slerp(rotationQuaternion, @angularDrag * dt)
+				# Apply the acceleration to the angular velocity
+				@angularVelocity.x += angularAcceleration.x
+				@angularVelocity.y += angularAcceleration.y
+				@angularVelocity.z += angularAcceleration.z

-				# Calculate and set our new rotation from the angular velocity.
-				@rotation.setFromQuaternion(targetRotationQuaternion)
+				# Apply drag force to the angular velocity. This way of doing it is pretty
+				# basic, but should be sufficient.
+				@angularVelocity.x *= 1 - @angularDrag * dt
+				@angularVelocity.y *= 1 - @angularDrag * dt
+				@angularVelocity.z *= 1 - @angularDrag * dt

 		# Applies transformation information given in an object to the entity.
 		#


more console logs :(

more console logs :(

--- models/article.coffee
+++ models/article.coffee
@@ -62,7 +62,6 @@
         for id in @get('super_article').related_articles
           dfds.push new Article(id: id).fetch
             success: (article) ->
-              console.log 'success'
               relatedArticles.add article
       Q.allSettled(dfds).fin =>
         @set('section', section) if section


[Bugfix] Fix pagination

[Bugfix] Fix pagination

--- src/desktop/components/artwork_filter_2/models/filter.coffee
+++ src/desktop/components/artwork_filter_2/models/filter.coffee
@@ -6,7 +6,7 @@
 module.exports = class ArtworkFilter extends Backbone.Model

   page: 1
-  size: 9
+  size: 40
   artworks: []
   reset: true


em_alg: style changes (e.g. bigger text)

--- em_alg/em_alg.coffee
+++ em_alg/em_alg.coffee
@@ -58,12 +58,6 @@
     d3.select("svg")
       .datum(toplot)
       .call(mychart)
-
-    # x and y axis labels
-    d3.select("g.x.axis text.title").text(() ->
-                         return "Pr(AB | marker data)" if iteration == 0
-                         "Pr(AB | marker data, y, theta-hat)")
-    d3.select("g.y.axis text.title").text("Phenotype")

     # erase the points produced by scatterplot
     mychart.pointsSelect().remove()


:lipstick:

:lipstick:

--- lib/autocomplete-view.coffee
+++ lib/autocomplete-view.coffee
@@ -46,18 +46,15 @@

   selectItem: (item) ->
     super
-
     match = @getSelectedElement()
     @replaceSelectedTextWithMatch(match) if match

   selectNextItem: ->
     super
-
     false

   selectPreviousItem: ->
     super
-
     false

   getCompletionsForCursorScope: ->


rename

rename

--- jasmine-harness.coffee
+++ jasmine-harness.coffee
@@ -1,10 +1,10 @@
 attach = (obj) ->
   window[key] = obj[key] for key of obj

-jasmine = require('./spec/lib/jasmine.js')
+runner = require('./spec/lib/jasmine.js')

 # attach jasmine to window
-attach jasmine
+attach runner

 html = require './spec/lib/jasmine-html.js'
 tap = require './spec/lib/jasmine.tap_reporter.js'


uuid muffin fix

uuid muffin fix

--- server/src/Component/Builtin/Database/CouchMuffin.coffee
+++ server/src/Component/Builtin/Database/CouchMuffin.coffee
@@ -43,7 +43,8 @@
             return callback null, @_keyPrefix + '1'

     _uuid: ->
-        uuid.v4()
+        uuid = uuid.v4()
+        return "#{@_keyPrefix}#{uuid}"

     _counter: (callback) ->
         @_dataSource.bucket.counter @_counterKey, 1, (error, result) =>


add http helper class

add http helper class

--- test/app_test.coffee
+++ test/app_test.coffee
@@ -8,38 +8,38 @@

 base = 'http://localhost:3000'

-# Url helper prepends `base` to a relative `path`.
-abs_url = (path) ->
-  if ~path.search /https?:\/\// then path else base + path
-
-# Creates custom get helper.
-getFor = (agent) ->
-  return (path, cb) ->
-    agent.get( abs_url path ).end( cb )
-
-# Creates custom post helper.
-postFor = (agent) ->
-  return (path, data, cb) ->
-    agent.post( abs_url path ).send( data ).end( cb )
-
-# Creates custom put helper.
-putFor = (agent) ->
-  return (path, data, cb) ->
-    agent.put( abs_url path ).end( cb )
-
-# Creates custom delete helper.
-deleteFor = (agent) ->
-  return (path, cb) ->
-    agent.del( abs_url path ).end( cb )
+class HttpHelper
+
+  constructor: (@agent, @basepath) ->
+
+  absUrl: (path) ->
+    if ~path.search /https?:\/\// then path else @basepath + path
+
+  get: (path, cb) ->
+    @agent.get( @absUrl path ).end( cb )
+
+  post: (path, data, cb) ->
+    @agent.post( @absUrl path ).send( data ).end( cb )
+
+  put: (path, data, cb) ->
+    @agent.put( @absUrl path ).send( data ).end( cb )
+
+  del: (path, cb) ->
+    @agent.del( @absUrl path ).end( cb )
+
+# Http helper - provides http methods with agent & base url.
+httpHelper = (callback) ->
+  agent = superagent.agent()
+  callback new HttpHelper( agent, base )

 # Temp agent helper - provides callback with get, post, put, delete.
 tempAgent = (callback) ->
-  temp = superagent.agent()
-  post = postFor temp
-  get  = getFor temp
-  put  = putFor temp
-  del  = deleteFor temp
-  callback get, post, put, del
+  httpHelper (http) ->
+    post = http.post.bind http
+    get  = http.get.bind http
+    put  = http.put.bind http
+    del  = http.del.bind http
+    callback get, post, put, del

 # Session helper - provides logged in user with new account, get, post.
 session = (callback) ->
@@ -102,10 +102,10 @@
     callback(json)
   eval jsonp

-# Superagent helpers.
-agent = superagent.agent()
-get = getFor agent
-post = postFor agent
+# Http helpers.
+http = new HttpHelper( superagent.agent(), base )
+get = http.get.bind http
+post = http.post.bind http

 # Request helpers.
 req_get = (path, cb) ->


Fix an issue that menu does not work. Closes #2

--- menus/broadcast.cson
+++ menus/broadcast.cson
@@ -9,7 +9,8 @@
     'submenu': [
       'label': 'broadcast'
       'submenu': [
-        { 'label': 'Toggle', 'command': 'broadcast:toggle' }
+        { 'label': 'Start', 'command': 'broadcast:start' },
+        { 'label': 'Stop', 'command': 'broadcast:stop' }
       ]
     ]
   }


More events to listen

More events to listen

--- test/appveyor.coffee
+++ test/appveyor.coffee
@@ -22,8 +22,9 @@
   uri.headers =
     'Content-Type': 'application/json'
     'Content-Length': data.length
-  console.log 'POST', api, uri, data
-  q = http.request uri, ->
+  q = http.request uri, (res)->
+    res.on 'data', ->
+    res.on 'end', ->
   q.on 'error', ->
     console.error 'HTTP error!'
   q.end data


namespaced unbind

namespaced unbind

--- test/bindable.coffee
+++ test/bindable.coffee
@@ -43,6 +43,8 @@
   o.unbind "test"
   o.trigger "test"

+test "#ht"
+
 test "#unbind namespaced", 1, ->
   o = Object.extend({}, Bindable())


namespaced unbind

namespaced unbind

--- test/bindable.coffee
+++ test/bindable.coffee
@@ -46,7 +46,7 @@
 test "#unbind namespaced", ->
   o = Object.extend({}, Bindable())

-  o.bind "test",
+  o.bind "test", ->

 module()


Ignore boot calls before first document ready instead

--- resources/assets/lib/react-turbolinks.coffee
+++ resources/assets/lib/react-turbolinks.coffee
@@ -21,14 +21,18 @@

 export class ReactTurbolinks
   constructor: (@components = {}) ->
-    @navigated = false
+    @documentReady = false
     @targets = []
-    $(document).on 'turbolinks:load', @destroyPersisted
-    $(document).on 'turbolinks:load', @boot
+    $(document).on 'turbolinks:load', =>
+      @documentReady = true
+      @destroyPersisted()
+      @boot()
     $(document).on 'turbolinks:before-cache', @destroy

   boot: =>
+    return unless @documentReady
+
     for own _name, component of @components
       for target in component.targets
         continue if target.dataset.reactTurbolinksLoaded == '1'
@@ -38,8 +42,6 @@

   destroy: =>
-    @navigated = true
-
     for own _name, component of @components
       for target in component.targets
         continue if target.dataset.reactTurbolinksLoaded != '1'
@@ -48,8 +50,6 @@

   destroyPersisted: =>
-    return unless @navigated
-
     ReactDOM.unmountComponentAtNode(target) while target = @targets.pop()


noop mixpanel functions

noop mixpanel functions

--- js/app.coffee
+++ js/app.coffee
@@ -1,3 +1,14 @@
+noop = () ->
+  null
+
+window.mixpanel ||=
+  name_tag: noop
+  identify: noop
+  track: noop
+  track_link: noop
+  track_pageview: noop
+  register_once: noop
+
 CI.ajax.init()

 setOuter = =>


Tidy up some routes

Tidy up some routes

--- js/app.coffee
+++ js/app.coffee
@@ -271,17 +271,17 @@
     @get '^/admin/build-state', (cx) -> VM.loadAdminBuildState cx

     # outer
-    @get "/docs(.*)", (cx) => VM.docs.display(cx)
-    @get "/about.*", (cx) => VM.about.display(cx)
-    @get "/privacy.*", (cx) => VM.privacy.display(cx)
-    @get "/pricing.*", (cx) => VM.pricing.display(cx)
+    @get "^/docs(.*)", (cx) => VM.docs.display(cx)
+    @get "^/about.*", (cx) => VM.about.display(cx)
+    @get "^/privacy.*", (cx) => VM.privacy.display(cx)
+    @get "^/pricing.*", (cx) => VM.pricing.display(cx)

     @get '^(.*)', (cx) => VM.error.display(cx)

     # valid posts, allow to propegate
     @post '^/logout', -> true
     @post '^/admin/switch-user', -> true
-    @post "/about/contact", -> true # allow to propagate
+    @post "^/about/contact", -> true # allow to propagate

     @post '^/circumvent-sammy', (cx) -> true # dont show an error when posting


Factored out multiplicity

Factored out multiplicity

--- core/app/backbone/views/interactors_view.coffee
+++ core/app/backbone/views/interactors_view.coffee
@@ -27,16 +27,11 @@
       @render()

   templateHelpers: =>
-    if @collection.totalRecords > 1
-      translation = switch @collection.type
-        when 'weakening' then 'fact_disbelieve_past_plural_action'
-        when 'supporting' then 'fact_believe_past_plural_action'
-        when 'doubting' then 'fact_doubt_past_plural_action'
-    else
-      translation = switch @collection.type
-        when 'weakening' then 'fact_disbelieve_past_singular_action'
-        when 'supporting' then 'fact_believe_past_singular_action'
-        when 'doubting' then 'fact_doubt_past_singular_action'
+    multiplicity = if @collection.totalRecords > 1 then 'plural' else 'singular'
+    translation = switch @collection.type
+      when 'weakening' then "fact_disbelieve_past_#{multiplicity}_action"
+      when 'supporting' then "fact_believe_past_#{multiplicity}_action"
+      when 'doubting' then "fact_doubt_past_#{multiplicity}_action"

     past_action: Factlink.Global.t[translation]


add config export to netlify deployer

add config export to netlify deployer

--- lib/deployers/netlify/index.coffee
+++ lib/deployers/netlify/index.coffee
@@ -21,6 +21,9 @@
     , d.reject

   return d.promise
+
+module.exports.config =
+  required: ['name', 'access_token']

 ###*
  * Checks to see if your site is already on netlify or not. Returns either a


Remove unused ANCHOR_LOCATOR constant.

Remove unused ANCHOR_LOCATOR constant.

--- test/e2e/collectionListSpec.coffee
+++ test/e2e/collectionListSpec.coffee
@@ -8,9 +8,10 @@

 class CollectionListPage extends Page
-  # @param url the page request URL
   constructor: ->
-    # Call the Page superclass initializer. The
+    # Call the Page superclass initializer with the helpShown
+    # flag set to true, since the help box is displayed on
+    # this landing page.
     super('/quip?project=QIN_Test',  true)

   # @returns the collection {name, description, url} object
@@ -32,10 +33,6 @@
     webdriver.promise.all(finders).then (resolved) ->
       [name, desc, info] = resolved
       {name: name, description: desc, info: info}
-
-
-# Hyperlink locator.
-ANCHOR_LOCATOR = By.tagName('a')

 describe 'E2E Testing Collection List', ->


fixing help for --skip-media-upload

fixing help for --skip-media-upload

--- lib/panoptes-subject-uploader.iced
+++ lib/panoptes-subject-uploader.iced
@@ -43,7 +43,6 @@
   location[mimeType] = url
   location

-
 createSubject = (subjectData) ->
   return if ( !subjectData || !subjectData instanceof Object )
   subject = apiClient.type('subjects').create(subjectData)
@@ -86,7 +85,7 @@
       --subject-set "345"         If omitted, a new subject set is created
       --skip 50                   Skip the first N lines (per manifest file)
       --limit 100                 Only create N subjects (per manifest file)
-      --skip-media-upload         Default to false. Designates a supplied url for each subject, instead of uploading an image.
+      --skip-media-upload         Defaults to false. If set to true, subjects will be created using the urls provided in each row without uploading the associated media.

     Notes:
       Multiple manifests will end up in the same subject set.


fixed progs example

fixed progs example

--- example/prettyprogs.coffee
+++ example/prettyprogs.coffee
@@ -16,5 +16,6 @@
 	result.forEach (prog) ->
 		if pid==-1 then pid = prog.id
 		console.log "#{prog.id}: #{prog.name}"
-
-hm.runProgram url,pid
+	hm.runProgram url,pid
+	.then ->
+		console.log "running #{pid}"


do not allow to start an application while it's already starting

--- server/controllers/applications.coffee
+++ server/controllers/applications.coffee
@@ -5,6 +5,12 @@
 Application = require '../models/application'
 {AppManager} = require '../lib/paas'
 {Manifest} = require '../lib/manifest'
+
+# Small hack to ensure that an user don't try to start an application twice
+# at the same time. We store there the ID of apps which are already started.
+# IDs are the keys, values are all equal to true.
+startedApplications = {}
+stoppedInstallations = {}

 # Helpers

@@ -267,30 +273,50 @@
                             msg: 'Application succesfuly updated'

+    # Start a stopped application.
     start: (req, res, next) ->
-        stop = false
+
         setTimeout () ->
-            if not stop
-                stop = true
-                return mark_broken res, req.application, {stack : "Timeout", message: "Timeout"}
+            unless stoppedStartings[req.application.id]?
+                return mark_broken res, req.application,
+                    stack: "Installation timeout",
+                    message: "Installation timeout"
+
+            delete stoppedStartings[req.application.id]
+            delete startedApplications[req.application.id]
         , 45000
-        manager = new AppManager
-        manager.start req.application, (err, result) ->
-            return mark_broken res, req.application, err if err
-            if not stop
-                stop = true
-                req.application.state = "installed"
-                req.application.port = result.drone.port
-                req.application.save (err) ->
-                    return send_error res, err if err
-
-                    manager.resetProxy (err) ->
-                        return mark_broken res, req.application, err if err
-
-                        res.send
-                            success: true
-                            msg: 'Application running'
-                            app: req.application
+
+
+        unless startedApplications[req.application.id]?
+            startedApplications[req.application.id] = true
+
+            manager = new AppManager
+            manager.start req.application, (err, result) ->
+                return mark_broken res, req.application, err if err
+
+                unless stoppedStartings[req.application.id]?
+                    stoppedStartings[req.application.id] = true
+                    req.application.state = "installed"
+                    req.application.port = result.drone.port
+                    req.application.save (err) ->
+                        return send_error res, err if err
+
+                        manager.resetProxy (err) ->
+                            return mark_broken res, req.application, err if err
+
+                            delete startedApplications[req.application.id]
+                            res.send
+                                success: true
+                                msg: 'Application running'
+                                app: req.application
+
+                # Else it means the starting never ends. So, it does nothing
+                # until the timeout is fired.
+        else
+            res.send
+                error: true
+                msg: 'Application is already starting'
+                app: req.application

     stop: (req, res, next) ->


Remove @loadTemplates

Remove @loadTemplates

--- BackofficeBundle/Resources/public/coffee/AdminFormView.coffee
+++ BackofficeBundle/Resources/public/coffee/AdminFormView.coffee
@@ -10,9 +10,7 @@
     ])
     @method = if @options.method then @options.method else 'GET'
     @events = @events || {}
-    @loadTemplates [
-        'OpenOrchestraBackofficeBundle:BackOffice:Underscore/deleteButton'
-    ]
+    @doRender()
     return

   render: ->


Fix Date at Material Graph

Fix Date at Material Graph

--- server/app/assets/javascript/material.coffee
+++ server/app/assets/javascript/material.coffee
@@ -34,4 +34,4 @@
   develop = { data: transElem(data, 'develop'), label: '開発資材', yaxis: 2 }
   [fuel, ammo, steel, bauxite, instant, bucket, develop]

-transElem = (data, elem) -> data.map (x) -> [x['created']/1000, x[elem]]
+transElem = (data, elem) -> data.map (x) -> [x['created'], x[elem]]


Optimize fetching

Optimize fetching


Use a node pool for autocomplete suggestions

--- lib/suggestion-list-element.coffee
+++ lib/suggestion-list-element.coffee
@@ -39,12 +39,14 @@
 class SuggestionListElement extends HTMLElement
   maxItems: 200
   emptySnippetGroupRegex: /(\$\{\d+\:\})|(\$\{\d+\})|(\$\d+)/ig
+  nodePool: null

   createdCallback: ->
     @subscriptions = new CompositeDisposable
     @classList.add('popover-list', 'select-list', 'autocomplete-suggestion-list')
     @registerMouseHandling()
     @snippetParser = new SnippetParser
+    @nodePool = []

   attachedCallback: ->
     # TODO: Fix overlay decorator to in atom to apply class attribute correctly, then move this to overlay creation point.
@@ -104,7 +106,11 @@
     else
       @descriptionContainer.style.display = 'none'

-  itemsChanged: -> @render()
+  itemsChanged: ->
+    if @model?.items?.length
+      @render()
+    else
+      @returnItemsToPool(0)

   render: ->
     @selectedIndex = 0
@@ -175,8 +181,14 @@
       if descLength > longestDesc
         longestDesc = descLength
         longestDescIndex = index
-    li.remove() while li = @ol.childNodes[items.length]
     @updateDescription(items[longestDescIndex])
+    @returnItemsToPool(items.length)
+
+  returnItemsToPool: (pivotIndex) ->
+    while li = @ol.childNodes[pivotIndex]
+      li.remove()
+      @nodePool.push(li)
+    return

   descriptionLength: (item) ->
     count = 0
@@ -227,8 +239,11 @@
   renderItem: ({iconHTML, type, snippet, text, displayText, className, replacementPrefix, leftLabel, leftLabelHTML, rightLabel, rightLabelHTML}, index) ->
     li = @ol.childNodes[index]
     unless li
-      li = document.createElement('li')
-      li.innerHTML = ItemTemplate
+      if @nodePool.length > 0
+        li = @nodePool.pop()
+      else
+        li = document.createElement('li')
+        li.innerHTML = ItemTemplate
       li.dataset.index = index
       @ol.appendChild(li)


default base path to `.`

default base path to `.`

--- lib/ewg/generator.coffee
+++ lib/ewg/generator.coffee
@@ -6,7 +6,7 @@
 util     = require 'util'

 class Generator
-  constructor: (@name, configPath, @gulp, @basePath = '') ->
+  constructor: (@name, configPath, @gulp, @basePath = '.') ->
     @config = new Config(configPath, @reGenerate).config
     @watch  = @gulp.watch


Showing changed files in tree view after startup.

--- lib/hg-repository.coffee
+++ lib/hg-repository.coffee
@@ -144,6 +144,9 @@

   # Slash win32 path
   slashPath: (path) ->
+    if path.indexOf('..') is 0
+      path = path.replace('..', '')
+
     return path unless path
     if process.platform is 'win32'
       return path.replace(/\\/g, '/')
@@ -244,7 +247,7 @@
   #
   # Returns a {Boolean}.
   # isPathIgnored: (path) -> @isStatusIgnored(@getPathStatus(path))
-  isPathIgnored: (path) -> @cachedIgnoreStatuses.indexOf(@slashPath(path)) != -1
+  isPathIgnored: (path) -> false #@cachedIgnoreStatuses.indexOf(@slashPath(path)) != -1

   # Public: Get the status of a directory in the repository's working directory.
   #


Add getMenu method

Add getMenu method

--- src/browser/auto-update-manager.coffee
+++ src/browser/auto-update-manager.coffee
@@ -3,31 +3,30 @@

 module.exports =
 class AutoUpdateManager
-  constructor: (@applicationMenu) ->
-
+  constructor: ->
     # Only released versions should check for updates.
     return if /\w{7}/.test(@getVersion())

     autoUpdater.setFeedUrl "https://atom.io/api/updates?version=#{@getVersion()}"

     autoUpdater.on 'checking-for-update', =>
-      @applicationMenu.showDownloadingUpdateItem(false)
-      @applicationMenu.showInstallUpdateItem(false)
-      @applicationMenu.showCheckForUpdateItem(false)
+      @getMenu().showDownloadingUpdateItem(false)
+      @getMenu().showInstallUpdateItem(false)
+      @getMenu().showCheckForUpdateItem(false)

     autoUpdater.on 'update-not-available', =>
-      @applicationMenu.showCheckForUpdateItem(true)
+      @getMenu().showCheckForUpdateItem(true)

     autoUpdater.on 'update-available', =>
-      @applicationMenu.showDownloadingUpdateItem(true)
+      @getMenu().showDownloadingUpdateItem(true)

     autoUpdater.on 'update-downloaded', (event, releaseNotes, releaseVersion, releaseDate, releaseURL) =>
       for atomWindow in @getWindows()
         atomWindow.sendCommand('window:update-available', [releaseVersion, releaseNotes])
-      @applicationMenu.showInstallUpdateItem(true)
+      @getMenu().showInstallUpdateItem(true)

     autoUpdater.on 'error', (event, message) =>
-      @applicationMenu.showCheckForUpdateItem(true)
+      @getMenu().showCheckForUpdateItem(true)

     # Check for update after Atom has fully started and the menus are created
     setTimeout((-> autoUpdater.checkForUpdates()), 5000)
@@ -48,6 +47,9 @@
     autoUpdater.removeListener 'update-not-available', @onUpdateNotAvailable
     dialog.showMessageBox type: 'warning', buttons: ['OK'], message: 'There was an error checking for updates.', detail: message

+  getMenu: ->
+    global.atomApplication.applicationMenu
+
   getVersion: ->
     global.atomApplication.version


Show two controls abreast on 800px wide displays

--- lib/web/scripts/ControlView.coffee
+++ lib/web/scripts/ControlView.coffee
@@ -4,7 +4,7 @@

 module.exports = class ControlView extends Backbone.View
   tagName: 'li'
-  className: 'col-md-6'
+  className: 'col-sm-6'

   initialize: ->
     bodyViewClass = controlBodyViews[@model.control.get('type')]


remove unused isEqual

remove unused isEqual

--- shared/src/components/notifications/bar.cjsx
+++ shared/src/components/notifications/bar.cjsx
@@ -1,6 +1,5 @@
 React = require 'react'
 isEmpty = require 'lodash/isEmpty'
-isEqual = require 'lodash/isEqual'
 partial = require 'lodash/partial'
 without = require 'lodash/without'
 classnames = require 'classnames'


Fix setting of categories to product

Fix setting of categories to product

- Save 1 request (fetch categories again only if category create has
been executed)
- Improve logged messages

--- src/coffee/import/productimport.coffee
+++ src/coffee/import/productimport.coffee
@@ -77,20 +77,24 @@
         manufacturers = @_buildManufacturers(manufacturersXML, @productType) if manufacturersXML
         @_updateProductType(@productType, manufacturers) if manufacturers
     .then (productTypeUpdateResult) =>
+      @logger.info '[Categories] Categories XML import started...'
+      @logger.info "[Categories] Fetched categories count before create: '#{_.size @fetchedCategories}'"
       @categories = @_buildCategories(@categoriesXML) if @categoriesXML
-      creates = @_buildCategoryCreates(@categories, @fetchedCategories) if @categories
-      @_batch(_.map(creates, (c) => @_createCategory c), 100) if creates
+      @categoryCreates = @_buildCategoryCreates(@categories, @fetchedCategories) if @categories
+      @_batch(_.map(@categoryCreates, (c) => @_createCategory c), 100) if @categoryCreates
     .then (createCategoriesResult) =>
-      # fetch created categories to get id's used for parent reference creation
-      @_fetchCategories()
+      # fetch created categories to get id's used for parent reference creation. Required only if new categories created.
+      @_fetchCategories() if @categoryCreates
     .then (fetchedCategories) =>
-      @fetchedCategories = @_transformByCategoryExternalId fetchedCategories.result
-      updates = @_buildCategoryUpdates(@categories, @fetchedCategories) if @categories
-      @_batch(_.map(updates, (c) => @_updateCategory c), 100) if updates
+      @fetchedCategories = @_transformByCategoryExternalId fetchedCategories.results if fetchedCategories
+      @logger.info "[Categories] Fetched count after create: '#{_.size @fetchedCategories}'" if fetchedCategories
+      categoryUpdates = @_buildCategoryUpdates(@categories, @fetchedCategories) if @categories
+      @_batch(_.map(categoryUpdates, (c) => @_updateCategory c), 100) if categoryUpdates
     .then (updateCategoriesResult) =>
-      @logger.info '[Products] Products import started...'
+      @logger.info '[Products] Products XML import started...'
+      @logger.info "[Products] Import products found: '#{_.size @productsXML.Products?.Product}'"
       products = @_buildProducts(@productsXML, @productType, @fetchedCategories)
-      @logger.info "[Products] About to create '#{_.size products}' products."
+      @logger.info "[Products] Create count: '#{_.size products}'"
       @_batch(_.map(products, (p) => @_createProduct p), 100) if products
     .fail (error) =>
       @logger.error "Error on execute method; #{error}"
@@ -120,7 +124,7 @@
     utils.xmlToJson(path) if path

   _buildManufacturers: (data, productType) ->
-    @logger.info '[Manufacturers] Manufacturers import started...'
+    @logger.info '[Manufacturers] Manufacturers XML import started...'
     @logger.debug "[Manufacturers] data:\n#{utils.pretty data}"

     if not @mapping.productMapping.ManufacturerId
@@ -129,9 +133,9 @@

     count = _.size(data.Manufacturers?.Manufacturer)
     if count
-      @logger.info "[Manufacturers] Manufacturers found: '#{count}'"
+      @logger.info "[Manufacturers] Import manufacturers found: '#{count}'"
     else
-      @logger.info '[Manufacturers] No manufacturers found or undefined. Please check manufacturers input XML.'
+      @logger.info '[Manufacturers] No manufacturers to import found or undefined. Please check manufacturers input XML.'
       return

     attributeName = @mapping.productMapping.ManufacturerId.to
@@ -166,13 +170,12 @@
       @logger.info "[Manufacturers] No update action for manufacturers attribute '#{attributeName}' required."

   _buildCategories: (data) ->
-    @logger.info '[Categories] Categories import started...'
     @logger.debug "[Categories] data:\n#{utils.pretty data}"
     count = _.size(data.Categories?.Category)
     if count
-      @logger.info "[Categories] Categories found: '#{count}'"
+      @logger.info "[Categories] Import categories found: '#{count}'"
     else
-      @logger.info '[Categories] No categories found or undefined. Please check manufacturers input XML.'
+      @logger.info '[Categories] No categories to import found or undefined. Please check categories input XML.'
       return
     categoriesData = data.Categories.Category
     # get root categories only
@@ -257,7 +260,7 @@
       @logger.info "[Categories] No category update required."
       null

-  _transformByCategoryExternalId: (fetchedCategories) =>
+  _transformByCategoryExternalId: (fetchedCategories) ->
     fetchedCats = {}
     _.each fetchedCategories, (el) ->
       externalId = el.slug.nl
@@ -406,7 +409,7 @@
         variants: []

       # assign categories
-      @_processCategories(product, p)
+      @_processCategories(product, p, fetchedCategories)

       variantBase =
         attributes: []
@@ -459,9 +462,9 @@

     variant

-  _processCategories: (product, data) ->
+  _processCategories: (product, data, fetchedCategories) ->
     catReferences = []
-    _.each data.Categories?.Category, (c) =>
+    _.each data.Categories[0]?.Category, (c) =>
       categoryId = c.CategoryId[0]
       existingCategory = @_getCategoryByExternalId(categoryId, fetchedCategories)
       id = existingCategory.id


Fix vars initialization

Fix vars initialization

--- lib/minimap-bookmarks.coffee
+++ lib/minimap-bookmarks.coffee
@@ -1,4 +1,4 @@
-[MinimapBookmarksBinding, CompositeDisposable, requirePackages] = null
+[MinimapBookmarksBinding, CompositeDisposable, requirePackages] = []

 module.exports =
   active: false


Remove explicit variable declaration as its done by cs anyhow.

--- src/coffee/producttypegenerator.coffee
+++ src/coffee/producttypegenerator.coffee
@@ -5,9 +5,7 @@
 Class for generating JSON product type representations from CSV files.
 ###
 class ProductTypeGenerator
-
-  _options = {}
-
+
   constructor: (options = {}) ->
     @_options = options


:bug: Remove call to deprecated method

:bug: Remove call to deprecated method

--- lib/minimap-selection.coffee
+++ lib/minimap-selection.coffee
@@ -37,4 +37,4 @@
     @active = false
     @views = {}

-    @subscription.off()
+    @subscription.dispose()


fix(inventory): fix failed int test

fix(inventory): fix failed int test

--- src/coffee/sync/utils/inventory.coffee
+++ src/coffee/sync/utils/inventory.coffee
@@ -49,18 +49,24 @@
   # diff - {Object} The result of diff from `jsondiffpatch`
   #
   # Returns {Array} The list of actions, or empty if there are none
-  actionsMapRestockableInDays: (diff) ->
+  actionsMapRestockableInDays: (diff, old_obj) ->
     actions = []
     if diff.restockableInDays
-      if _.isArray(diff.restockableInDays) and _.size(diff.restockableInDays) is 2
-        oldVal = diff.restockableInDays[0]
-        newVal = diff.restockableInDays[1]
-        diffVal = newVal - oldVal
-        if diffVal
-          a =
-            action: 'setRestockableInDays'
-            restockableInDays: newVal
-          actions.push a
+      if _.isArray(diff.restockableInDays)
+        size = _.size(diff.restockableInDays)
+        console.log size
+        a =
+          action: 'setRestockableInDays'
+        if size is 2
+          oldVal = diff.restockableInDays[0]
+          newVal = diff.restockableInDays[1]
+          diffVal = newVal - oldVal
+          if diffVal
+            a.restockableInDays = newVal
+        else if size is 1
+          a.restockableInDays = diff.restockableInDays[0]
+      # Delete case (size is 3) - we do not set any restockableInDays
+      actions.push a
     actions

   # Private: map inventory custom type and fields


Only show graph buttons if we're in CODAP

--- src/code/views/graph-view.coffee
+++ src/code/views/graph-view.coffee
@@ -10,7 +10,8 @@
 RelationFactory  = require "../models/relation-factory"

 SimulationStore  = require "../stores/simulation-store"
-AppSettingsStore  = require "../stores/app-settings-store"
+AppSettingsStore = require "../stores/app-settings-store"
+CodapStore       = require "../stores/codap-store"
 LinkColors       = require "../utils/link-colors"

 {div} = React.DOM
@@ -18,7 +19,7 @@
 module.exports = React.createClass

   displayName: 'LinkView'
-  mixins: [ GraphStore.mixin, SimulationStore.mixin, AppSettingsStore.mixin ]
+  mixins: [ GraphStore.mixin, SimulationStore.mixin, AppSettingsStore.mixin, CodapStore.mixin ]

   getDefaultProps: ->
     linkTarget: '.link-top'
@@ -268,9 +269,7 @@
             graphStore: @props.graphStore
             selectionManager: @props.selectionManager
             showMinigraph: @state.showingMinigraphs
-            # showGraphButton: @props.graphStore.codapStandaloneMode and not @state.diagramOnly
-            # for now, show graph button whenever we are in simulation mode
-            showGraphButton: not @state.diagramOnly
+            showGraphButton: @state.codapHasLoaded and not @state.diagramOnly
           })
       )
     )


Rename normal users to logged-in users, loading now ...

--- src/coffee/metric-updater.coffee
+++ src/coffee/metric-updater.coffee
@@ -1,13 +1,13 @@
 data =
   metrics:
     anon:
-      colour: 'orange', number: 'loading...', title: 'Anonymous Visitors'
+      colour: 'orange', number: '...', title: 'Anonymous Visitors'
     ,
     normal:
-      colour: 'blue', number: 'loading...', title: 'Normal Visitors'
+      colour: 'blue', number: '...', title: 'Logged-in Visitors'
     ,
     premium:
-      colour: 'green', number: 'loading...', title: 'Premium Visitors'
+      colour: 'green', number: '...', title: 'Premium Visitors'

 source = $('#metric-block-template').html()
 template = Handlebars.compile source


Adds saveTeamMedium

Adds saveTeamMedium

--- src/collections/teamMedia.coffee
+++ src/collections/teamMedia.coffee
@@ -42,6 +42,26 @@
   @deleteItem teamMedium, callback

+exports.saveTeamMedium = (teamMedium, callback) ->
+  unless teamMedium
+    throw new TSArgsError 'teamsnap.saveTeamMedium', "`teamMedium` must be
+    provided"
+  unless @isItem teamMedium, 'teamMedium'
+    throw new TSArgsError 'teamsnap.saveTeamMedium', "`type` must be
+      'teamMedium'"
+  unless @isId teamMedium.teamId
+    throw new TSArgsError 'teamsnap.saveTeamMedium', 'must include
+      `teamId`'
+  unless @isId teamMedium.memberId
+    throw new TSArgsError 'teamsnap.saveTeamMedium', 'must include
+      `memberId`'
+  unless @isId teamMedium.teamMediaGroupId
+    throw new TSArgsError 'teamsnap.saveTeamMedium', 'must include
+      `teamMediaGroupId`'
+
+  @saveItem teamMedium, callback
+
+
 exports.saveTeamVideoLink = (teamMedium, callback) ->
   unless teamMedium
     throw new TSArgsError 'teamsnap.createVideoLink', "`teamMedium` must be


Rename inviews

Rename inviews

--- source/assets/javascripts/app.js.coffee
+++ source/assets/javascripts/app.js.coffee
@@ -393,7 +393,7 @@
   stylesActive = ->
     $('a.active').removeClass 'active'
     $('a.styles').addClass 'active'
-  details = new Waypoint.Inview {
+  detailsIn = new Waypoint.Inview {
     element: $('#details')[0],
     enter: (direction) ->
       if direction == 'down'
@@ -403,7 +403,7 @@
       if direction == 'up'
         glyphsActive()
   }
-  glyphs = new Waypoint.Inview {
+  glyphsIn = new Waypoint.Inview {
     element: $('#glyphs')[0],
     exited: (direction) ->
       if direction == 'up'
@@ -413,7 +413,7 @@
       glyphsActive()

   }
-  styles = new Waypoint.Inview {
+  stylesIn = new Waypoint.Inview {
     element: $('#styles')[0],
     enter: (direction) ->
       stylesActive()


Fix #8.

Fix #8.

--- lib/linter-pylama.coffee
+++ lib/linter-pylama.coffee
@@ -94,7 +94,16 @@
     pylamaPath = atom.config.get 'linter-pylama.executablePath'

     if pylamaVersion is 'external' and pylamaPath isnt @pylamaPath
-      if not do fs.statSync(pylamaPath).isFile
+      if /^(pylama|pylama\.exe)$/.test pylamaPath
+        process.env.PATH.split(path.delimiter).forEach (dir) =>
+          tmp = path.join dir, pylamaPath
+          if fs.existsSync tmp
+            pylamaPath = tmp
+
+      if not path.isAbsolute pylamaPath
+        pylamaPath = path.resolve pylamaPath
+
+      if not fs.existsSync pylamaPath or not do fs.statSync(pylamaPath).isFile
         atom.notifications.addError 'Pylama executable not found',
         detail: "[linter-pylama] `#{pylamaPath}` executable file not found. \
         Please set the correct path to `pylama`."


test for empty inner arrays and preserving inner arrays

--- test/lib/test.coffee
+++ test/lib/test.coffee
@@ -10,6 +10,12 @@

     input  = [ 1, '2', {three:'3'}, new Date(2017, 3, 1) ]
     answer = [ 1, '2', {three:'3'}, new Date(2017, 3, 1) ]
+    assert.deepEqual flatten(input), answer
+
+  it 'with empty inner arrays', ->
+
+    input  = [ 1, '2', [], 3, [[]], 4, [ 5, [], 6] ]
+    answer = [ 1, '2', 3, 4, 5, 6 ]
     assert.deepEqual flatten(input), answer

   it 'with level=1 sub arrays', ->
@@ -29,3 +35,18 @@
     input  = [ 1, [ 2 ], 3, [ 4, [ 5, [ 6 ] ], 7 ], 8 ]
     answer = [ 1, 2, 3, 4, 5, 6, 7, 8 ]
     assert.deepEqual flatten(input), answer
+
+  it 'doesnt change inner arrays', ->
+
+    a1 = [ 2 ]
+    a4 = [ 6 ]
+    a3 = [ 5, a4 ]
+    a2 = [ 4, a3, 7 ]
+    input = [ 1, a1, 3, a2, 8 ]
+    answer = [ 1, 2, 3, 4, 5, 6, 7, 8 ]
+    assert.deepEqual flatten(input), answer
+    # ensure the inner arrays weren't altered
+    assert.deepEqual a1, [ 2 ]
+    assert.deepEqual a2, [ 4, [ 5, [ 6 ] ], 7 ]
+    assert.deepEqual a3, [ 5, [ 6 ] ]
+    assert.deepEqual a4, [ 6 ]


not using

not using

--- public/script/draggable.coffee
+++ public/script/draggable.coffee
@@ -1,2 +0,0 @@
-# this is a comment
-alert 'blammo!'


Indentation fix.

Indentation fix.

--- test/formatting.coffee
+++ test/formatting.coffee
@@ -123,17 +123,17 @@
   eq -1, js.indexOf ';;'

 test "#1195 Ignore trailing semicolons (before newlines or as the last char in a program)", ->
-    preNewline = (numSemicolons) ->
-      """
-      nonce = {}; nonce2 = {}
-      f = -> nonce#{Array(numSemicolons+1).join(';')}
-      nonce2
-      unless f() is nonce then throw new Error('; before linebreak should = newline')
-      """
-    CoffeeScript.run(preNewline(n), bare: true) for n in [1,2,3]
+  preNewline = (numSemicolons) ->
+    """
+    nonce = {}; nonce2 = {}
+    f = -> nonce#{Array(numSemicolons+1).join(';')}
+    nonce2
+    unless f() is nonce then throw new Error('; before linebreak should = newline')
+    """
+  CoffeeScript.run(preNewline(n), bare: true) for n in [1,2,3]

-    lastChar = '-> lastChar;'
-    doesNotThrow -> CoffeeScript.compile lastChar, bare: true
+  lastChar = '-> lastChar;'
+  doesNotThrow -> CoffeeScript.compile lastChar, bare: true

 test "#1299: Disallow token misnesting", ->
   try


Add some documentation for J.Model

Add some documentation for J.Model


* fixed testing on windows

* fixed testing on windows

--- test/index-test.coffee
+++ test/index-test.coffee
@@ -14,6 +14,7 @@
 require 'task-registry-template-engine-lodash'

 fs.cwd = process.cwd
+fs.path = require 'path.js'
 Resource.setFileSystem fs

 describe 'TemplateFileTask', ->


show tabs when 'no assignments'

show tabs when 'no assignments'

--- src/components/scores/index.cjsx
+++ src/components/scores/index.cjsx
@@ -254,6 +254,11 @@
     else

         No Assignments Yet
+        <CoursePeriodsNavShell
+          handleSelect={@selectPeriod}
+          handleKeyUpdate={@setPeriodIndex}
+          intialActive={period_id}
+          courseId={courseId} />


temporarily disable abort test for slimerjs

--- tests/suites/casper/request.coffee
+++ tests/suites/casper/request.coffee
@@ -4,6 +4,10 @@

 if utils.ltVersion(phantom.version, '1.9.0')
   casper.test.skip(6, 'PhantomJS version <1.9.0 does not implement request.abort()')
+  casper.test.done()
+# FIXME: abort test does not work for slimerjs, either -- disable
+else if true
+  casper.test.skip(6, 'request.abort() test is broken for slimerjs')
   casper.test.done()
 else
   SERVER = 'http://localhost:54321/'


Add missing auctions sitemap reference (#7252)

--- src/desktop/apps/sitemaps/index.coffee
+++ src/desktop/apps/sitemaps/index.coffee
@@ -19,6 +19,7 @@
   '/sitemap-artists.xml',
   '/sitemap-artworks-:timestamp.xml',
   '/sitemap-artworks.xml',
+  '/sitemap-auctions.xml',
   '/sitemap-cities.xml',
   '/sitemap-collect.xml',
   '/sitemap-fairs-:timestamp.xml',


resolve test for encodeuricomponent

resolve test for encodeuricomponent

--- test/route_test.coffee
+++ test/route_test.coffee
@@ -64,7 +64,9 @@

         it "Then I should get redirected to login", ->
             @response.statusCode.should.equal 200
-            @response.request.path.should.equal "/login?next=/apps/myapp/"
+            uri = "/login?next="
+            params = "/apps/myapp/"
+            @response.request.path.should.equal uri + encodeURIComponent(params)

         it "When I send non-identified request to an existing
 private route (with params)", (done) ->
@@ -74,7 +76,9 @@

         it "Then I should get redirected to login", ->
             @response.statusCode.should.equal 200
-            @response.request.path.should.equal "/login?next=/apps/myapp/?param=a"
+            uri = "/login?next="
+            params = "/apps/myapp/?param=a"
+            @response.request.path.should.equal uri + encodeURIComponent(params)

     describe "Public proxying", ->


Add a setStandAlone method on minimap and dispatch a dedicated event on change

--- lib/minimap.coffee
+++ lib/minimap.coffee
@@ -131,6 +131,16 @@
   onDidChangeScrollLeft: (callback) ->
     @emitter.on 'did-change-scroll-left', callback

+  # Calls the `callback` when the text editor stand-alone mode is modified
+  #
+  # callback - The callback {Function}. The event the callback will receive
+  #            the {Minimap} as the sole argument.
+  #
+  # Returns a `Disposable`.
+  onDidChangeStandAlone: (callback) ->
+    @emitter.on 'did-change-stand-alone', callback
+
+
   # Calls the `callback` when this {Minimap} was destroyed.
   #
   # callback - The callback {Function}.
@@ -146,6 +156,15 @@
   #
   # Returns a {Boolean}.
   isStandAlone: -> @standAlone
+
+  # Sets the stand-alone mode for this minimap.
+  #
+  # standAlone - A {Boolean} of whether the minimap operates in stand-alone
+  #              mode or not.
+  setStandAlone: (standAlone) ->
+    if standAlone isnt @standAlone
+      @standAlone = standAlone
+      @emitter.emit('did-change-stand-alone', this)

   # Returns the `TextEditor` that this minimap represents.
   #


:lipstick: Whitespace

:lipstick: Whitespace

--- lib/minimap.coffee
+++ lib/minimap.coffee
@@ -22,6 +22,7 @@
       @emitter.emit('did-change-scroll-top', scrollTop)

   onDidChange: (callback) -> @emitter.on 'did-change', callback
+
   onDidChangeScrollTop: (callback) ->
     @emitter.on 'did-change-scroll-top', callback


use @all() instead of calling @each, which is faster

--- js/u.coffee
+++ js/u.coffee
@@ -100,12 +100,15 @@
       https://developer.mozilla.org/en-US/docs/DOM/element.classList
       ###
       addClass: (cls) ->
+        els = @all()
         if typeof cls is "object"
-          return @each (i, el) ->
+          for el in els
             for c in cls
               el.classList.add(c)
         else
-          return @each (i, el) -> el.classList.add(cls)
+          for el in els
+            el.classList.add(cls)
+        return this

       toggleClass: (cls) ->
         if typeof cls is "object"


fixed comments in 'connect'

fixed comments in 'connect'

--- lib/orpheus.coffee
+++ lib/orpheus.coffee
@@ -83,12 +83,11 @@
 			if err then callback(err, results = [])
 			else
 				# The response
-				resp = {}
-				# Go over the schema
-				for key, num of schema
-					resp[key] = results.splice(0, num)
+				response = {}
+				# Go over the schema and convert it a a response object
+				response[key] = results.splice(0, num) for key, num of schema
 				# Call the callback, with the error and the parsed results
-				callback(err, resp)
+				callback(err, response)

 	# Orpheus model extends the model


Check for public_id

Check for public_id

--- client/functions.coffee
+++ client/functions.coffee
@@ -2,7 +2,8 @@
 	collection: new Mongo.Collection "_cloudinary", connection:null
 	_helpers:
 		"url": (public_id,options) ->
-			$.cloudinary.url(public_id,options.hash)
+			if public_id and not _.isEmpty public_id
+				$.cloudinary.url(public_id,options.hash)

 	delete: (public_id, callback) ->
 		Meteor.call "c.delete_by_public_id", public_id, (error,result) ->


Patch region override

Patch region override

--- client/functions.coffee
+++ client/functions.coffee
@@ -129,6 +129,7 @@
 		file_size:file.size
 		acl:ops.acl
 		bucket:ops.bucket
+		region:ops.region
 		expiration:ops.expiration
 		(error,result) ->
 			if result


fixing bug missing callback on no work

fixing bug missing callback on no work

--- src/highlights.coffee
+++ src/highlights.coffee
@@ -140,7 +140,10 @@
     fs.readdir(dir, (err, files)=>
       if err
         return cb(err)
+
       todo = files.length
+      if !todo
+        return cb(false,[])

       while files.length
         file = files.shift()


fix property name completion of font & refactoring

--- lib/styleProvider.coffee
+++ lib/styleProvider.coffee
@@ -36,7 +36,7 @@
       completions = @getPropertyNameCompletions(request)

     # for Selector
-    if @isCompletingClassName(request)
+    else if @isCompletingClassName(request)
       # find class names from view(xml)
       # filter using request.prefix
       completions = []
@@ -72,8 +72,8 @@
         completions = completions.concat(tagCompletions)

     # console.log completions
-    completions
     completions?.sort util.completionSortFun
+    completions

   onDidInsertSuggestion: ({editor, triggerPosition, suggestion}) ->
     suggestion.onDidInsertSuggestion and suggestion.onDidInsertSuggestion({editor, triggerPosition, suggestion})
@@ -107,7 +107,10 @@
     previousScopes = editor.scopeDescriptorForBufferPosition(previousBufferPosition)
     previousScopesArray = previousScopes.getScopesArray()

-    (hasScope(scopes, 'meta.property-value.css.tss') and not hasScope(scopes, 'punctuation.terminator.rule.css.tss'))
+    lastValueScopeIndex = _.lastIndexOf(scopes,'meta.property-value.css.tss')
+    lastListScopeIndex = _.lastIndexOf(scopes,'meta.property-list.css.tss')
+
+    (hasScope(scopes, 'meta.property-value.css.tss') and not hasScope(scopes, 'punctuation.terminator.rule.css.tss')) and lastListScopeIndex < lastValueScopeIndex

   isCompletingName: ({scopeDescriptor, bufferPosition, prefix, editor}) ->
     scopes = scopeDescriptor.getScopesArray()
@@ -199,11 +202,16 @@
     {row} = bufferPosition
     while row >= 0
       line = editor.lineTextForBufferRow(row)
-      propertyName = objectNameWithColonPattern.exec(line)?[1]
+      regexResult = objectNameWithColonPattern.exec(line)
+      propertyName = regexResult?[1]
+
+      parentNameIndex = regexResult?.index || -1;
+      console.log parentNameIndex, line.lastIndexOf('}')
+      return if parentNameIndex <  line.lastIndexOf('}')
       return propertyName if propertyName
       row--
     return
-
+
   getPreviousPropertyName: (bufferPosition, editor) ->
     {row} = bufferPosition
     while row >= 0
@@ -216,17 +224,11 @@
   getPropertyValueCompletions: (request) ->
     {bufferPosition, editor, prefix, scopeDescriptor} = request
     property = @getPreviousPropertyName(bufferPosition, editor)
-
-    return null unless @properties[property]
+    parentPropertyName = @getParentObjectName(bufferPosition, editor)
+
+    return null unless @properties[property] #and @properties[parentPropertyName]

     values = @properties[property].values
-
-    if @types[@properties[property].type] and !values?.length # such as FONT
-      candidateProperties = {};
-      _.each @types[@properties[property].type].properties, (item)->
-        candidateProperties[item] = {}
-      return this.getPropertyNameCompletions(request, candidateProperties)
-

     return null unless values?

@@ -286,7 +288,7 @@
     propertyNamePrefixPattern.exec(line)?[0]

-  getPropertyNameCompletions: ({bufferPosition, editor, scopeDescriptor, activatedManually}, candidateProperties) ->
+  getPropertyNameCompletions: ({bufferPosition, editor, scopeDescriptor, activatedManually}) ->
     # Don't autocomplete property names in SASS on root level
     scopes = scopeDescriptor.getScopesArray()
     line = editor.getTextInRange([[bufferPosition.row, 0], bufferPosition])
@@ -294,9 +296,16 @@

     prefix = @getPropertyNamePrefix(bufferPosition, editor)
     return null unless activatedManually or prefix
-
+
+    parentObjName = @getParentObjectName(bufferPosition, editor)
+
+    innerProperties = {}
+    if @properties[parentObjName]?.type && @types[@properties[parentObjName]?.type]?.properties.length
+      _.each @types[@properties[parentObjName]?.type].properties, (innerKey) ->
+        innerProperties[innerKey] = {}
+
     completions = []
-    candidateProperties = candidateProperties || @properties
+    candidateProperties = if _.isEmpty(innerProperties) then @properties else innerProperties
     for property, options of candidateProperties when not prefix or firstCharsEqual(property, prefix)
       jsObjectTypes = ['Font']
       if jsObjectTypes.indexOf(@properties[property].type) > -1


:bug: Fix real gist url.

:bug: Fix real gist url.

--- lib/sync-settings.coffee
+++ lib/sync-settings.coffee
@@ -65,7 +65,7 @@
           message = 'Gist ID Not Found' if message == 'Not Found'
           atom.notifications.addError "sync-settings: Error uploading your settings. ("+message+")"
       else
-          atom.notifications.addSuccess "sync-settings: Your settings were successfully uploaded.
Click here to open your Gist."
+          atom.notifications.addSuccess "sync-settings: Your settings were successfully uploaded.
Click here to open your Gist."
       cb?(err, res)

   getPackages: ->


Add todo for controllers.

Add todo for controllers.

--- express/index.coffee
+++ express/index.coffee
@@ -100,6 +100,8 @@

 ###
     Actions
+    TODO: put some controllers, which are called intp the index.coffee and register the routes.
+    These controllers should also call model when accessing to mongodbd.
 ###
 app.all(/^\/admin.*$/, backbone.index)
 app.post '/collector/collect', loginMiddleware, collector.collect


fix clientside receiving text updates

fix clientside receiving text updates

--- src/coffee/client/text_field_handler.coffee
+++ src/coffee/client/text_field_handler.coffee
@@ -64,9 +64,9 @@
             selection = @selection
         else if @baseText == @text
             # TODO OT the selection over the op
-            selection = null
+            selection = []
         else
-            selection = null
+            selection = []

         @setContents modelTextNew
         @setSelection selection


More robust memory state.

More robust memory state.

--- lib/MemoryState.coffee
+++ lib/MemoryState.coffee
@@ -305,7 +305,7 @@
     sockets = @socketsToRooms.keys()
     for id in sockets
       socketsset = @socketsToRooms.get id
-      result[id] = socketsset.toArray()
+      result[id] = socketsset?.toArray() || []
     Promise.resolve result

   # @private
@@ -324,7 +324,7 @@
   removeSocketFromRoom : (id, roomName) ->
     roomsset = @socketsToRooms.get id
     socketsset = @roomsToSockets.get roomName
-    roomsset.delete roomName
+    roomsset?.delete roomName
     socketsset?.delete id
     njoined = socketsset?.length || 0
     Promise.resolve njoined
@@ -333,19 +333,20 @@
   removeAllSocketsFromRoom : (roomName) ->
     sockets = @socketsToRooms.keys()
     socketsset = @roomsToSockets.get roomName
-    removedSockets = socketsset.toArray()
+    removedSockets = socketsset?.toArray() || []
     for id in removedSockets
       roomsset = @socketsToRooms.get id
       roomsset.delete roomName
-    socketsset = socketsset.difference sockets
-    @roomsToSockets.set roomName, socketsset
+    if socketsset
+      socketsset = socketsset.difference sockets
+      @roomsToSockets.set roomName, socketsset
     Promise.resolve removedSockets

   # @private
   removeSocket : (id) ->
     rooms = @roomsToSockets.toArray()
     roomsset = @socketsToRooms.get id
-    removedRooms = roomsset.toArray()
+    removedRooms = roomsset?.toArray() || []
     joinedSockets = []
     for roomName, idx in removedRooms
       socketsset = @roomsToSockets.get roomName


lock改为--lock

lock改为--lock

--- honey-preview/index.coffee
+++ honey-preview/index.coffee
@@ -37,7 +37,7 @@
       return done null

     #如果参数中提供了lock，则写入锁定文件
-    if _.find(process.argv, (current)-> /^lock$/i.test current) then writeLockFile silky
+    if _.find(process.argv, (current)-> /^\-\-lock$/i.test current) then writeLockFile silky

     projectName = silky.config.name || pluginOptions.project_name || pluginOptions.projectName
     projectName = projectName || _path.basename(silky.options.workbench)
@@ -61,6 +61,7 @@

   file = _path.join silky.options.output, ".lock"
   _fs.writeJSONSync file, content
+  console.log "Project has already locked by #{_hostname}.".white

 #分析多个服务器
 analysisServer = (serverText)->


Update addBlacklist.coffee

Update addBlacklist.coffee

--- src/routes/addBlacklist.coffee
+++ src/routes/addBlacklist.coffee
@@ -9,7 +9,9 @@
         false

     # Create blacklist.list if not exists
-    fs.closeSync fs.openSync path, 'a'
+    fs.open path, "wx", (err, fd) ->
+        fs.close fd, (err) ->
+            console.log "Created a blank blacklist file"

     fs.readFile path, encoding: 'utf8', (error, data) ->
         if error


We cannot test %-y unless we upgrade moment.js to 2.11.1

--- test/javascripts/src/strftime_test.coffee
+++ test/javascripts/src/strftime_test.coffee
@@ -24,7 +24,6 @@
   "%-S": "s"
   "%w": "e"
   "%y": "YY"
-  "%-y": "Y"
   "%Y": "YYYY"

 testGroup "strftime", ->


Add comment heading to document ready

Add comment heading to document ready

--- source/assets/javascripts/application.coffee
+++ source/assets/javascripts/application.coffee
@@ -30,6 +30,10 @@
 #= require directives/slide
 #= require directives/ytVideo

+# -------------------------------------
+#   Document Ready
+# -------------------------------------
+
 jQuery ($) ->
   if window.location.hash is ''
     window.location = '/#/'


add a couple of lines of checking code

add a couple of lines of checking code

--- library/nucleus/arche.coffee
+++ library/nucleus/arche.coffee
@@ -98,11 +98,14 @@
         return if _.isArray this.$icpCts or null
         assert _.isArray this.$icpCts = currents
         msg = "Intercepting an %s event at the %s"
+        evt = "missing interceptor event specifier"
+        imp = "missing interceptor implementation"
+        internal = "missing the object EM prototype"
         _.each currents, (record, index, linear) =>
             {event, implement} = record or Object()
-            assert _.isString event or undefined
-            assert _.isFunction implement or null
-            assert _.isFunction try this.on or null
+            assert _.isString(event or null), evt
+            assert _.isFunction(try implement), imp
+            assert _.isFunction(this.on), internal
             logger.debug msg, event.underline, ids
             this._events ?= {} # event emitter bug
             do => @removeListener event, implement


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/engine_selector.coffee
+++ test/engine_selector.coffee
@@ -25,6 +25,6 @@
     x: 4
     y: 20

-  equals engine.first('type="testObj"').length, obj1
+  equals engine.first('type="testObj"').length, 1

 module()


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/engine_selector.coffee
+++ test/engine_selector.coffee
@@ -15,4 +15,6 @@
     x: 50
     y: 30

+
+
 module()


Remove obsolete file

Remove obsolete file

--- h2o-web/src/main/steam/tests/node.global.coffee
+++ h2o-web/src/main/steam/tests/node.global.coffee
@@ -1,3 +0,0 @@
-_ = require 'lodash'
-httpRequest = require 'request'
-test = require 'tape'


Show module name

Show module name

--- lib/wanigui.coffee
+++ lib/wanigui.coffee
@@ -34,8 +34,8 @@
   @params = []
   @module = module
   @instrument
-  profile = module.profile
-  @buildInstrumentInterface(module, opts) if profile.type is 'synth'
+  @profile = profile = module.profile
+  @attachToInstrument(module, profile, opts) if profile.type is 'synth'
   for name, param of profile.audioParams
     @attachToAudioParam module, name, param, @opts
   for name, param of profile.params
@@ -60,17 +60,20 @@
       @params.push( new guiModule.create(module,name,param,opts) )
       return

-Wanigui::buildInstrumentInterface = () ->
+Wanigui::attachToInstrument = (module, profile, opts) ->
   looks = @module.looks or []
   looks.push 'keyboard' #fallback ...is required? should ignore?
   for look in looks
     guiModule = Wanigui.modules[look]
     if guiModule
-      @instrument = new guiModule.create(@opts)
+      @instrument = new guiModule.create(module, @opts)
       return

 Wanigui::build = () ->
-  $box = $('<div />');
+  $box = $('<div class="wanigui-module" />');
+  $('<h2 />')
+    .text @profile.name
+    .appendTo $box
   $box.append @instrument.build() if @instrument
   for audioParam in @audioParams
     $box.append audioParam.build()


added a comment

added a comment

--- web/scripts/playerCodeEditor.coffee
+++ web/scripts/playerCodeEditor.coffee
@@ -42,6 +42,9 @@
         return

     buildNeededParsers: ->
+        ###
+            Builds the parsers needed by the scanText function.
+        ###
         for command of @commands
             @commands[command]['parser'] = {
                 'exec': @buildParser command


Only process when mouse is up.

Only process when mouse is up.

--- lib/auto-indent.coffee
+++ lib/auto-indent.coffee
@@ -108,6 +108,7 @@

   # Buffer has stopped changing. Indent as required
   didStopChanging: () ->
+    return unless @mouseUp
     return unless @autoJsx
     selectedRange = @editor.getSelectedBufferRange()
     highestRow = Math.max selectedRange.start.row, selectedRange.end.row


Fix reset button submitting form

Fix reset button submitting form

--- SingularityUI/app/views/formBaseView.coffee
+++ SingularityUI/app/views/formBaseView.coffee
@@ -15,7 +15,9 @@
     initialize: ->
         @checkForm = _.debounce @checkForm, 100

-    render: ->
+    render: (event) ->
+        event.preventDefault() if event
+
         @$el.html @template
             model: @model?.toJSON()


Fix exe.run notation

Fix exe.run notation

--- src/beautifiers/puppet-fix.coffee
+++ src/beautifiers/puppet-fix.coffee
@@ -29,7 +29,7 @@
   ]

   beautify: (text, language, options) ->
-    @exe("puppet-lint", [
+    @exe("puppet-lint").run([
       '--fix'
       tempFile = @tempFile("input", text)
       ], {


Remove unused file

Remove unused file

--- client/includes.coffee
+++ client/includes.coffee
@@ -747,7 +747,6 @@
   "stylus/app.group.creation.styl",
   "stylus/app.user.styl",
   "stylus/app.markdown.styl",
-  "stylus/app.vm.styl",
   "stylus/temp.styl",
   # "stylus/app.landing.styl",
   # "stylus/app.predefined.styl",


More fallbacks if mac fails

More fallbacks if mac fails

--- src/lib/docpad.coffee
+++ src/lib/docpad.coffee
@@ -1024,13 +1024,14 @@
 			@emitSync('welcome', {docpad}, complete)

 		# Anyomous
+		# Ignore errors
 		tasks.push (complete) =>
 			# No statistics or username is already identified
 			return complete()  if !mixpanelInstance or @userConfig.username

 			# User is anonymous, set their username to the hashed and salted mac address
 			require('getmac').getMac (err,macAddress) =>
-				return complete()  if err
+				return complete()  if err or !macAddress

 				# Hash with salt
 				try
@@ -1039,8 +1040,11 @@
 					return complete()  if err

 				# Apply
-				@userConfig.name ?= "MAC #{macAddressHash}"
-				@userConfig.username ?= macAddressHash
+				if macAddressHash
+					@userConfig.name ?= "MAC #{macAddressHash}"
+					@userConfig.username ?= macAddressHash
+
+				# Next
 				return complete()

 		# Track
@@ -1061,6 +1065,7 @@
 					$country_code: @getCountryCode()
 					languageCode: @getLanguageCode()
 				})
+				# Save the changes with these
 				@updateUserConfig({
 					identified: true
 				})


Made implementation classes internal to the FingerTreeType constructor.

--- lib/finger_tree.coffee
+++ lib/finger_tree.coffee
@@ -19,11 +19,10 @@

 class FingerTreeType
-  buildLeft:  -> Sequence.reduce arguments, @Empty, (s, a) -> s.before a
-  buildRight: -> Sequence.reduce arguments, @Empty, (s, a) -> s.after a
-
   constructor: (measure = SizeMeasure) ->
-    T = this
+    @buildLeft  = -> Sequence.reduce arguments, Empty, (s, a) -> s.before a
+    @buildRight = -> Sequence.reduce arguments, Empty, (s, a) -> s.after a
+
     norm = ->
       Sequence.reduce arguments, measure.empty, (n, x) ->
         if x?
@@ -37,84 +36,84 @@
           n

     # A node.
-    @Node2 = class
+    class Node2
       constructor: ->
         [@a, @b] = arguments
         @v = norm @a, @b

       reduceLeft:  (z, op) -> op(op(z, @a), @b)
       reduceRight: (op, z) -> op(@a, op(@b, z))
-      asDigit: -> new T.Digit2 @a, @b
+      asDigit: -> new Digit2 @a, @b
       measure: -> @v

-    @Node3 = class
+    class Node3
       constructor: ->
         [@a, @b, @c] = arguments
         @v = norm @a, @b, @c

       reduceLeft:  (z, op) -> op(op(op(z, @a), @b), @c)
       reduceRight: (op, z) -> op(@a, op(@b, op(@c, z)))
-      asDigit: -> new T.Digit3 @a, @b, @c
+      asDigit: -> new Digit3 @a, @b, @c
       measure: -> @v

     # A digit in a finger tree.
-    @Digit1 = class
+    class Digit1
       constructor: -> [@a] = arguments

       reduceLeft:  (z, op) -> op(z, @a)
       reduceRight: (op, z) -> op(@a, z)

-      after:  (x) -> new T.Digit2 x, @a
-      before: (x) -> new T.Digit2 @a, x
+      after:  (x) -> new Digit2 x, @a
+      before: (x) -> new Digit2 @a, x

       first: -> @a
       last:  -> @a

-      rest: -> T.Empty
-      init: -> T.Empty
+      rest: -> Empty
+      init: -> Empty

       measure: -> norm @a

-    @Digit2 = class
+    class Digit2
       constructor: -> [@a, @b] = arguments

       reduceLeft:  (z, op) -> op(op(z, @a), @b)
       reduceRight: (op, z) -> op(@a, op(@b, z))

-      after:  (x) -> new T.Digit3 x, @a, @b
-      before: (x) -> new T.Digit3 @a, @b, x
+      after:  (x) -> new Digit3 x, @a, @b
+      before: (x) -> new Digit3 @a, @b, x

       first: -> @a
       last:  -> @b

-      rest: -> new T.Digit1 @b
-      init: -> new T.Digit1 @a
-
-      asNode: -> new T.Node2 @a, @b
+      rest: -> new Digit1 @b
+      init: -> new Digit1 @a
+
+      asNode: -> new Node2 @a, @b

       measure: -> norm @a, @b

-    @Digit3 = class
+    class Digit3
       constructor: -> [@a, @b, @c] = arguments

       reduceLeft:  (z, op) -> op(op(op(z, @a), @b), @c)
       reduceRight: (op, z) -> op(@a, op(@b, op(@c, z)))

-      after:  (x) -> new T.Digit4 x, @a, @b, @c
-      before: (x) -> new T.Digit4 @a, @b, @c, x
+      after:  (x) -> new Digit4 x, @a, @b, @c
+      before: (x) -> new Digit4 @a, @b, @c, x

       first: -> @a
       last:  -> @c

-      rest: -> new T.Digit2 @b, @c
-      init: -> new T.Digit2 @a, @b
-
-      asNode: -> new T.Node3 @a, @b, @c
+      rest: -> new Digit2 @b, @c
+      init: -> new Digit2 @a, @b
+
+      asNode: -> new Node3 @a, @b, @c

       measure: -> norm @a, @b, @c

-    @Digit4 = class
+    class Digit4
       constructor: -> [@a, @b, @c, @d] = arguments

       reduceLeft:  (z, op) -> op(op(op(op(z, @a), @b), @c), @d)
@@ -123,21 +122,21 @@
       first: -> @a
       last:  -> @d

-      rest: -> new T.Digit3 @b, @c, @d
-      init: -> new T.Digit3 @a, @b, @c
+      rest: -> new Digit3 @b, @c, @d
+      init: -> new Digit3 @a, @b, @c

       measure: -> norm @a, @b, @c, @d

     # An empty finger tree.
-    @Empty = {
+    Empty = {
       isEmpty: -> true

       reduceLeft:  (z, op) -> z
       reduceRight: (op, z) -> z

-      after:  (a) -> new T.Single a
-      before: (a) -> new T.Single a
+      after:  (a) -> new Single a
+      before: (a) -> new Single a

       first: ->
       last:  ->
@@ -152,7 +151,7 @@

     # A finger tree with a single element.
-    @Single = class
+    class Single
       constructor: (a) -> @a = a

       isEmpty: -> false
@@ -160,14 +159,14 @@
       reduceLeft:  (z, op) -> op z, @a
       reduceRight: (op, z) -> op @a, z

-      after:  (x) -> new T.Deep new T.Digit1(x), (-> T.Empty), new T.Digit1(@a)
-      before: (x) -> new T.Deep new T.Digit1(@a), (-> T.Empty), new T.Digit1(x)
+      after:  (x) -> new Deep new Digit1(x), (-> Empty), new Digit1(@a)
+      before: (x) -> new Deep new Digit1(@a), (-> Empty), new Digit1(x)

       first: -> @a
       last:  -> @a

-      rest: -> T.Empty
-      init: -> T.Empty
+      rest: -> Empty
+      init: -> Empty

       concat: (t) -> t.after @a

@@ -175,11 +174,11 @@

     # A deep finger tree.
-    @Deep = class
+    class Deep
       reduceLeft  = (op) -> (z, x) -> x.reduceLeft(z, op)
       reduceRight = (op) -> (x, z) -> x.reduceRight(op, z)

-      asTree = (s) -> s.reduceLeft T.Empty, (a, b) -> a.before b
+      asTree = (s) -> s.reduceLeft Empty, (a, b) -> a.before b
       asSeq  = (s) -> s.reduceRight ((a, b) -> Sequence.conj a, -> b), null

       constructor: (left, mid, right) ->
@@ -202,69 +201,69 @@
         op1(@l, op2(@m(), op1(@r, z)))

       after: (x) ->
-        if @l.constructor == T.Digit4
+        if @l.constructor == Digit4
           { a, b, c, d } = @l
-          new T.Deep(new T.Digit2(x, a),
-                     (=> @m().after(new T.Node3(b, c, d))),
+          new Deep(new Digit2(x, a),
+                     (=> @m().after(new Node3(b, c, d))),
                      @r)
         else
-          new T.Deep @l.after(x), @m, @r
+          new Deep @l.after(x), @m, @r

       before: (x) ->
-        if @r.constructor == T.Digit4
+        if @r.constructor == Digit4
           { a, b, c, d } = @r
-          new T.Deep(@l,
-                     (=> @m().before(new T.Node3(a, b, c))),
-                     new T.Digit2(d, x))
-        else
-          new T.Deep @l, @m, @r.before(x)
+          new Deep(@l,
+                     (=> @m().before(new Node3(a, b, c))),
+                     new Digit2(d, x))
+        else
+          new Deep @l, @m, @r.before(x)

       first: -> @l.first()
       last:  -> @r.last()

       rest: ->
-        if  @l.rest() == T.Empty
-          if @m() == T.Empty
+        if  @l.rest() == Empty
+          if @m() == Empty
             asTree @r
           else
-            new T.Deep @m().first().asDigit(), (=> @m().rest()), @r
-        else
-          new T.Deep @l.rest(), @m, @r
+            new Deep @m().first().asDigit(), (=> @m().rest()), @r
+        else
+          new Deep @l.rest(), @m, @r

       init: ->
-        if  @r.init() == T.Empty
-          if @m() == T.Empty
+        if  @r.init() == Empty
+          if @m() == Empty
             asTree @l
           else
-            new T.Deep @l, (=> @m().init()), @m().last().asDigit()
-        else
-          new T.Deep @l, @m, @r.init()
+            new Deep @l, (=> @m().init()), @m().last().asDigit()
+        else
+          new Deep @l, @m, @r.init()

       nodes = (n, s) ->
         if n == 0
           null
         else if n == 2 or n % 3 == 1
-          Sequence.conj new T.Node2(s.take(3).into([])...),
+          Sequence.conj new Node2(s.take(3).into([])...),
             -> nodes n-2, s.drop 2
         else if n >= 3
-          Sequence.conj new T.Node3(s.take(3).into([])...),
+          Sequence.conj new Node3(s.take(3).into([])...),
             -> nodes n-3, s.drop 3
         else
           raise new Error "this should not happen"

       app3 = (tLeft, list, tRight) ->
-        if tLeft == T.Empty
+        if tLeft == Empty
           Sequence.reduce Sequence.reverse(list), tRight, (t, x) -> t.after x
-        else if tRight == T.Empty
+        else if tRight == Empty
           Sequence.reduce list, tLeft, (t, x) -> t.before x
-        else if tLeft.constructor == T.Single
-          app3(T.Empty, list, tRight).after tLeft.a
-        else if tRight.constructor == T.Single
-          app3(tLeft, list, T.Empty).before tRight.a
+        else if tLeft.constructor == Single
+          app3(Empty, list, tRight).after tLeft.a
+        else if tRight.constructor == Single
+          app3(tLeft, list, Empty).before tRight.a
         else
           tmp = Sequence.flatten [asSeq(tLeft.r), list,  asSeq(tRight.l)]
           s = nodes tmp.size(), tmp
-          new T.Deep tLeft.l, (-> app3 tLeft.m(), s, tRight.m()), tRight.r
+          new Deep tLeft.l, (-> app3 tLeft.m(), s, tRight.m()), tRight.r

       concat: (t) -> app3 this, null, t


Update transfer test to use ProportionalSourceMore relation.

[#151508724]

https://www.pivotaltracker.com/story/show/151508724

--- test/simulation-test.coffee
+++ test/simulation-test.coffee
@@ -346,13 +346,14 @@
           expect(@nodeB.currentValue, "Node: #{@nodeB.title}").to.be.closeTo 55, 0.000001

         # sanity check
+        # transfer 10% of source (2) per step. 20 - 2 = 18 ,  50 + 2 = 52
         it "should transfer the appropriate percentage of the source node with a transfer-modifer", ->
           @nodeA.initialValue = 20
-          @transferModifier = LinkNodes(@nodeA, @transferNode, RelationFactory.half)
+          @transferModifier = LinkNodes(@nodeA, @transferNode, RelationFactory.proportionalSourceMore)
           @simulation.duration = 2
           @simulation.run()
-          expect(@nodeA.currentValue, "Node: #{@nodeA.title}").to.be.closeTo 10, 0.000001
-          expect(@nodeB.currentValue, "Node: #{@nodeB.title}").to.be.closeTo 60, 0.000001
+          expect(@nodeA.currentValue, "Node: #{@nodeA.title}").to.be.closeTo 18, 0.000001
+          expect(@nodeB.currentValue, "Node: #{@nodeB.title}").to.be.closeTo 52, 0.000001

 describe "The SimulationStore, with a network in the GraphStore", ->


convert if not statements to unless

convert if not statements to unless

--- src/coffee/breadcrumbsEatr.coffee
+++ src/coffee/breadcrumbsEatr.coffee
@@ -254,7 +254,7 @@
                             holder = null

                             # hide the dropdownWrapper if it is visible
-                            o.dropdownWrapper.hide() if not o.dropdownWrapper.is(':hidden')
+                            o.dropdownWrapper.hide() unless o.dropdownWrapper.is(':hidden')

                             # remove wrapped class to the element if it exists
                             current.removeClass(o.opts.wrappedClass) if current.hasClass(o.opts.wrappedClass)
@@ -354,7 +354,7 @@
             o.smartCompressionTimer = null

             # trigger the resize event after the plugin has loaded and the element has no hidden parents
-            if not o.isParentsHidden()
+            unless o.isParentsHidden()
                 o.browserWindow.trigger o.resizeKey

                 # resolve the onAfterLoad deferred


UGHGHGHGHGH

UGHGHGHGHGH

--- test/src/object-test.coffee
+++ test/src/object-test.coffee
@@ -12,7 +12,7 @@
     And -> @testDouble.now.toString() == '[test double for ".now"]'
     And -> @testDouble.otherThing == 8

-  describe.only 'creating an object that is an instance of a prototypal thing', ->
+  describe 'creating an object that is an instance of a prototypal thing', ->
     Given -> @type = class Thing
       foo: -> 'bar'
     When -> try td.object(new @type()) catch e then @error = e


Repository test: use test repo

Repository test: use test repo

--- test/test.repository.coffee
+++ test/test.repository.coffee
@@ -4,40 +4,35 @@
 fixtures = require "./fixtures"

 describe "Repository", ->
-	describe "Using the project repo...", ->
+	describe "Using the test repo...", ->
 		repo = null
 		it "opens correctly", (done) ->
-			gitteh.openRepository fixtures.projectRepo.path, (err, _repo) ->
+			gitteh.openRepository fixtures.testRepo.path, (err, _repo) ->
 				repo = _repo
 				repo.should.be.an.instanceof gitteh.Repository
 				done()
 		describe "#bare", ->
-			it "should be false for this repo", ->
-				repo.bare.should.be.false
+			it "should be true for this repo", ->
+				repo.bare.should.be.true
 			it "should be immutable", ->
 				repo.bare = 123
-				repo.bare.should.be.false
+				repo.bare.should.be.true
 				delete repo.path
-				repo.bare.should.be.false
+				repo.bare.should.be.true
 		describe "#path", ->
-			it "should point to #{fixtures.projectRepo.gitPath}", ->
-				repo.path.should.equal fixtures.projectRepo.gitPath
+			it "should point to #{fixtures.testRepo.path}", ->
+				repo.path.should.equal fixtures.testRepo.path
 			it "should be immutable", ->
 				repo.path = "foo"
-				repo.path.should.equal fixtures.projectRepo.gitPath
+				repo.path.should.equal fixtures.testRepo.path
 				delete repo.path
-				repo.path.should.equal fixtures.projectRepo.gitPath
+				repo.path.should.equal fixtures.testRepo.path
 		describe "#workingDirectory", ->
-			it "should point to #{fixtures.projectRepo.path}", ->
-				repo.workingDirectory.should.equal fixtures.projectRepo.path
-			it "should be immutable", ->
-				repo.path = "foo"
-				repo.workingDirectory.should.equal fixtures.projectRepo.path
-				delete repo.path
-				repo.workingDirectory.should.equal fixtures.projectRepo.path
+			it "should be null", ->
+				should.not.exist repo.workingDirectory
 		describe "#exists()", ->
 			it "should return true for first commit in repo :)", (done) ->
-				repo.exists "1f4425ce2a14f21b96b9c8dde5bcfd3733467b14", (err, exists) ->
+				repo.exists fixtures.testRepo.firstCommit.id, (err, exists) ->
 					exists.should.be.true
 					done()
 			it "should reject invalid oids", ->
@@ -52,42 +47,42 @@
 				).should.throw()
 		describe "#object()", ->
 			it "works for full OID", (done) ->
-				repo.object "1f4425ce2a14f21b96b9c8dde5bcfd3733467b14", (err, obj) ->
+				repo.object fixtures.testRepo.secondCommit.id, (err, obj) ->
 					should.not.exist err
 					obj.should.be.an.instanceof gitteh.Commit
 					done()
 			it "works for shortened OID", (done) ->
-				repo.object "1f4425ce2a", (err, obj) ->
+				repo.object fixtures.testRepo.secondCommit.id[..8], (err, obj) ->
 					should.not.exist err
 					obj.should.be.an.instanceof gitteh.Commit
 					done()
 		describe "#commit()", ->
 			it "works", (done) ->
-				repo.commit "1f4425ce2a14f21b96b9c8dde5bcfd3733467b14", (err, obj) ->
+				repo.commit fixtures.testRepo.secondCommit.id, (err, obj) ->
 					should.not.exist err
 					obj.should.be.an.instanceof gitteh.Commit
 					done()
 			it "fails for objects that aren't a commit", (done) ->
-				repo.commit fixtures.projectRepo.secondCommit.wscriptBlob, (err, obj) ->
+				repo.commit fixtures.testRepo.secondCommit.readmeBlob, (err, obj) ->
 					should.exist err
 					done()
 		describe "#tree()", ->
 			it "works", (done) ->
-				repo.tree fixtures.projectRepo.secondCommit.tree, (err, obj) ->
+				repo.tree fixtures.testRepo.secondCommit.tree, (err, obj) ->
 					should.not.exist err
 					obj.should.be.an.instanceof gitteh.Tree
 					done()
 			it "fails for objects that aren't a tree", (done) ->
-				repo.tree fixtures.projectRepo.secondCommit.id, (err, obj) ->
+				repo.tree fixtures.testRepo.secondCommit.id, (err, obj) ->
 					should.exist err
 					done()
 		describe "#blob()", ->
 			it "works", (done) ->
-				repo.blob fixtures.projectRepo.secondCommit.wscriptBlob, (err, obj) ->
+				repo.blob fixtures.testRepo.secondCommit.readmeBlob, (err, obj) ->
 					should.not.exist err
 					obj.should.be.an.instanceof gitteh.Blob
 					done()
 			it "fails for objects that aren't a blob", (done) ->
-				repo.blob fixtures.projectRepo.secondCommit.id, (err, obj) ->
+				repo.blob fixtures.testRepo.secondCommit.id, (err, obj) ->
 					should.exist err
 					done()


add test for copying layer styles

add test for copying layer styles

--- test/tests/LayerTest.coffee
+++ test/tests/LayerTest.coffee
@@ -929,9 +929,14 @@
 			copy.width.should.equal 100
 			copy.height.should.equal 100

-
-
-
-
-
-
+		it "copied layer should copy styles", ->
+
+			layer = new Layer
+			layer.style.backgroundColor = "yellow"
+
+			layer2 = layer.copy()
+			layer2.style.backgroundColor.should.equal "yellow"
+
+
+
+


sagews2html: multiple show plots deduplication, author name and project id; autodetecting title

--- src/smc-webapp/printing.coffee
+++ src/smc-webapp/printing.coffee
@@ -158,7 +158,7 @@
                     <meta charset="utf-8">

                     <title>#{data.title}</title>
-                    <meta name="description" content="automatically generated from '#{data.filename} on SageMathCloud">
+                    <meta name="description" content="automatically generated from '#{data.project_id}:#{data.filename}' on SageMathCloud">
                     <meta name="date" content="#{data.timestamp}">


limit number of middlewares

limit number of middlewares

--- proxy/app.coffee
+++ proxy/app.coffee
@@ -9,12 +9,9 @@

   @order: [
     'reqLogger'
-    'bodyParser'
-    'cors'
     '$custom'
     'static'
     '404'
-    '500'
   ]

   # opts = ctrl: ctrl, method: method


Simplify type mappings, add coercion for string type

--- layout.coffee
+++ layout.coffee
@@ -112,6 +112,7 @@
   typemappings =
     number: parseFloat
     boolean: (val) -> (if (typeof val == 'string') then val == 'true' else (!! val))
+    string: (val) -> val + ''

   installMethod = (scope, methodname, method) ->
     if methodname of scope
@@ -287,8 +288,8 @@

       # coerce value to type
       type = @types[name]
-      if type
-        value = typemappings[type](value) if type of typemappings
+      if type# and type of typemappings
+        value = typemappings[type](value)
         # console.log 'type', name, type, value, @

       if @[name] != value


judge platform in save-log

judge platform in save-log

--- views/akashic-advanced-module.cjsx
+++ views/akashic-advanced-module.cjsx
@@ -29,15 +29,11 @@
 AttackLog = React.createClass
   getInitialState: ->
     typeChoosed: '出击'
-    codeType: '选择文件编码格式'
   # componentWillMount: ->
   #   console.log "test"
   handleSetType: ->
     @setState
       typeChoosed: @refs.type.getValue()
-  handleSetCode: ->
-    @setState
-      codeType: @refs.codeType.getValue()
   showMessage: (message)->
     dialog.showMessageBox
       type: 'info'
@@ -66,21 +62,22 @@
         else
           @showMessage '发生错误！请报告开发者'
           return
-      if @state.codeType isnt 'utf8' and @state.codeType isnt 'GBK'
-        @showMessage '请选择编码格式'
-      else
-        filename = dialog.showSaveDialog
-          title: "保存#{@state.typeChoosed}记录"
-          defaultPath: "#{nickNameId}-#{logType}.csv"
-        if filename?
-          saveData = "#{@props.tableTab[logType].slice(1).join(',')}\n"
-          for item in data
-            saveData = "#{saveData}#{toDateLabel item[0]},#{item.slice(1).join(',')}\n"
-          if @state.codeType is 'GBK'
-            saveData = iconv.encode saveData, 'GBK'
-          fs.writeFile filename, saveData, (err)->
-            if err
-              console.log "err! Save data error"
+      if process.platform is 'win32'
+        codeType = 'GBK'
+      else
+        codeType = 'utf8'
+      filename = dialog.showSaveDialog
+        title: "保存#{@state.typeChoosed}记录"
+        defaultPath: "#{nickNameId}-#{logType}.csv"
+      if filename?
+        saveData = "#{@props.tableTab[logType].slice(1).join(',')}\n"
+        for item in data
+          saveData = "#{saveData}#{toDateLabel item[0]},#{item.slice(1).join(',')}\n"
+        if codeType is 'GBK'
+          saveData = iconv.encode saveData, 'GBK'
+        fs.writeFile filename, saveData, (err)->
+          if err
+            console.log "err! Save data error"
     else
       @showMessage '未找到相应的提督！是不是还没登录？'
   importLogHandle: ->
@@ -100,7 +97,7 @@
           </Col>
         </Row>
         <Row>
-          <Col xs={3}>
+          <Col xs={4}>
             <Input type="select" ref="type" value={@state.typeChoosed} onChange={@handleSetType}>
                 <option key={0} value={'出击'}>出击</option>
                 <option key={1} value={'远征'}>远征</option>
@@ -109,17 +106,10 @@
                 <option key={4} value={'资源'}>资源</option>
             </Input>
           </Col>
-          <Col xs={3}>
-            <Input type="select" ref="codeType" value={@state.codeType} onChange={@handleSetCode}>
-                <option key={0} value={'选择文件编码格式'}>文件编码格式</option>
-                <option key={1} value={'utf8'}>UTF-8(Linux, OSX用户)</option>
-                <option key={2} value={'GBK'}>GBK(Windows用户)</option>
-            </Input>
-          </Col>
-          <Col xs={3}>
+          <Col xs={4}>
              <Button bsStyle='primary' style={width: '100%'} onClick={@saveLogHandle}>导出</Button>
           </Col>
-          <Col xs={3}>
+          <Col xs={4}>
              <Button bsStyle='primary' style={width: '100%'} onClick={@importLogHandle}>导入</Button>
           </Col>
         </Row>


Fix interpretation of left argument of pick.

--- src/vocabulary/disclose.coffee
+++ src/vocabulary/disclose.coffee
@@ -6,22 +6,36 @@

     # Pick (`⊃`)
     #
-    # ⍬⊃3            <=> 3
-    # 2⊃'PICK'       <=> 'C'
-    # 1 0⊃2 2⍴'ABCD' <=> 'C'
-    # 1⊃'foo' 'bar'  <=> 'bar'
-    # (2 2⍴0)⊃1 2    !!! RANK ERROR
-    # (2 2)⊃1 2      !!! RANK ERROR
-    # 0 2⊃2 2⍴'ABCD' !!! INDEX ERROR
+    # ⍬⊃3               <=> 3
+    # 2⊃'PICK'          <=> 'C'
+    # (⊂1 0)⊃2 2⍴'ABCD' <=> 'C'
+    # 1⊃'foo' 'bar'     <=> 'bar'
+    # 1 2⊃'foo' 'bar'   <=> 'r'
+    # (2 2⍴0)⊃1 2       !!! RANK ERROR
+    # (⊂2 1⍴0)⊃2 2⍴0    !!! RANK ERROR
+    # (⊂2 2⍴0)⊃1 2      !!! RANK ERROR
+    # (⊂2 2)⊃1 2        !!! RANK ERROR
+    # (⊂0 2)⊃2 2⍴'ABCD' !!! INDEX ERROR
     if alpha.shape.length > 1
       throw RankError()
-    pick = alpha.toArray()
-    if pick.length isnt omega.shape.length
-      throw RankError()
-    for i in [0...pick.length]
-      if pick[i] >= omega.shape[i]
-        throw IndexError()
-    omega.get pick
+    x = omega
+    path = alpha.toArray()
+    for pick in path
+      if pick instanceof APLArray
+        if pick.shape.length > 1
+          throw RankError()
+        pick = pick.toArray()
+      else
+        pick = [pick]
+      if pick.length isnt x.shape.length
+        throw RankError()
+      for i in [0...pick.length]
+        if pick[i] >= x.shape[i]
+          throw IndexError()
+      x = x.get pick
+      if x not instanceof APLArray
+        x = APLArray.scalar x
+    x

   else

@@ -35,7 +49,5 @@
     #!    ⊃''               <=> ' '
     if omega.empty()
       return APLArray.zero
-    pick = []
-
-  x = omega.get pick
-  if x instanceof APLArray then x else APLArray.scalar x
+    x = omega.get []
+    if x instanceof APLArray then x else APLArray.scalar x


Fixed worker running.

Fixed worker running.

--- worker.coffee
+++ worker.coffee
@@ -2,7 +2,7 @@

 class JobsWorker extends JobsWorker
   @WORKER_INSTANCES: parseInt(process.env.WORKER_INSTANCES || '1')
-  @WORKER_INSTANCES: 1 unless _.isFinite @WORKER_INSTANCES
+  @WORKER_INSTANCES: if _.isFinite(@WORKER_INSTANCES) then @WORKER_INSTANCES else 1

   @STALLED_JOB_CHECK_INTERVAL: 60 * 1000 # ms
   @PROMOTE_INTERVAL: 15 * 1000 # ms


Remove unused FlashService refs

Remove unused FlashService refs

--- lineman/app/app.coffee
+++ lineman/app/app.coffee
@@ -25,7 +25,7 @@
     snakeName = _.snakeCase(name);
     'generated/components/' + snakeName + '/' + snakeName + '.html';

-angular.module('loomioApp').controller 'AppController', ($scope, $filter, $rootScope, $router, KeyEventService, FlashService) ->
+angular.module('loomioApp').controller 'AppController', ($scope, $filter, $rootScope, $router, KeyEventService) ->
   $scope.currentComponent = 'nothing yet'

   $scope.$on 'currentComponent', ->


Added default prompt

Added default prompt

--- lib/ui.coffee
+++ lib/ui.coffee
@@ -134,12 +134,12 @@
     @color 'none', 'none'
     return @

-  prompt: ->
+  prompt: (value) ->
     @pos @stdout.rows, 0
     @color 'black', 'white'
     @fillLine()
     @pos @stdout.rows+1, 0
-    @write '> '
+    @write '> ' + (if typeof value != 'undefined' then value else '')
     return @

   build: ->


in which the remaining bugs were fixed

in which the remaining bugs were fixed


fix channel type parsing

fix channel type parsing

--- grammar.coffee
+++ grammar.coffee
@@ -211,7 +211,7 @@
     map_type: -> seq(keyword("map"), "[", @key_type, "]", @element_type)
     key_type: -> @type

-    channel_type: -> seq(choice(keyword("chan"), seq(keyword("chan"), "<-"), seq(keyword("chan"), "->")), @element_type)
+    channel_type: -> seq(choice(keyword("chan"), seq(keyword("chan"), "<-"), seq("<-", keyword("chan"))), @element_type)

     #########################################################################
     # Statements


Missouri folk Placeholders for Trish, William and Mike.


Ignore reveal.js plugin leap

Ignore reveal.js plugin leap

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -89,6 +89,7 @@
                     timestamp: true
                     exclude: [
                       'bower_components/reveal.js/plugin/leap'
+                      'bower_components/reveal.js/plugin/leap/leap.js'
                     ]
                 src: [
                     'css/**'


Scope build to components used in main graph

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -13,6 +13,7 @@
     # Browser build of NoFlo
     noflo_browser:
       options:
+        graph: 'ui/main'
         manifest:
           runtimes: [
             'noflo'


Don't copy:ymls, create_env_settings in test grunt task

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -294,10 +294,6 @@
     'start_test_server'
     'watch'
   ]
-  grunt.registerTask 'test', [
-    'copy:ymls'
-    'create_env_settings'
-    'karma:single'
-  ]
+  grunt.registerTask 'test', ['karma:single']

   return


grunt rebuild

grunt rebuild

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -157,6 +157,7 @@
   # Our local tasks
   @registerTask 'nuke', ['exec:nuke_main', 'exec:nuke_preview']
   @registerTask 'build', ['exec:main_install', 'exec:main_build', 'exec:preview_install', 'exec:preview_build']
+  @registerTask 'rebuild', ['nuke', 'build']
   @registerTask 'test', ['coffeelint', 'build', 'coffee', 'mocha_phantomjs']
   @registerTask 'app', ['build', 'compress', 'phonegap-build']
   @registerTask 'default', ['test']


Ignore unrelated tests during development

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -296,9 +296,9 @@
   # Travis CI
   # -----
   grunt.registerTask 'test', [
-    'jshint'
-    'jsbeautifier'
-    'coffeelint'
+    #'jshint'
+    #'jsbeautifier'
+    #'coffeelint'
     'mocha'
     #'recess' NOTE: Disabled until recess is upgraded to support LESS 1.6+
   ]


chore: report coveralls if travis is present

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -53,8 +53,8 @@
     coveralls:
       options:
         coverageDir: '.coverage/',
-        debug: !!process.env.TRAVIS,
-        dryRun: !!process.env.TRAVIS,
+        debug: !process.env.TRAVIS,
+        dryRun: !process.env.TRAVIS,
         force: true,
         recursive: true


Fix build system not to depend on pre-existence of droplet-full.js

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -1,11 +1,10 @@
-path = require 'path'
-
 browserify = require 'browserify'
 coffeeify = require 'coffeeify'
 watchify = require 'watchify'

 livereload = require 'tiny-lr'

+path = require 'path'
 fs = require 'fs'

 serveNoDottedFiles = (connect, options, middlewares) ->
@@ -23,13 +22,11 @@
   # require() calls from different modules systems or
   # are already packaged.
   NO_PARSE = [
-    require.resolve('./vendor/coffee-script')
-    require.resolve('./vendor/acorn')
-    require.resolve('./vendor/skulpt.js')
+    path.resolve('./vendor/coffee-script.js')
+    path.resolve('./vendor/acorn.js')
+    path.resolve('./vendor/skulpt.js')
+    path.resolve('./dist/droplet-full.js')
   ]
-
-  try
-    NO_PARSE.push require.resolve './dist/droplet-full'

   grunt.initConfig
     pkg: grunt.file.readJSON 'package.json'


Make sure fbp-manifest doesn't pick up legacy component.io modules as NoFlo components

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -13,6 +13,13 @@
     # Browser build of NoFlo
     noflo_browser:
       options:
+        manifest:
+          runtimes: [
+            'noflo'
+          ]
+          discover: true
+          recursive: true
+          subdirs: false
         baseDir: './'
         webpack:
           externals:


Remove api.json during clean

Remove api.json during clean

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -42,7 +42,10 @@
   grunt.loadNpmTasks('grunt-coffeelint')
   grunt.loadNpmTasks('grunt-atomdoc')

-  grunt.registerTask 'clean', -> require('rimraf').sync('lib')
+  grunt.registerTask 'clean', ->
+    require('rimraf').sync('lib')
+    require('rimraf').sync('api.json')
+
   grunt.registerTask('lint', ['coffeelint'])
   grunt.registerTask('default', ['lint', 'coffee', 'peg'])
   grunt.registerTask('test', ['coffee', 'lint', 'shell:test'])


added coffee:jslove to compile all project coffee files, issue #31

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -32,6 +32,18 @@
 					# Don't include a surrounding Immediately-Invoked Function Expression (IIFE) in the compiled output.
 					# For more information on IIFEs, please visit http://benalman.com/news/2010/11/immediately-invoked-function-expression/
 					bare: true
+			jslove:
+				files: [
+					cwd: './'
+					src: [
+						'**/*.coffee'
+						'!**/node_modules/**'
+					]
+					dest: './'
+					expand: true
+					ext: '.js'
+				]
+				options: '<%= coffee.scripts.options %>'

 		# Copies directories and files from one location to another.
 		copy:
@@ -333,7 +345,7 @@
 	# grunt
 	grunt.registerTask 'default', [
 		'clean'
-		'coffee'
+		'coffee:scripts'
 		'less'
 		'template:views'
 		'copy:img'
@@ -355,7 +367,7 @@
 	# grunt prod
 	grunt.registerTask 'prod', [
 		'clean'
-		'coffee'
+		'coffee:scripts'
 		'less'
 		'template:views'
 		'imagemin'


Make grunt bump work with new major versioning scheme

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -41,7 +41,7 @@
           replace: -> "var NOTIFIER_VERSION = \"#{require("./package.json").version}\";"
         ,
           name: "readme"
-          search: /cloudfront.net\/bugsnag-[0-9\.]+.min.js/g
+          search: /cloudfront.net\/bugsnag-([0-9]+\.)+[0-9]+.min.js/g
           replace: -> "cloudfront.net/bugsnag-#{require("./package.json").version}.min.js"
         ]


add comment and fix style

add comment and fix style

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -36,8 +36,7 @@

 # Use symlinkSrc with the name of the module, and it will automatically symlink
 # the path to its src/ directory.
-Rule.symlinkSrc = (module) =>
-  Rule.symlink Path.join(getNodePath(module), 'src')
+Rule.symlinkSrc = (module) => Rule.symlink Path.join(getNodePath(module), 'src')
 Rule.symlinkThirdParty = (module) =>
   Rule.symlink(Path.join(getNodePath(module), 'third_party'), 'third_party')

@@ -62,6 +61,9 @@
   rule = Rule.typescriptSpecDecl name
   rule.options.noImplicitAny = false
   rule
+# fast = 'never' refers to recompiling even if .tscache suggests that the
+# same files were already compiled. Needed to recompile generic_ui
+# between Chrome/FF builds in case polymer/ contents have changes.
 Rule.typescriptSrcLenientNeverFast = (name) =>
   rule = Rule.typescriptSrc name
   rule.options.noImplicitAny = false


Copy image an dist task

Copy image an dist task

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -29,7 +29,7 @@
             jshint:
                 files: ['js/*.js']
                 tasks: ['jshint']
-
+
         connect:

             livereload:
@@ -67,6 +67,7 @@
                     src: [
                         'slides/**'
                         'bower_components/**'
+                        'image/**'
                         'js/**'
                     ]
                     dest: 'dist/'
@@ -77,7 +78,7 @@
                     filter: 'isFile'
                 }]

-
+
         buildcontrol:

             options:
@@ -89,7 +90,7 @@
                 options:
                     remote: 'git@github.com:perspective-on-js/presentation.git'
                     branch: 'gh-pages'
-
+

     # Load all grunt tasks.
@@ -131,13 +132,13 @@
             'copy'
         ]

-
+
     grunt.registerTask 'deploy',
         'Deploy to Github Pages', [
             'dist'
             'buildcontrol'
         ]
-
+

     # Define default task.
     grunt.registerTask 'default', [


Don't recompile app_top when scripts change.

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -82,7 +82,7 @@
     watch:
       scripts:
         files: ['app/assets/scripts/**/*.coffee']
-        tasks: ['coffee', 'concat:app_top_js', 'concat:app_js', 'clean:post']
+        tasks: ['coffee', 'concat:app_js', 'clean:post']

       styles:
         files: ['app/assets/styles/**/*.less']


auto pin mode

auto pin mode

--- grovepi.coffee
+++ grovepi.coffee
@@ -38,9 +38,9 @@
 	mode: (port, mode, callback) ->
 		unless modes[port]? is mode
 			modes[port] = mode
-			send CMD.ranger, port, mode
+			@send CMD.ranger, port, mode

-	send = ( cmd, port, args... ) =>
+	send: ( cmd, port, args... ) ->
 		unless cmd is CMD.mode
 			@mode port, MODES.output
 		writeArgs = [cmd]
@@ -64,7 +64,7 @@
 		wire[writeCmd] writeArgs...

-	receive = ( port, args... ) ->
+	receive: ( port, args... ) ->
 		@mode port, MODES.input
 		readArgs = []
 		if args[1]
@@ -85,13 +85,13 @@
 		wire[readCmd] readArgs...

 	write: ( type, port, data, callback ) ->
-		send CMD[type].write, port, data, callback
+		@send CMD[type].write, port, data, callback

 	read: ( type, args... ) ->
-		send CMD[type].read, args...
+		@send CMD[type].read, args...

 	ranger: ( port, callback ) ->
-		send CMD.ranger, port, [0,0], ->
-			receive port, 3, (data) ->
+		@send CMD.ranger, port, [0,0], =>
+			@receive port, 3, (data) ->
 				callback data[2] + data[1]


Changed: removeDocs is now marked as public

--- main.coffee
+++ main.coffee
@@ -105,7 +105,7 @@

             # Removing documents
             @log "\t* Deleting documents from the Data System..."
-            @_removeDocs doctypeName, (err) =>
+            @removeDocs doctypeName, (err) =>
                 if err?
                     msg = "\t\tx Couldn't delete documents from the Data " + \
                                "System --- #{err}"
@@ -180,7 +180,7 @@
         @client.put "request/#{doctypeName}/all/", all, (err, res, body) ->
             callback err

-    _removeDocs: (doctypeName, callback) ->
+    removeDocs: (doctypeName, callback) ->
         url = "request/#{doctypeName}/all/destroy/"
         @client.put url, {}, (err, res, body) ->
             err = body.error if body? and body.error?


Bubble sort ascending ahem...

Bubble sort ascending ahem...

--- main.coffee
+++ main.coffee
@@ -91,7 +91,7 @@
 bsort = ->
 	swapped = false
 	for i in [1...colours.length]
-		if colours[i - 1].val <= colours[i].val
+		if colours[i - 1].val > colours[i].val
 			swapRects(i - 1, i)
 			swapped = true