remove some spew

remove some spew

--- lib/new-cc.coffee
+++ lib/new-cc.coffee
@@ -636,22 +636,13 @@
                                                                 func_envs[i-1].addChild(func_envs[i])
                                                         catch e
                                                                 console.log "1 while working on scope for function #{func_idx} #{func.id?.name}/#{func.loc?.start.line}"
+                                                                console.log "func_envs = [#{env.name for env in func_envs}]"
                                                                 throw e

-                                        if func_envs[0].scope.differentFunction(s)
-                                                debug.log " #{func_envs[0].name} was from a different function"
-                                                for fenv in func_envs
-                                                        debug.log(" func_env #{fenv.name} slots=#{fenv.slotCount()}")
-                                                debug.log "current path is:"
-                                                for penv in env_path
-                                                        debug.log(" env_path #{penv.name} #{penv.scope.isFunctionBodyScope()}")
-
+                                        if func_envs[func_envs.length-1].scope.differentFunction(s)
                                                 # the environment for this function wasn't from this function
                                                 if env_path.length > 2
-                                                        for fe in [(env_path.length-2)..1]  # -2 = skip ours
-                                                                #if env_path[fe] is func_envs[0]
-                                                                #        break
-
+                                                        for fe in [(env_path.length-1)..1]
                                                                 if env_path[fe].slot_map.size() > 0
                                                                         try
                                                                                env_path[fe-1].addChild(env_path[fe])


rough cut

rough cut

--- src/goggles.coffee
+++ src/goggles.coffee
@@ -1,14 +1,54 @@
 Q = require('q')

-Goggles = {
-  mixin: {
-    request: (requestConstructor, args...) ->
-      def = Q.defer()
-      @api.then((api) ->
-        api.client.request(eventsRequest.apply(this, arguments)).execute((results) ->
-          def.resolve(results)
-        )
-      )
-      return def.promise
-  }
-}
+do (window, document) ->
+
+  WINDOW_CALLBACK_NAME = 'gogglesOnLoad'
+
+  class Goggles
+
+    constructor: (opts = {}) ->
+      throw "api key required" unless opts.apiKey
+      throw "client id required" unless opts.clientId
+
+      @def = Q.defer()
+
+      @apiKey = opts.apiKey
+      @clientId = opts.clientId
+      @scopes = opts.scope || []
+
+      window[WINDOW_CALLBACK_NAME] = @windowCallback
+
+      @appendGapiScript()
+      @def.promise.login = @login
+
+      return @def.promise
+
+    windowCallback: =>
+      @gapi = window.gapi
+      @gapi.client.setApiKey(@apiKey)
+      @gapi.auth.authorize({client_id: @clientId, scope: @scopes, immediate: true}, @handleAuthResult)
+      console.log("gapi loaded")
+
+    appendGapiScript: ->
+      tag = document.createElement('script')
+      tag.type = 'text/javascript'
+      tag.async = true
+      tag.src = "https://apis.google.com/js/client.js?onload=#{WINDOW_CALLBACK_NAME}"
+
+      sib = document.getElementsByTagName('script')[0]
+      sib.parentNode.insertBefore(tag, sib)
+
+    authSuccess: () ->
+      @def.resolve(@gapi)
+
+    login: =>
+      @gapi.auth.authorize({client_id: @clientId, scope: @scopes, immediate: false}, @handleAuthResult)
+
+    handleAuthResult: (authResult) =>
+      if authResult and not authResult.error
+        @authSuccess()
+      else
+        console.warn "unsuccessful auth", authResult
+
+  window.Goggles = Goggles
+


add simple assignlist

add simple assignlist

--- src/grammar.coffee
+++ src/grammar.coffee
@@ -81,6 +81,8 @@
   Body: [
     o 'Line',                                   -> Block.wrap [$1]
     o 'Body TERMINATOR Line',                   -> $1.push $3
+    o 'SimpleAssign',                           -> Block.wrap [$1]
+    o 'Body TERMINATOR SimpleAssign',           -> $1.push $3
     o 'Body TERMINATOR'
   ]

@@ -336,6 +338,15 @@
     o 'Value Accessor',                         -> $1.add $2
     o 'Code Accessor',                          -> new Value($1).add $2
     o 'ThisProperty'
+  ]
+
+  SimpleAssignableList: [
+    o 'SimpleAssignable , SimpleAssignable',     -> [$1, $3]
+    o 'SimpleAssignableList , SimpleAssignable', -> $1.concat $3
+  ]
+
+  SimpleAssign: [
+    o 'SimpleAssignableList = Expression',       -> new Assign new Value(new Arr($1)), $3
   ]

   # Everything that can be assigned to.


Add [] () to inline type signature characters

--- src/haskell.coffee
+++ src/haskell.coffee
@@ -366,7 +366,7 @@
         2: name: 'keyword.other.double-colon.haskell'
         3: {name: 'meta.type-signature.haskell', patterns: [include: '#type_signature']}
     ,
-      match: '(::|∷)((?:{className}|{functionName}|\\->|=>|→|⇒|\\s)*)'
+      match: '(::|∷)((?:{className}|{functionName}|\\->|=>|[→⇒()\\[\\]]|\\s)*)'
       captures:
         1: name: 'keyword.other.double-colon.haskell'
         2: {name: 'meta.type-signature.haskell', patterns: [include: '#type_signature']}


add isAllowed(resource, ruleName, model, context)

--- lib/parser.coffee
+++ lib/parser.coffee
@@ -75,12 +75,15 @@

     optimizer = Optimizer.create language

+    #console.log 'rules', typeof rules, rules
+
     @_recursiveNormalize rules, optimizer, rulesObj

     resourceObj.rules[name] = rulesObj
     @parsed[resource] = resourceObj

   _recursiveNormalize: (rules, optimizer, rulesObj, level=1)->
+    #padding = ''
     if _.isArray rules.either
       #console.log(padding + 'either', arguments[0], arguments[2])
       $or = []
@@ -104,19 +107,33 @@
       #console.log(padding + 'string', arguments[0], arguments[2])
       rulesObj.push optimizer.optimize rules

+    else if rules is true or rules is false
+      #console.log(padding + 'boolean', arguments[0], arguments[2])
+      rulesObj.push rules
+
   applyContext: (resource, action, context)->
+    logger = log4js.getLogger 'applyContext'
+    logger.setLevel 'ERROR'
+
+    logger.trace 'resource', resource
+    logger.trace 'action', action
+    logger.trace 'context', context
+
     root = _.cloneDeep @parsed[resource]?.rules
     cloned = root?[action]

     return unless cloned

     root = {$and: cloned}
+    logger.trace 'before root', root

     #for rule, index in cloned
     @_recursiveApplyContext root, '$and', cloned, context, '$and'

     if root.$and?.length == 1
       return root.$and[0]
+
+    logger.trace 'after root', root

     return root

@@ -190,13 +207,20 @@
       for key, subValue of value
         @_recursiveApplyContext value, key, subValue, context, key

+  isAllowed: (resource, ruleName, model, context)->
+    logger = log4js.getLogger 'isAllowed'
+    logger.setLevel 'ERROR'
+
+    logger.trace 'resource', resource
+    logger.trace 'ruleName', ruleName
+    logger.trace 'context', context
+
+    rules = @applyContext resource, ruleName, context
+    logger.debug 'rules', rules
+    @validateModel model, rules
+
   createAllowed: (resource, model, context)->
-    logger = log4js.getLogger 'createAllowed'
-    logger.setLevel 'ALL'
-
-    rules = @applyContext resource, 'create', context
-    #logger.debug 'rules', rules
-    @validateModel model, rules
+    @isAllowed resource, 'create', model, context

   validateModel: (model, rules)->
     logger = log4js.getLogger 'validateModel'


Integration test updated

Integration test updated

--- test/IntegrationSpec.coffee
+++ test/IntegrationSpec.coffee
@@ -94,11 +94,6 @@
           expect(obj).toBeEqual {one: 'test'}
           expect(arr).toBeEqual ['a', 'b', 'c']

-        # JE.afterEach ->
-        #   expect(subject).toBeUndefined()
-        #   expect(obj).toBeEqual {one: 'test'}
-        #   expect(arr).toBeEqual ['a', 'b', 'c']
-
         @describe 'middle_first', ->
           func.is (coll)-> obj['two'] = coll

@@ -120,194 +115,122 @@
             expect(obj).toBeEqual {one: 'test'}
             expect(arr).toBeEqual ['a', 'b', 'c']

-        #   JE.afterEach ->
-        #     expect(subject).toBeUndefined()
-        #     expect(func)   .toBeDefined()
-        #     expect(func)   .toBeAFunction()
-        #     expect(obj).toBeEqual {one: 'test'}
-        #     expect(arr).toBeEqual ['a', 'b', 'c']
-
           @describe 'inner_first', ->
             collection.is [1, 2, 3, 4]

             JE.beforeEach ->
-              expect(func).toBeUndefined() # bug?
+              expect(func).toBeUndefined() # bug
               expect(obj).toBeEqual {one: 'test', two: [1, 2, 3, 4]}
               expect(arr).toBeEqual ['a', 'b', 'c']
               expect(subject).toBeEqual [1, 2, 3, 4]
               expect(collection).toBeEqual [1, 2, 3, 4]

             @it 'inner it first', ->
-              expect(func).toBeUndefined() # bug?
+              expect(func).toBeUndefined() # bug
               expect(obj).toBeEqual {one: 'test', two: [1, 2, 3, 4]}
               expect(arr).toBeEqual ['a', 'b', 'c']
               expect(subject).toBeEqual [1, 2, 3, 4]
               expect(collection).toBeEqual [1, 2, 3, 4]

             @it 'inner it second', ->
-              expect(func).toBeUndefined() # bug?
+              expect(func).toBeUndefined() # bug
               expect(obj).toBeEqual {one: 'test', two: [1, 2, 3, 4]}
               expect(arr).toBeEqual ['a', 'b', 'c']
               expect(subject).toBeEqual [1, 2, 3, 4]
               expect(collection).toBeEqual [1, 2, 3, 4]

-        #     JE.afterEach ->
-        #       expect(func).toBeDefined()
-        #       expect(func).toBeAFunction()
-        #       expect(obj).toBeEqual {one: 'test', two: [1, 2, 3, 4]}
-        #       expect(arr).toBeEqual ['a', 'b', 'c']
-        #       expect(subject).toBeEqual [1, 2, 3, 4]
-        #       expect(collection).toBeEqual [1, 2, 3, 4]
-
           @describe 'inner_second', ->
             collection.is ['one', 'two', 'three']

             JE.beforeEach ->
-              expect(func).toBeUndefined() # bug?
+              expect(func).toBeUndefined() # bug
               expect(obj).toBeEqual {one: 'test', two: ['one', 'two', 'three']}
               expect(arr).toBeEqual ['a', 'b', 'c']
               expect(subject).toBeEqual ['one', 'two', 'three']
               expect(collection).toBeEqual ['one', 'two', 'three']

             @it 'inner it third', ->
-              expect(func).toBeUndefined() # bug?
+              expect(func).toBeUndefined() # bug
               expect(obj).toBeEqual {one: 'test', two: ['one', 'two', 'three']}
               expect(arr).toBeEqual ['a', 'b', 'c']
               expect(subject).toBeEqual ['one', 'two', 'three']
               expect(collection).toBeEqual ['one', 'two', 'three']

             @it 'inner it fourth', ->
-              expect(func).toBeUndefined() # bug?
+              expect(func).toBeUndefined() # bug
               expect(obj).toBeEqual {one: 'test', two: ['one', 'two', 'three']}
               expect(arr).toBeEqual ['a', 'b', 'c']
               expect(subject).toBeEqual ['one', 'two', 'three']
               expect(collection).toBeEqual ['one', 'two', 'three']

-        #     JE.afterEach ->
-        #       expect(func).toBeDefined()
-        #       expect(func).toBeAFunction()
-        #       expect(obj).toBeEqual {one: 'test', two: ['one', 'two', 'three']}
-        #       expect(arr).toBeEqual ['a', 'b', 'c']
-        #       expect(subject).toBeEqual ['one', 'two', 'three']
-        #       expect(collection).toBeEqual ['one', 'two', 'three']
-
         @describe 'middle_second', ->
           func.is (coll)-> arr.push coll[0]

           JE.beforeEach ->
-            expect(subject).toBeEqual 4 # bug?
-            # expect(subject).toBeUndefined() # should be
-            expect(func).toBeUndefined() # bug?
-            expect(obj).toBeEqual {one: 'test', two: ['one', 'two', 'three']} # bug
-            # expect(obj).toBeEqual {one: 'test'} # should be
-            expect(arr).toBeEqual ['a', 'b', 'c', 'one'] # bug
-            # expect(arr).toBeEqual ['a', 'b', 'c'] # should be
+            expect(func).toBeUndefined() # bug
+            expect(subject).toBeUndefined()
+            expect(obj).toBeEqual {one: 'test'}
+            expect(arr).toBeEqual ['a', 'b', 'c']

           @it 'middle it third', ->
-            expect(subject).toBeEqual 4 # bug?
-            # expect(subject).toBeUndefined() # should be
-            expect(func).toBeUndefined() # bug?
-            expect(obj).toBeEqual {one: 'test', two: ['one', 'two', 'three']} # bug
-            # expect(obj).toBeEqual {one: 'test'} # should be
-            expect(arr).toBeEqual ['a', 'b', 'c', 'one'] # bug
-            # expect(arr).toBeEqual ['a', 'b', 'c'] # should be
+            expect(subject).toBeUndefined()
+            expect(func).toBeUndefined() # bug
+            expect(obj).toBeEqual {one: 'test'}
+            expect(arr).toBeEqual ['a', 'b', 'c']

           @it 'middle it fourth', ->
-            expect(subject).toBeEqual 4 # bug?
-            # expect(subject).toBeUndefined() # should be
-            expect(func).toBeUndefined() # bug?
-            expect(obj).toBeEqual {one: 'test', two: ['one', 'two', 'three']} # bug
-            # expect(obj).toBeEqual {one: 'test'} # should be
-            expect(arr).toBeEqual ['a', 'b', 'c', 'one'] # bug
-            # expect(arr).toBeEqual ['a', 'b', 'c'] # should be
+            expect(subject).toBeUndefined()
+            expect(func).toBeUndefined() # bug
+            expect(obj).toBeEqual {one: 'test'}
+            expect(arr).toBeEqual ['a', 'b', 'c']

           @describe 'inner_third', ->
             collection.is ['d', 'e', 'f']

             JE.beforeEach ->
               expect(func).toBeUndefined() # bug
-              # expect(func).toBeDefined() # should be
-              expect(obj).toBeEqual {one: 'test', two: ['one', 'two', 'three']} # bug
-              # expect(obj).toBeEqual {one: 'test'} # should be
-              expect(arr).toBeEqual ['a', 'b', 'c', 'one', 'd'] # bug
-              # expect(arr).toBeEqual ['a', 'b', 'c', 'd'] # should be
-              expect(subject).toBeEqual 5 # bug
-              # expect(subject).toBeEqual 4 # should be
+              expect(obj).toBeEqual {one: 'test'}
+              expect(arr).toBeEqual ['a', 'b', 'c', 'd']
+              expect(subject).toBeEqual 4
               expect(collection).toBeEqual ['d', 'e', 'f']

             @it 'inner it fifth', ->
               expect(func).toBeUndefined() # bug
-              # expect(func).toBeDefined() # should be
-              expect(obj).toBeEqual {one: 'test', two: ['one', 'two', 'three']} # bug
-              # expect(obj).toBeEqual {one: 'test'} # should be
-              expect(arr).toBeEqual ['a', 'b', 'c', 'one', 'd'] # bug
-              # expect(arr).toBeEqual ['a', 'b', 'c', 'd'] # should be
-              expect(subject).toBeEqual 5 # bug
-              # expect(subject).toBeEqual 4 # should be
+              expect(obj).toBeEqual {one: 'test'}
+              expect(arr).toBeEqual ['a', 'b', 'c', 'd']
+              expect(subject).toBeEqual 4
               expect(collection).toBeEqual ['d', 'e', 'f']

             @it 'inner it sixth', ->
               expect(func).toBeUndefined() # bug
-              # expect(func).toBeDefined() # should be
-              expect(obj).toBeEqual {one: 'test', two: ['one', 'two', 'three']} # bug
-              # expect(obj).toBeEqual {one: 'test'} # should be
-              expect(arr).toBeEqual ['a', 'b', 'c', 'one', 'd'] # bug
-              # expect(arr).toBeEqual ['a', 'b', 'c', 'd'] # should be
-              expect(subject).toBeEqual 5 # bug
-              # expect(subject).toBeEqual 4 # should be
+              expect(obj).toBeEqual {one: 'test'}
+              expect(arr).toBeEqual ['a', 'b', 'c', 'd']
+              expect(subject).toBeEqual 4
               expect(collection).toBeEqual ['d', 'e', 'f']
-
-        #     JE.afterEach ->
-        #       expect(func).toBeDefined()
-        #       expect(func).toBeAFunction()
-        #       expect(obj).toBeEqual {one: 'test'}
-        #       expect(arr).toBeEqual ['a', 'b', 'c', 'd']
-        #       expect(subject).toBeEqual 4
-        #       expect(collection).toBeEqual ['d', 'e', 'f']

           @describe 'inner_fourth', ->
             collection.is ['e', 'f', 'j']

             JE.beforeEach ->
               expect(func).toBeUndefined() # bug
-              # expect(func).toBeDefined() # should be
-              expect(obj).toBeEqual {one: 'test', two: ['one', 'two', 'three']} # bug
-              # expect(obj).toBeEqual {one: 'test'} # should be
-              expect(arr).toBeEqual ['a', 'b', 'c', 'one', 'd', 'e'] # bug
-              # expect(arr).toBeEqual ['a', 'b', 'c', 'e'] # should be
-              expect(subject).toBeEqual 6 #bug
-              # expect(subject).toBeEqual 4 # should be
+              expect(obj).toBeEqual {one: 'test'}
+              expect(arr).toBeEqual ['a', 'b', 'c', 'e']
+              expect(subject).toBeEqual 4
               expect(collection).toBeEqual ['e', 'f', 'j']

             @it 'inner it seventh', ->
               expect(func).toBeUndefined() # bug
-              # expect(func).toBeDefined() # should be
-              expect(obj).toBeEqual {one: 'test', two: ['one', 'two', 'three']} # bug
-              # expect(obj).toBeEqual {one: 'test'} # should be
-              expect(arr).toBeEqual ['a', 'b', 'c', 'one', 'd', 'e'] # bug
-              # expect(arr).toBeEqual ['a', 'b', 'c', 'e'] # should be
-              expect(subject).toBeEqual 6 #bug
-              # expect(subject).toBeEqual 4 # should be
+              expect(obj).toBeEqual {one: 'test'}
+              expect(arr).toBeEqual ['a', 'b', 'c', 'e']
+              expect(subject).toBeEqual 4
               expect(collection).toBeEqual ['e', 'f', 'j']

             @it 'inner it eighth', ->
               expect(func).toBeUndefined() # bug
-              # expect(func).toBeDefined() # should be
-              expect(obj).toBeEqual {one: 'test', two: ['one', 'two', 'three']} # bug
-              # expect(obj).toBeEqual {one: 'test'} # should be
-              expect(arr).toBeEqual ['a', 'b', 'c', 'one', 'd', 'e'] # bug
-              # expect(arr).toBeEqual ['a', 'b', 'c', 'e'] # should be
-              expect(subject).toBeEqual 6 #bug
-              # expect(subject).toBeEqual 4 # should be
+              expect(obj).toBeEqual {one: 'test'}
+              expect(arr).toBeEqual ['a', 'b', 'c', 'e']
+              expect(subject).toBeEqual 4
               expect(collection).toBeEqual ['e', 'f', 'j']
-
-        #     JE.afterEach ->
-        #       expect(func).toBeDefined()
-        #       expect(func).toBeAFunction()
-        #       expect(obj).toBeEqual {one: 'test'}
-        #       expect(arr).toBeEqual ['a', 'b', 'c', 'e']
-        #       expect(subject).toBeEqual 4
-        #       expect(collection).toBeEqual ['e', 'f', 'j']

       context.describe 'outer_second', ->
         subject.is {one: one, two: two}
@@ -325,10 +248,6 @@
           expect(subject).toBeUndefined()
           expect(arr).toBeEqual [1, 2]

-        # JE.afterEach ->
-        #   expect(subject).toBeUndefined()
-        #   expect(arr).toBeEqual [1, 2]
-
         @describe 'middle_third', ->
           one.is 'one'

@@ -347,11 +266,6 @@
             expect(one).toBeEqual 'one'
             expect(arr).toBeEqual [1, 2]

-          # JE.afterEach ->
-          #   expect(subject).toBeUndefined()
-          #   expect(one).toBeEqual 'one'
-          #   expect(arr).toBeEqual [1, 2]
-
           @describe 'inner_fifth', ->
             two.is arr[1]

@@ -373,12 +287,6 @@
               expect(arr).toBeEqual [1, 2]
               expect(subject).toBeEqual {one: 'one', two: 2}

-            # JE.afterEach ->
-            #   expect(one).toBeEqual 'one'
-            #   expect(two).toBeEqual 2
-            #   expect(arr).toBeEqual [1, 2]
-            #   expect(subject).toBeEqual {one: 'one', two: 2}
-
           @describe 'inner_sixth', ->
             two.is 'two'

@@ -400,37 +308,23 @@
               expect(arr).toBeEqual [1, 2]
               expect(subject).toBeEqual {one: 'one', two: 'two'}

-      #       JE.afterEach ->
-      #         expect(one).toBeEqual 'one'
-      #         expect(two).toBeEqual 'two'
-      #         expect(arr).toBeEqual [1, 2]
-      #         expect(subject).toBeEqual {one: 'one', two: 'two'}
-
         @describe 'middle_fourth', ->
           one.is 1

           JE.beforeEach ->
-            expect(subject).toBeEqual {one: 1, two: 'two'} # bug
-            # expect(subject).toBeUndefined() # should be
+            expect(subject).toBeUndefined() # should be
             expect(one).toBeEqual 1
             expect(arr).toBeEqual [1, 2]

           @it 'middle it seventh', ->
-            expect(subject).toBeEqual {one: 1, two: 'two'} # bug
-            # expect(subject).toBeUndefined() # should be
+            expect(subject).toBeUndefined() # should be
             expect(one).toBeEqual 1
             expect(arr).toBeEqual [1, 2]

           @it 'middle it eighth', ->
-            expect(subject).toBeEqual {one: 1, two: 'two'} # bug
-            # expect(subject).toBeUndefined() # should be
+            expect(subject).toBeUndefined() # should be
             expect(one).toBeEqual 1
             expect(arr).toBeEqual [1, 2]
-
-      #     JE.afterEach ->
-      #       expect(subject).toBeUndefined()
-      #       expect(one).toBeEqual 1
-      #       expect(arr).toBeEqual [1, 2]

           @describe 'inner_seventh', ->
             two.is arr[1]
@@ -453,12 +347,6 @@
               expect(arr).toBeEqual [1, 2]
               expect(subject).toBeEqual {one: 1, two: 2}

-      #       JE.afterEach ->
-      #         expect(one).toBeEqual 1
-      #         expect(two).toBeEqual 2
-      #         expect(arr).toBeEqual [1, 2]
-      #         expect(subject).toBeEqual {one: 1, two: 2}
-
           @describe 'inner_eighth', ->
             two.is true

@@ -479,12 +367,6 @@
               expect(two).toBeEqual true
               expect(arr).toBeEqual [1, 2]
               expect(subject).toBeEqual {one: 1, two: true}
-
-      #       JE.afterEach ->
-      #         expect(one).toBeEqual 1
-      #         expect(two).toBeEqual true
-      #         expect(arr).toBeEqual [1, 2]
-      #         expect(subject).toBeEqual {one: 1, two: true}

       JE.run(context)


Ignore any cache building errors

Ignore any cache building errors

--- src/install.coffee
+++ src/install.coffee
@@ -394,8 +394,9 @@
     packageDirectory = path.join(@atomPackagesDirectory, packageName)

     config.getResourcePath (resourcePath) ->
-      ModuleCache = require(path.join(resourcePath, 'src', 'module-cache'))
-      ModuleCache.create(packageDirectory)
+      try
+        ModuleCache = require(path.join(resourcePath, 'src', 'module-cache'))
+        ModuleCache.create(packageDirectory)
       callback()

   isBundledPackage: (packageName, callback) ->


:lipstick:

:lipstick:

--- src/install.coffee
+++ src/install.coffee
@@ -352,8 +352,8 @@

       fs.removeSync(path.resolve(__dirname, '..', 'native-module', 'build'))

-      @fork @atomNpmPath, buildArgs, buildOptions, (code, stderr, stdout) =>
-        @logCommandResults(callback, code, stderr, stdout)
+      @fork @atomNpmPath, buildArgs, buildOptions, (args...) =>
+        @logCommandResults(callback, args...)

   run: (options) ->
     {callback} = options


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/engine_selector.coffee
+++ test/engine_selector.coffee
@@ -10,6 +10,7 @@

   engine.add
     class: "Awesome"
+    x:

 test "#find", ->
   engine = Engine()


cloning a book keeps the overridden title (or original if it was not overridden)

--- scripts/gh-book/toc-node.coffee
+++ scripts/gh-book/toc-node.coffee
@@ -56,8 +56,11 @@
       modelRoot = model.getRoot?() # Case of dropping a book onto a folder... `or model`

       if root and modelRoot and root != modelRoot
+        # Use `.toJSON().title` instead of `.get('title')` to support
+        # TocPointerNodes which inherit their title if it is not overridden
+        title = model.toJSON().title or 'Untitled'
+
         # If it is a pointer then dereference it
-        title = model.get('title')
         realModel = model.dereferencePointer?() or model

         # At this point realModel can be a XhtmlFile or a TocNode (section).


(#223) Remember preview window position

(#223) Remember preview window position

--- lib/viewer.coffee
+++ lib/viewer.coffee
@@ -51,7 +51,9 @@
       @latex.viewer.focusMain()

   focusViewer: ->
-    @window.show() if @window? and !@window.isDestroyed()
+    if @window? and !@window.isDestroyed()
+      @window.setBounds(@window.getBounds())
+      @window.focus()

   focusMain: ->
     @self.focus() if @self? and !@self.focused


bind bug

bind bug

--- lib/worker.coffee
+++ lib/worker.coffee
@@ -146,17 +146,17 @@
   # helper fns exposed to worker function
   class WorkerHelper extends EventEmitter
     constructor: (@parent, @handle) ->
-    warning: (warning) -> @parent.sendCommand 'WORK_WARNING', @handle, warning
-    status: (num, den) -> @parent.sendCommand 'WORK_STATUS', @handle, num, den
-    data: (data)       -> @parent.sendCommand 'WORK_DATA', @handle, data
-    error: (warning) ->
+    warning: (warning) => @parent.sendCommand 'WORK_WARNING', @handle, warning
+    status: (num, den) => @parent.sendCommand 'WORK_STATUS', @handle, num, den
+    data: (data)       => @parent.sendCommand 'WORK_DATA', @handle, data
+    error: (warning) =>
       @warning warning if warning?
       @parent.sendCommand 'WORK_FAIL', @handle
       @parent.sendCommand 'GRAB_JOB'
-    complete: (data) ->
+    complete: (data) =>
       @parent.sendCommand 'WORK_COMPLETE', @handle, data
       @parent.sendCommand 'GRAB_JOB'
-    done: (err) ->
+    done: (err) =>
       if err?
         @error(err)
       else


fixed most things! added ignore pattern

fixed most things! added ignore pattern

--- src/marktab.coffee
+++ src/marktab.coffee
@@ -7,8 +7,8 @@
 		4: "D"
 		5: "A"
 		6: "E"
-	notePattern = /[0-9]:[0-9]/
-	singleNotePattern = /[0-9]/
+	notePattern = /[0-9]+:[0-9]+/
+	singleNotePattern = /[0-9]+/
 	restPattern = /r/
 	hammerPattern = /h/
 	pullOffPattern = /p/
@@ -16,6 +16,7 @@
 	slideDownPattern = /\\/
 	chordPattern = /\([0-9\s:]+\)/
 	riffPattern = /\[.*\]/
+	ignorePattern = /[\s\n]/

 	constructor: (@lines = [], @stringNames = stringNameDefaults) ->
 		# @lines contains an array of parsed lines, ready to be output
@@ -28,57 +29,71 @@
 		while i < input.length
 			part = input.substr(i, input.length-i)# get rest of line
 			tabMapPart = {}
-			if part.search(chordPattern) is 0
+			if part.search(ignorePattern) is 0
+				# ignore
+				part = part.match(ignorePattern)[0]
+				i += part.length
+				continue
+			else if part.search(chordPattern) is 0
 				# chord
-				i += part.match(chordPattern).length
+				part = part.match(chordPattern)[0]
+				i += part.length
 				tabMapPart = this.parseChord(part)
 			else if part.search(notePattern) is 0
 				# note
-				i += part.match(notePattern).length
+				part = part.match(notePattern)[0]
+				i += part.length
 				tabMapPart = this.parseNotes(part)
 				lastString = parseInt(_.keys(tabMapPart), 10)
 			else if part.search(restPattern) is 0
 				# rest
-				i += part.match(restPattern).length
-				tabMapPart = {1: [undefined]}
+				part = part.match(restPattern)[0]
+				i += part.length
+				tabMapPart[lastString || 1] = [undefined]
 			else if part.search(hammerPattern) is 0
 				# hammer-on
 				if !lastString
 					throw "invalid hammer-on"
-				i += part.match(hammerPattern).length
+				part = part.match(hammerPattern)[0]
+				i += part.length
 				tabMapPart[lastString] = []
 				tabMapPart[lastString][i] = "h"
 			else if part.search(pullOffPattern) is 0
 				# pull-off
 				if !lastString
 					throw "invalid pull-off"
-				i += part.match(pullOffPattern).length
+				part = part.match(pullOffPattern)[0]
+				i += part.length
 				tabMapPart[lastString] = []
 				tabMapPart[lastString][i] = "p"
 			else if part.search(slideUpPattern) is 0
 				# slide-up
 				if !lastString
 					throw "invalid slide-up"
-				i += part.match(sliceUpPattern).length
+				part = part.match(slideUpPattern)[0]
+				i += part.length
 				tabMapPart[lastString] = []
 				tabMapPart[lastString][i] = "/"
 			else if part.search(slideDownPattern) is 0
 				# slide-down
 				if !lastString
 					throw "invalid slide-down"
-				i += part.match(slideDownPattern).length
+				part = part.match(slideDownPattern)[0]
+				i += part.length
 				tabMapPart[lastString] = []
 				tabMapPart[lastString][i] = "\\"
 			else if part.search(singleNotePattern) is 0
 				# single note
 				if !lastString
 					throw "invalid single note"
-				i += part.match(singleNotePattern).length
+				part = part.match(singleNotePattern)[0]
+				i += part.length
 				tabMapPart[lastString] = []
 				tabMapPart[lastString][i] = parseInt(part, 10)
 			else if part.search(riffPattern) is 0
 				# riff
-				i += part.match(riffPattern).length
+				part = part.match(riffPattern)[0]
+				i += part.length
 				tabMapPart = this.parseRiff(part)
 				# this.mergeTabMaps(tabMap, tabMapPart)
 				# continue
@@ -132,7 +147,6 @@
 	# parses marktab note into a single tabMap frame
 	# example: parseNotes("5:6") => { 5: [6] }
 	parseNotes: (note) ->
-		console.log(note)
 		result = {}
 		stringAndFret = note.split(":")
 		string = stringAndFret[0]
@@ -144,7 +158,6 @@
 	# parses marktab chords into tabMap
 	# example: parseChord("(6:8 5:6)") => { 5:[6], 6:[8] }
 	parseChord: (chord) ->
-		console.log(chord)
 		result = {}
 		notesLine = chord.substr(1, chord.length-2)# remove parenthesis
 		notes = notesLine.split(" ")


Fix Backbone.Router braindamage.

Fix Backbone.Router braindamage.

--- templates/default-layout.coffee
+++ templates/default-layout.coffee
@@ -145,7 +145,8 @@
             dataType: 'json',
             contentType: 'application/json'
         d.done (data) ->
-            router.navigate data.self, trigger: true
+            history.pushState {}, '', data.self
+            Backbone.history.loadUrl()

 class AppView extends Backbone.View


refactor MainLadderView

refactor MainLadderView

--- app/views/ladder/MainLadderView.coffee
+++ app/views/ladder/MainLadderView.coffee
@@ -15,14 +15,15 @@
   id: 'main-ladder-view'
   template: template

-  constructor: (options) ->
-    super options
-    @levelStatusMap = {}
-    @levelPlayCountMap = {}
+  initialize: ->
+    @levelStatusMap = []
+    @levelPlayCountMap = []
+    @campaigns = campaigns
+
     @sessions = @supermodel.loadCollection(new LevelSessionsCollection(), 'your_sessions', {cache: false}, 0).model
-    @listenToOnce @sessions, 'sync', @onSessionsLoaded
+    @listenToOnce @sessions, 'sync', @onSessionsLoaded
+
     @getLevelPlayCounts()
-    @campaigns = campaigns

   onSessionsLoaded: (e) ->
     for session in @sessions.models


Zero index line and column numbers

Zero index line and column numbers

--- lib/link-paths.coffee
+++ lib/link-paths.coffee
@@ -8,10 +8,10 @@
   parentView.on 'click', '.-linked-path', (event) ->
     el = this
     {path, line, column} = el.dataset
-    line = Number(line)
-    column = Number(column)
+    line = Number(line) - 1
+    column = Number(column) - 1

     atom.workspace.open path, {
       initialLine: line
       initialColumn: column
-      }
+    }


Finished pending manifest test

Finished pending manifest test

By making it full change git URL of a the tool in an
update. Seems to work well.

--- test/integration/api.coffee
+++ test/integration/api.coffee
@@ -203,7 +203,8 @@
                 form:
                   name: @toolName
                   type: 'view'
-                  gitUrl: 'git://github.com/scraperwiki/datatables-view-tool.git'
+                  # note this is a totally new URL for the code!
+                  gitUrl: 'https://github.com/scraperwiki/magic-summary-tool'
               , (err, res) =>
                 @response = res
                 @tool = parseJSON res.body
@@ -220,10 +221,8 @@
               should.exist @tool.updated
               @tool.updated.should.be.above @tool.created

-            # We should check whether the manifest has been updated,
-            # but it's hard.
-            xit 'returns the updated tool', ->
-              @tool.manifest.displayName.should.equal 'View in a table'
+            it 'has updated display name from the manifest', ->
+              @tool.manifest.displayName.should.equal 'Summarise this data'

         context 'When I create a private tool', ->
           before (done) ->


Removed condition that hides "User left message" in channels

--- server/methods/leaveRoom.coffee
+++ server/methods/leaveRoom.coffee
@@ -13,9 +13,8 @@

 		RocketChat.models.Rooms.removeUsernameById rid, user.username

-		if room.t isnt 'c' and room.usernames.indexOf(user.username) isnt -1
+		if room.usernames.indexOf(user.username) isnt -1
 			removedUser = user
-
 			RocketChat.models.Messages.createUserLeaveWithRoomIdAndUser rid, removedUser

 		if room.t is 'l'


Revert "test modified copy-to-clipboard"

This reverts commit 8c44a9f38a1db90eb1d07d319d5a780cc7a26f61.

--- review_front/app/components/copy-to-clipboard.coffee
+++ review_front/app/components/copy-to-clipboard.coffee
@@ -1,35 +1,19 @@
 `import Ember from 'ember'`
+`import ZeroClipboard from 'ember-cli-zero-clipboard/components/zero-clipboard'`

-CopyToClipboard = Ember.Component.extend
-  attributeBindings: [
-    'title'
-    'data-clipboard-text'
-    'data-clipboard-target'
-  ]
-  title: 'Copy to clipboard'
+CopyToClipboard = ZeroClipboard.extend
   tagName: 'button'
   classNames: ['btn', 'btn-default', 'btn-xs', 'copy-to-clipboard']
   justCopied: false

   justCopiedToggle: ->
     @set 'justCopied', !@justCopied
-  didInsertElement: ->
-    client = new ZeroClipboard(@get('element'))
-    #bind aftercopy to an ember event
-    client.on 'aftercopy', ((event) ->
+
+  actions:
+    afterCopy: ->
       @justCopiedToggle()
       Ember.run.later @, (->
         @justCopiedToggle()
       ), 1500
-      return
-    ).bind(this)
-    return
-  'data-clipboard-text': (->
-    @get 'text'
-  ).property('text')
-  'data-clipboard-target': (->
-    @get 'cbTarget'
-  ).property('cbTarget')
-

 `export default CopyToClipboard`


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/function_extensions.coffee
+++ test/function_extensions.coffee
@@ -25,7 +25,7 @@
   score = 0

   addScore = ->
-    score +=
+    score += 100

   onceScore = ->
     ( ->


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -27,7 +27,7 @@

 someOtherObject.meter 'turbo'
 # => Sets up a turbo meter that will be drawn during the someOtherObject overlay event.
-# Since neither turbo maxTurbo wasn't provided, it is set to the value of I.health (500)
+# Since neither turbo maxTurbo were provided, it is set to the value of I.health (500)

 # now player has all the methods provided by this module


remove global var; full on recursion

remove global var; full on recursion

--- ccss.coffee
+++ ccss.coffee
@@ -1,6 +1,6 @@
-css = ''
+@compile = (ccss) ->
+  css = ''

-compile = (ccss) ->
   for selector, pairs of ccss
     # a pair can be a css declaration, or a pair of the child ccss object
     child = {}
@@ -20,10 +20,6 @@
       css += declarations
       css += '}\n'

-    compile child
+    css += @compile child

-@compile = (ccss) ->
-  compile ccss
-  ret = css
-  css = ''
-  ret
+  css


refactor panel/view

refactor panel/view

--- lib/panel/view.coffee
+++ lib/panel/view.coffee
@@ -7,11 +7,11 @@
 HIDE = 0
 OUTPUT = 1
 QUERY = 2
-IM = 3

 class PanelView extends View

     mode: HIDE
+    IM: false

     @content: ->
         @div outlet: 'agdaPanel', class: 'agda-panel tool-panel panel-bottom', =>
@@ -36,15 +36,27 @@
     #   Modes
     #

+    switchMode: (mode, callback) ->
+        if mode isnt @mode
+            log 'Panel', "mode: #{@mode} => #{mode}"
+            switch mode
+                when HIDE
+                    @hide()
+                when OUTPUT
+                    @show()
+                    @content.show()
+                    @inputBox.hide()
+                when QUERY
+                    @show()
+                    @content.hide()
+                    @inputBox.show()
+                else
+            callback?()
+            @mode = mode
+
+
     query: ->
-        if @mode isnt QUERY
-            @mode = QUERY
-
-            log 'Panel', "query mode"
-            @show()
-            @content.hide()
-            @inputBox.show()
-
+        @switchMode QUERY, =>
             @inputBox.focus()
             @promise = Q.Promise (resolve, reject, notify) =>
                 # confirm
@@ -55,28 +67,21 @@
         return @

     output: ->
-        if @mode isnt OUTPUT
-            @mode = OUTPUT
-            log 'Panel', "output mode"
-            @show()
-            @content.show()
-            @inputBox.hide()
+        @switchMode OUTPUT
         return @

     activateIM: ->
-        if @mode isnt IM
-            @mode = IM
-            log 'Panel', "IM mode on"
-            @show()
+        if not @IM
+            @IM = true
+            log 'Panel', "IM on"
             @title.hide()
             @inputMethod.show()
         return @

     deactivateIM: ->
-        if @mode is IM
-            @mode = OUTPUT
-            log 'Panel', "IM mode off"
-            @show()
+        if @IM
+            @IM = false
+            log 'Panel', "IM off"
             @title.show()
             @inputMethod.hide()
         return @


escape strings before presenting them

escape strings before presenting them

--- lib/panel/view.coffee
+++ lib/panel/view.coffee
@@ -2,6 +2,7 @@
 {log, warn, error} = require '../logger'

 Q = require 'Q'
+_ = require 'lodash'

 UNINIT = 0
 HIDE = 1
@@ -93,6 +94,7 @@

     # title
     setTitle: (content, type) ->
+        content = _.escape content
         @title.text content
         if type
           @title.attr 'class', 'text-' + type
@@ -109,6 +111,7 @@

     # placeholder of the inputbox of query mode
     setPlaceholder: (content) ->
+        content = _.escape content
         @inputBox.editor.placeholderText = content
         return @

@@ -118,6 +121,7 @@
         return @

     setContent: (content) ->
+        content = content.map (s) => _.escape s
         @clearContent()

         if content.length > 0
@@ -144,6 +148,7 @@
         return @

     appendContent: (content) ->
+        content = content.map (s) => _.escape s
         @body.show()
         for item in content
             @contentList.append "<li class: 'list-item'>#{item}</li>"


suppr key is pressed on last message : Select Previous Message

--- client/app/utils/api_utils.coffee
+++ client/app/utils/api_utils.coffee
@@ -165,6 +165,7 @@
             # Get next message information
             # before delete (context changes)
             next = MessageStore.getPreviousConversation()
+            next = MessageStore.getNextConversation() unless next.size

             MessageActionCreator.delete {messageID}
             LayoutActionCreator.hideModal() if isModal


remove code

remove code

--- client/code/view/tool/tile.coffee
+++ client/code/view/tool/tile.coffee
@@ -72,23 +72,6 @@
     @showLoading()
     @createDataset()

-  createDataset: ->
-    dataset = Cu.Model.Dataset.findOrCreate
-      displayName: @model.get('manifest').displayName
-      tool: @model
-    app.datasets().add dataset
-    dataset.new = true
-    dataset.save {},
-      wait: true
-      success: ->
-        delete dataset.new
-        window.app.navigate "/dataset/#{dataset.id}/settings", {trigger: true}
-        $('#chooser').fadeOut 200, ->
-          $(this).remove()
-      error: (model, xhr, options) ->
-        @active = false
-        console.warn "Error creating dataset (xhr status: #{xhr.status} #{xhr.statusText})"
-
   # TODO: DRY with RPC call
   createDataset: ->
     dataset = Cu.Model.Dataset.findOrCreate


fill crash-report view with data from db

--- client/coffee/crash_report.coffee
+++ client/coffee/crash_report.coffee
@@ -22,21 +22,13 @@
 ## Module Globals
 $p = {}

-deepcopy = (obj) ->
-    return obj if (typeof obj) != 'object'
-
-    cp = {}
-    for k,v of obj
-        cp[k] = deepcopy v
-    return cp
-
 initialize_application = () ->
     frag = parse_fragment()
     if not frag?
         window.location = "http://" + window.location.host #redirect to index
         #TODO: redirect to search
     else
-        console.log "frag=#{frag}" #debug
+        #console.log "frag=#{frag}" #debug
         clear_crashreport()
         load_crashreport_data frag, (data) ->
             #TODO: add error handling
@@ -57,8 +49,27 @@
 clear_crashreport = () ->
     #TODO: clear crashreport data from layout

+write_link = (dom, text, link) ->
+    $dom = $(dom).find('a')
+    #TODO: add link tag if not exist
+    $dom.text text
+    $dom.attr "href", link
+
 render_crashreport = (data) ->
-    #TODO: write crashreport data to layout
+    #Overview
+    write_link '#overview_application', "NA", ""
+    write_link '#overview_executable' , "NA", ""
+    write_link '#overview_application', "NA", ""
+
+    $('#overview_date').text "NA"
+    $('#overview_upload_notes').text "-"
+    $('#overview_core_notes').text "-"
+
+    #Version
+    write_link '#version_build'  ,data.build  ,""
+    write_link '#version_product',data.product,""
+    write_link '#version_week'   ,""          ,""
+

 $ () ->
     CFInstall?.check()


safe from manual call

safe from manual call

--- lib/proto-repl.coffee
+++ lib/proto-repl.coffee
@@ -753,4 +753,4 @@
                 @stderr("Error trying to open: #{result.error}")

   remoteNreplFocusNext: ->
-    @connectionView.toggleFocus()
+    @connectionView ? @connectionView.toggleFocus()


:lipstick: Use in instead of indexOf

:lipstick: Use in instead of indexOf

--- src/pattern.coffee
+++ src/pattern.coffee
@@ -47,7 +47,7 @@
     return false unless @regexSource
     escape = false
     for character in @regexSource
-      return true if escape and 'AGz'.indexOf(character) isnt -1
+      return true if escape and character in ['A', 'G', 'z']
       escape = not escape and character is '\\'
     false


don't reset cursor on change

don't reset cursor on change

--- src/payform.coffee
+++ src/payform.coffee
@@ -151,7 +151,7 @@
       target = e.target or e.srcElement
       cursor = target.selectionStart
       target.value = payform.formatCardNumber(target.value)
-      if cursor?
+      if cursor? and e.type isnt 'change'
         target.setSelectionRange(cursor, cursor)

   formatCardNumber = (e) ->
@@ -213,7 +213,7 @@
       target = e.target or e.srcElement
       cursor = target.selectionStart
       target.value = payform.formatCardExpiry(target.value)
-      if cursor?
+      if cursor? and e.type isnt 'change'
         target.setSelectionRange(cursor, cursor)

   formatCardExpiry = (e) ->
@@ -274,7 +274,7 @@
       target = e.target or e.srcElement
       cursor = target.selectionStart
       target.value = target.value.replace(/\D/g, '')[0...4]
-      if cursor?
+      if cursor? and e.type isnt 'change'
         target.setSelectionRange(cursor, cursor)

   # Restrictions


Removing prefix `user@key` from url

Removing prefix `user@key` from url

--- tests/www/run_sauce_labs.coffee
+++ tests/www/run_sauce_labs.coffee
@@ -4,7 +4,8 @@
   username: user = process.env.SAUCE_USERNAME
   accessKey: key = process.env.SAUCE_ACCESS_KEY

-base_url = "http://#{user}:#{key}@localhost:8080"
+# base_url = "http://#{user}:#{key}@localhost:8080"
+base_url = "http://localhost:8080"
 mark_as_passed = (require './utils/mark-as-passed').config user, key

 (require './run').test 'sauce labs', conf, base_url, mark_as_passed


adjust arc epsilon to a more reasonable value. fixes #7

--- src/plotter.coffee
+++ src/plotter.coffee
@@ -6,13 +6,14 @@
 Macro = require './macro-tool'
 # standard tool functions
 tool = require './standard-tool'
+# coordinate scale factor
+coordFactor = require('./svg-coord').factor
+

 # constants
 HALF_PI = Math.PI/2
 THREEHALF_PI = 3*HALF_PI
 TWO_PI = 2*Math.PI
-# error epsilon
-arcEps = 0.0000001
 # assumed units
 ASSUMED_UNITS = 'in'

@@ -378,9 +379,10 @@

   # draw an arc with the start point, end point, and center offset
   drawArc: (sx, sy, ex, ey, i, j) ->
-    # use a seriously low epsilon constant
-    # this value is too small and causing problems. re-evaluate
-    arcEps = 1.01 * 10**-( (@parser?.format.places[1] ? 6 ) - 1 )
+    # lets try this for arc point comparison epsilon
+    # this value seems strict enough to prevent invalid arcs but forgiving
+    # enough to let most gerbers draw
+    arcEps = 1.5 * coordFactor * 10**-(@parser?.format.places[1] ? 7)
     t = @tools[@currentTool]
     # throw an error if the tool is rectangular
     if not @region and not t.trace['stroke-width']


Call getValues() when iterating over buffers

--- src/project.coffee
+++ src/project.coffee
@@ -300,7 +300,7 @@
   replace: (regex, replacementText, filePaths, iterator) ->
     deferred = Q.defer()

-    openPaths = (buffer.getPath() for buffer in @buffers)
+    openPaths = (buffer.getPath() for buffer in @buffers.getValues())
     outOfProcessPaths = _.difference(filePaths, openPaths)

     inProcessFinished = !openPaths.length
@@ -318,7 +318,7 @@

       task.on 'replace:path-replaced', iterator

-    for buffer in @buffers
+    for buffer in @buffers.getValues()
       replacements = buffer.replace(regex, replacementText, iterator)
       iterator({filePath: buffer.getPath(), replacements}) if replacements


Fix regex

Fix regex


Created missing view for non admin users.

--- client/landing/app/Applications/Activity.kdapplication/views/activitylistheader.coffee
+++ client/landing/app/Applications/Activity.kdapplication/views/activitylistheader.coffee
@@ -41,6 +41,8 @@

     else
       @lowQualitySwitch = new KDCustomHTMLView
+      @refreshLink      = new KDCustomHTMLView
+        tagName: "span"

     @appStorage.fetchStorage (storage)=>
       state = @appStorage.getValue('liveUpdates') or off


added date generated to templates

added date generated to templates

--- src/reports.coffee
+++ src/reports.coffee
@@ -134,7 +134,7 @@
   User.find { weeklyReport: true }, callback

 plainTemplate = (report) ->
-  text = ''
+  text = "Generated on: #{new Date().toString()}"
   for data in report.data
     do (data) ->
       text += " \r\n \r\n <---------- Start Channel  #{data.channel.name} ---------------------------> \r\n \r\n
@@ -160,6 +160,7 @@

#{report.type} OpenHIM Transactions Summary

on the OpenHIM instance running on #{config.alerts.himInstance}:

+
Generated on: #{new Date().toString()}

       Channel Name


fix test.

fix test.

--- test/unit/model/plan.coffee
+++ test/unit/model/plan.coffee
@@ -14,6 +14,7 @@

   describe 'Can set quota of a box', ->
     before (done) ->
+      process.env.CU_QUOTA_SERVER = 'testy'
       @request = sinon.stub request, 'post', (opt, cb) ->
         cb null, null, null


Direct users to getting started page on first login

--- client/views/signIn/signIn.coffee
+++ client/views/signIn/signIn.coffee
@@ -45,6 +45,9 @@
         console.log("error on login", error)
         Session.set('entryError', T9n.get(error.reason))
         #T9NHelper.accountsError error
+      else if not Meteor.user().profile?.onboarding?.gettingStarted
+        Router.go "/docs/getting-started.html"
+        Meteor.users.update(Meteor.user()._id, {$set: {"profile.onboarding.gettingStarted": true}})
       else if Session.get('fromWhere')
         Router.go Session.get('fromWhere')
         Session.set('fromWhere', undefined)


Fix username only and forgot password stuff.  Not sure how this test ever passed before.

--- client/views/signIn/signIn.coffee
+++ client/views/signIn/signIn.coffee
@@ -22,7 +22,7 @@
     AccountsEntry.settings.logo

   isUsernameOnly: ->
-    return AccountsEntry.settings.passwordSignupFields == t9n("username")
+    return AccountsEntry.settings.passwordSignupFields == 'USERNAME_ONLY'

 }


fixes manual test file system mocking

fixes manual test file system mocking

--- tests/run_manual_testing.coffee
+++ tests/run_manual_testing.coffee
@@ -14,6 +14,7 @@
 spa = require("../lib")

 snapshot_0 = ->
+    mock.restore()
     system = {}
     utils.mount(system, path.resolve(__dirname, "./testing_assets"))
     utils.mount(system, path.resolve(__dirname, "../lib/assets"))
@@ -22,6 +23,7 @@
     mock(system)

 snapshot_1 = ->
+    mock.restore()
     system = yaml.safeLoad("""
         /app:
             d.js: |
@@ -68,6 +70,7 @@
     mock(system)

 snapshot_2 = ->
+    mock.restore()
     system = yaml.safeLoad("""
         /app:
             d.js: |
@@ -108,6 +111,7 @@
     mock(system)

 snapshot_3 = ->
+    mock.restore()
     system = yaml.safeLoad("""
         /app:
             spa.yaml: |


Switch to main branch of marked and monkey patch to resolve url.

--- src/plugins/markdown-page.coffee
+++ src/plugins/markdown-page.coffee
@@ -8,19 +8,18 @@

 Page = require './page'

-is_relative = (uri) ->
-  ### returns true if *uri* is relative; otherwise false ###
-  (url.parse(uri).protocol == undefined)
+# monkeypatch to add url resolving to marked
+marked.InlineLexer.prototype._outputLink = marked.InlineLexer.prototype.outputLink
+marked.InlineLexer.prototype._resolveLink = (href) -> href
+marked.InlineLexer.prototype.outputLink = (cap, link) ->
+  link.href = @_resolveLink link.href
+  return @_outputLink cap, link

 parseMarkdownSync = (content, baseUrl) ->
-  ### takes markdown *content* and returns html using *baseUrl* for any relative urls
-      returns html ###
+  ### Parse markdown *content* and resolve links using *baseUrl*, returns html. ###

-  marked.inlineLexer.formatUrl = (uri) ->
-    if is_relative uri
-      return url.resolve baseUrl, uri
-    else
-      return uri
+  marked.InlineLexer.prototype._resolveLink = (uri) ->
+    url.resolve baseUrl, uri

   tokens = marked.lexer content

@@ -64,7 +63,7 @@
       callback null, yaml.load(source) or {}
     catch error
       callback error
-
+
   # split metadata and markdown content

   if content[0...3] is '---'


Fixed scope of monitor method call

Fixed scope of monitor method call

--- models/App.coffee
+++ models/App.coffee
@@ -136,7 +136,7 @@

 			# Delay monitoring to allow for startup time.
 			@stayOn = false
-			setTimeout ->
+			setTimeout =>
 				@stayOn = true
 				@monitor()
 			, STARTUP_GRACE_PERIOD


Mark commit as processed after the try catch block in Commit Publisher

Thanks @qejk !

--- source/server/infrastructure/commit_publisher.coffee
+++ source/server/infrastructure/commit_publisher.coffee
@@ -45,13 +45,13 @@
       for command in commit.changes.commands
         @log.info @_logMsg("sending #{command.typeName()}"), command
         @commandBus.send command
-      @_markAsProcessed(commit)
     catch error
       @_failCommitProcessingAttempt(commit._id)
       throw new Error "while publishing:\n
         #{JSON.stringify(commit)}\n
         error:#{error.message}\n
         stack:#{error.stack}"
+    @_markAsProcessed(commit)

   _setProcessingTimeout: (commit) ->
     @_inProgress[commit._id] = @meteor.setTimeout (=>


fixed case incensitive error when checking api limit

* github error message is changed

--- src/service.coffee
+++ src/service.coffee
@@ -101,15 +101,15 @@
                     urls.forEach (url) ->
                       timeline.getCommitInfo url, (err, commit) ->
                         if err?
-                          logger.error 'getCommitInfo: ', {err: err, limit: /^API Rate Limit Exceeded/.test(err.message), isCompleted: isCompleted, processCount: processCount}
-                          if /^API Rate Limit Exceeded/.test(err.message) and not isCompleted and processCount > 2000
+                          logger.error 'getCommitInfo: ', {err: err, limit: /^API Rate Limit Exceeded/i.test(err.message), isCompleted: isCompleted, processCount: processCount}
+                          if /^API Rate Limit Exceeded/i.test(err.message) and not isCompleted and processCount > 2000
                             isCompleted = true
                             persistence.completeWorklog worklog._id, (err) ->
                               if err?
                                 isCompleted = false
                                 logger.error 'completeWorklog: ', {err: err}
                               logger.debug 'completed worklog', {file: worklog.file}
-                          else if not /^API Rate Limit Exceeded/.test(err.message)
+                          else if not /^API Rate Limit Exceeded/i.test(err.message)
                             innerLoop cur
                         else
                           logger.debug "parsing commit #{url} : ", {commit: commit}


Fix for position buttons panel

Fix for position buttons panel

--- lineman/app/components/thread_page/position_buttons_panel/position_buttons_panel.coffee
+++ lineman/app/components/thread_page/position_buttons_panel/position_buttons_panel.coffee
@@ -3,11 +3,10 @@
   restrict: 'E'
   templateUrl: 'generated/components/thread_page/position_buttons_panel/position_buttons_panel.html'
   replace: true
-  controller: ($scope, ModalService, VoteForm, CurrentUser, Records) ->
+  controller: ($scope, ModalService, VoteForm, CurrentUser, Records, AbilityService) ->

     $scope.showPositionButtons = ->
-      CurrentUser.isMemberOf($scope.proposal.group()) and
-      $scope.proposal.isActive() and $scope.undecided()
+      AbilityService.canVoteOn($scope.proposal) and $scope.undecided()

     $scope.undecided = ->
       !($scope.proposal.lastVoteByUser(CurrentUser)?)


Fixed indentation issue (everything below gulp.src)

--- gulp/client-scripts.coffee
+++ gulp/client-scripts.coffee
@@ -33,29 +33,29 @@
     # gather all coffeescript source files in /app/...
     gulp.src ['app/**/*.coffee'], base: './app'

-    # handle and prevent crashes
-    .pipe plumber()
+      # handle and prevent crashes
+      .pipe plumber()

-    # check for script mistakes
-    .pipe lint()
-    .pipe lint.reporter()
+      # check for script mistakes
+      .pipe lint()
+      .pipe lint.reporter()

-    # compile coffescript source
-    .pipe sourcemaps.init()
-    .pipe coffee()
+      # compile coffescript source
+      .pipe sourcemaps.init()
+      .pipe coffee()

-    # add javascript files to bundle
-    .pipe addsrc('app/**/*.js')
+      # add javascript files to bundle
+      .pipe addsrc('app/**/*.js')

-    # bring everything together with index.js (concat)
-    .pipe gulpif config.concat, concat 'index.js'
+      # bring everything together with index.js (concat)
+      .pipe gulpif config.concat, concat 'index.js'

-    # Angular.js annotations pre-processing...
-    .pipe ngAnnotate add: yes, remove: yes, single_quotes: yes
+      # Angular.js annotations pre-processing...
+      .pipe ngAnnotate add: yes, remove: yes, single_quotes: yes

-    # Parse js files and make them "nicer" (Uglify)
-    .pipe gulpif config.minify, uglify()
+      # Parse js files and make them "nicer" (Uglify)
+      .pipe gulpif config.minify, uglify()

-    # write out product
-    .pipe gulpif config.sourcemaps, sourcemaps.write()
-    .pipe gulp.dest path.join config.paths.dest, 'app'+      # write out product
+      .pipe gulpif config.sourcemaps, sourcemaps.write()
+      .pipe gulp.dest path.join config.paths.dest, 'app'


EnumFieldView: changed format for specifying values to array of arrays, instead of hash, to preserve order. Fixed issue where non-null enum fields would have a default value of null, and instead use first item in values array as value.

--- lib/ST/EnumFieldView.coffee
+++ lib/ST/EnumFieldView.coffee
@@ -3,7 +3,7 @@
 ST.class 'EnumFieldView', 'View', ->
   @initializer 'withValuesNull', (values, _null) ->
     @init()
-    @_value = null
+    @_value = if _null then null else values[0][1]
     @_null = _null
     @_values = values
     @_valueIndex = {}
@@ -14,6 +14,14 @@
   @property 'values'
   @property 'selectElement'
   @property 'id'
+
+  @method 'isValueValid', (value) ->
+    if value is null
+      @_null
+    else
+      for option in @_values
+        return true if option[1] == value
+      false

   @method 'render', ->
     @_selectElement = $ '<select />'
@@ -29,12 +37,11 @@
       html.push '<option value=""'
       html.push ' selected="selected"' if @_value is null
       html.push '></option>'
-    for value, label of @_values
-      if @_values.hasOwnProperty value
-        html.push '<option value="', value, '"'
-        html.push ' selected="selected"' if @_value == value
-        html.push '>', label, '</option>'
-        @_valueIndex[value] = index++
+    for option in @_values
+      html.push '<option value="', option[1], '"'
+      html.push ' selected="selected"' if @_value == option[1]
+      html.push '>', option[0], '</option>'
+      @_valueIndex[option[1]] = index++
     @_selectElement.html html.join('')

   @method 'selectChanged', (e) ->
@@ -48,14 +55,16 @@
         @_skipUpdate = true
         @value newValue

-  @method '_valueChanged', (oldValue, newValue) ->
-    if @_skipUpdate
-      @_skipUpdate = false
-    else if @_loaded
-      @_selectElement[0].selectedIndex = if @_valueIndex[newValue]? then @_valueIndex[newValue] else 0
+  @method 'setValue', (newValue) ->
+    if @isValueValid(newValue)
+      @_value = newValue
+      if @_skipUpdate
+        @_skipUpdate = false
+      else if @_loaded
+        @_selectElement[0].selectedIndex = if @_valueIndex[newValue]? then @_valueIndex[newValue] else 0

   @method '_valuesChanged', (oldValues, newValues) ->
-    @value null unless @_values[@_value]
+    @value null unless @isValueValid(@value)
     @renderOptions() if @_loaded

   @method '_idChanged', (oldValue, newValue) ->


Port to Process API

Port to Process API

--- components/GetActionValues.coffee
+++ components/GetActionValues.coffee
@@ -18,25 +18,28 @@
     datatype: 'object'
   c.inPorts.add 'keys',
     datatype: 'string'
+    control: true
   c.outPorts.add 'values',
     datatype: 'all'
     addressable: yes
   c.outPorts.add 'out',
     datatype: 'object'
-  noflo.helpers.WirePattern c,
-    in: 'in'
-    params: 'keys'
-    out: 'out'
-    async: true
-    forwardGroups: true
-  , (data, groups, out, callback) ->
-    if not c.params.keys or not data.state or not data.payload
-      out.send data.payload or data
-      do callback
-      return
-    keys = c.params.keys.split ','
-    values = getValues keys, data.state
-    for value, idx in values
-      c.outPorts.values.send value, idx
-    out.send data.payload
-    do callback
+  c.outPorts.add 'state',
+    datatype: 'object'
+  c.process (input, output) ->
+    return unless input.hasData 'in'
+    return if input.attached('keys').length and not input.hasData 'keys'
+
+    data = input.getData 'in'
+
+    if input.hasData 'keys'
+      keys = input.getData('keys').split ','
+      values = getValues keys, data.state
+      for value, idx in values
+        output.send
+          values: new noflo.IP 'data', value,
+            index: idx
+
+    output.sendDone
+      state: data.state or {}
+      out: data.payload or data


Adds funnel event for successful login

Adds funnel event for successful login

--- components/auth_modal/view.coffee
+++ components/auth_modal/view.coffee
@@ -73,8 +73,12 @@
       @showError _.capitalize res.error
     else
       createCookie 'destination', @destination, 1 if @destination
-      createCookie 'signed_in', true, 7 if @state.get('mode') is 'login'
-      href = '/force/log_in_to_artsy'
+
+      if @state.get('mode') is 'login'
+        createCookie 'signed_in', true, 7
+        analytics.track.funnel 'Successfully logged in'
+
+      href  = '/force/log_in_to_artsy'
       href += "?redirect-to=#{@redirectTo}" if @state.get('mode') is 'register'
       location.href = href


Fix workspaceView spec

Fix workspaceView spec

--- spec/workspace-view-spec.coffee
+++ spec/workspace-view-spec.coffee
@@ -58,7 +58,7 @@
         pane1 = atom.workspaceView.getActivePaneView()
         pane2 = pane1.splitRight()
         pane3 = pane2.splitRight()
-        pane4 = pane2.splitDown()
+        pane4 = null

         waitsForPromise ->
           atom.workspace.open('b').then (editor) ->
@@ -70,6 +70,7 @@

         runs ->
           pane3.activeItem.setCursorScreenPosition([2, 4])
+          pane4 = pane2.splitDown()

         waitsForPromise ->
           atom.workspace.open('../sample.txt').then (editor) ->


Adding special route for the authentication interface to redirect already authenticated users to the requested application

--- src/server/http_server.coffee
+++ src/server/http_server.coffee
@@ -122,7 +122,7 @@
         browserRoute = "#{mountPointNoSlash}/browsers/:browserID/index"

         # Middleware that protects access to browsers
-        verifyAuthentication = (req, res, next) =>
+        isAuthenticated = (req, res, next) =>
             components  = mountPointNoSlash.split("/")
             index       = 1
             mp          = ""
@@ -141,6 +141,18 @@
                         next()
                 else
                     res.send("Permission Denied", 403)
+
+        # Middleware to reroute authenticated users when they request for
+        # the authentication_interface
+        isNotAuthenticated = (req, res, next) =>
+            components  = mountPointNoSlash.split("/")
+            index       = 1
+            mp          = ""
+            while components[index] isnt "authenticate" and index < components.length
+                mp += "/" + components[index++]
+            if @findAppUser(req, mp)
+                @redirect(res, "#{mp}#{@constructQueryString(req)}")
+            else next()

         # Route handler for resource proxy request
         resourceProxyRouteHandler = (req, res) ->
@@ -173,21 +185,18 @@
         # a browser from a URL sent via POST).

         if /landing_page$/.test(mountPointNoSlash)
-            @server.get mountPoint, verifyAuthentication, (req, res) =>
+            @server.get mountPoint, isAuthenticated, (req, res) =>
                 components  = mountPointNoSlash.split("/")
-                index       = 1
-                mp          = ""
-                while components[index] isnt "landing_page" and index < components.length
-                    mp += "/" + components[index++]
+                components.pop()
+                mp = components.join("/")
                 user = @findAppUser(req, mp)
                 queryString = @constructQueryString(req)
                 browsers.create app, queryString, user, (err, bserver) =>
                     throw err if err
                     @redirect(res, "#{mountPointNoSlash}/browsers/#{bserver.id}/index#{queryString}")

-            @server.get browserRoute, verifyAuthentication, browserRouteHandler
-
-            @server.get resourceProxyRoute, verifyAuthentication, resourceProxyRouteHandler
+            @server.get browserRoute, isAuthenticated, browserRouteHandler
+            @server.get resourceProxyRoute, isAuthenticated, resourceProxyRouteHandler

         else if app.authenticationInterface

@@ -213,7 +222,7 @@
                         throw err if err
                         res.render 'deactivate.jade'

-            @server.get mountPoint, verifyAuthentication, (req, res) =>
+            @server.get mountPoint, isAuthenticated, (req, res) =>
                 queryString = @constructQueryString(req)
                 if app.getPerUserBrowserLimit() > 1
                     @redirect(res, "#{mountPointNoSlash}/landing_page#{queryString}")
@@ -222,9 +231,21 @@
                     browsers.create app, queryString, user, (err, bserver) =>
                         @redirect(res, "#{mountPointNoSlash}/browsers/#{bserver.id}/index#{queryString}")

-            @server.get browserRoute, verifyAuthentication, authorize, browserRouteHandler
-
-            @server.get resourceProxyRoute, verifyAuthentication, resourceProxyRouteHandler
+            @server.get browserRoute, isAuthenticated, authorize, browserRouteHandler
+            @server.get resourceProxyRoute, isAuthenticated, resourceProxyRouteHandler
+
+        else if /authenticate$/.test(mountPointNoSlash)
+            @server.get mountPoint, isNotAuthenticated, (req, res) =>
+                id = req.session.browserID
+                queryString = @constructQueryString(req)
+                if !id? || !browsers.find(id)
+                  bserver = browsers.create(app, queryString)
+                  # Makes the browser stick to a particular client to prevent creation of too many browsers
+                  id = req.session.browserID = bserver.id
+                  @redirect(res, "#{mountPointNoSlash}/browsers/#{id}/index#{queryString}")
+
+            @server.get browserRoute, isNotAuthenticated, browserRouteHandler
+            @server.get resourceProxyRoute, isNotAuthenticated, resourceProxyRouteHandler

         else
             @server.get mountPoint, (req, res) =>


Log errors better when value field is missing

--- indicatorators/esri.coffee
+++ indicatorators/esri.coffee
@@ -37,11 +37,13 @@
   unless data.features?
     throw new Error("ESRI data should ahve a features atributes")

-addIndicatorTextToData = (rows, indicatorCode, indicatorDefintion) ->
+addIndicatorTextToData = (rows, indicatorCode, indicatorDefinition) ->
   outputRows = []
   for row in rows
     value = row[indicatorDefinition.valueField]
-    continue unless value?
+    unless value?
+      console.log "Row is missing value field '#{indicatorDefinition.valueField}'"
+      continue
     text = calculateIndicatorText(indicatorCode, value)
     row.text = text
     outputRows.push(attributes: row)


Re-fix bug that prevented run now dialog from opening from the pending tasks page

--- SingularityUI/app/models/Task.coffee
+++ SingularityUI/app/models/Task.coffee
@@ -1,5 +1,5 @@
 Model = require './model'
-Request = require './Request'
+Request = require './request'

 endsWith = (needle, haystack) ->
     position = haystack.length - needle.length


Add news

Add news

--- server/materials/data/news.coffee
+++ server/materials/data/news.coffee
@@ -3,8 +3,8 @@

 export default allNews = () ->
     return news([
-        newsItem("10 февраля занятия в лицее 40 не будет", String.raw"""
-
10 февраля занятия в лицее не будет. 17 февраля и далее занятия, скорее всего, будут дальше как обычно.

+        newsItem("Наблюдаются проблемы при взаимодействии алгопрога и информатикса", String.raw"""
+
На данный момент наблюдаются проблемы во взаимодействии алгопрога и информатикса, в частности, решения не отправляются или отправляются не стабильно.

         """),
         newsItem("Про занятия в ННГУ", String.raw"""

В текущем учебном году занятий в ННГУ точно не будет.


Use Mode::push to handle adding/removing a handler

--- content_scripts/link_hints.coffee
+++ content_scripts/link_hints.coffee
@@ -249,16 +249,12 @@
           when "Control"
             @setOpenLinkMode(if @mode is OPEN_IN_NEW_FG_TAB then OPEN_IN_NEW_BG_TAB else OPEN_IN_NEW_FG_TAB)

-        handlerId = handlerStack.push
+        handlerId = @hintMode.push
           keyup: (event) =>
             if event.key == key
               handlerStack.remove()
               @setOpenLinkMode previousMode
             true # Continue bubbling the event.
-
-        # For some (unknown) reason, we don't always receive the keyup event needed to remove this handler.
-        # Therefore, we ensure that it's always removed when hint mode exits.  See #1911 and #1926.
-        @hintMode.onExit -> handlerStack.remove handlerId

     else if KeyboardUtils.isBackspace event
       if @markerMatcher.popKeyChar()


request a cloned model vs cloning itself

This allows the array result to just create a model insead of it
creating on and then it being cloned

--- client/lanes/components/grid/Body.cjsx
+++ client/lanes/components/grid/Body.cjsx
@@ -15,7 +15,10 @@
         )
         left = ev.clientX - ourBounds.left
         selectedIndex = (if @props.selectedIndex == index then null else index)
-        selectedModel = if selectedIndex? then @props.query.results.modelAt(selectedIndex)?.clone() else null
+
+        selectedModel = if selectedIndex?
+            @props.query.results.modelAt(selectedIndex, clone: true)
+        else null
         @props.onRowClick(selectedModel, selectedIndex,
             {top, left, container: ourBounds, rowHeight: clickBounds.height}
         )


Remove old objects from index when updating files

--- lib/fortran-provider.coffee
+++ lib/fortran-provider.coffee
@@ -22,6 +22,7 @@
   lastRow: -1

   fileObjInd: { }
+  fileObjLists: { }
   globalObjInd: []
   projectObjList: { }
   exclPaths: []
@@ -61,6 +62,7 @@
     @modFiles = []
     @fileIndexed = []
     @fileObjInd = { }
+    @fileObjLists = { }
     @globalObjInd = []
     @projectObjList = { }
     @descList = []
@@ -226,7 +228,10 @@
     if fileRef == -1
       @modFiles.push(filePath)
       fileRef = @modFiles.indexOf(filePath)
+    oldObjList = @fileObjLists[filePath]
+    @fileObjLists[filePath] = []
     for key of fileAST['objs']
+      @fileObjLists[filePath].push(key)
       if key of @projectObjList
         @resetInherit(@projectObjList[key])
       @projectObjList[key] = fileAST['objs'][key]
@@ -238,6 +243,12 @@
           @projectObjList[key]['desc'] = @descList.length-1
         else
           @projectObjList[key]['desc'] = descIndex
+    # Remove old objects
+    if oldObjList?
+      for key in oldObjList
+        unless key of fileAST['objs']
+          delete @projectObjList[key]
+    #
     @globalObjInd = []
     for key of @projectObjList
       if not key.match(/::/)


word cloud tweaks

word cloud tweaks

--- static/coffee/v2_polls.coffee
+++ static/coffee/v2_polls.coffee
@@ -50,6 +50,8 @@
         chart: {
           marginTop: 0
           marginBottom: 0
+          paddingTop: 0
+          paddingBottom: 0
           style: {
             fontFamily: "Montserrat"
           }
@@ -62,6 +64,7 @@
         plotOptions: {
           wordcloud: {
             colors: orgColors
+            minFontSize: 6
             rotation: {
               orientations: 1
             }


Rename editSession to editor

Rename editSession to editor

--- lib/markdown-preview.coffee
+++ lib/markdown-preview.coffee
@@ -6,15 +6,15 @@

   show: ->
     activePane = atom.workspaceView.getActivePane()
-    editSession = activePane.activeItem
+    editor = activePane.activeItem

-    isMarkdownEditor = editSession.getGrammar?()?.scopeName is "source.gfm"
+    isMarkdownEditor = editor.getGrammar?()?.scopeName is "source.gfm"
     unless isMarkdownEditor
-      console.warn("Can not render markdown for '#{editSession.getUri() ? 'untitled'}'")
+      console.warn("Can not render markdown for '#{editor.getUri() ? 'untitled'}'")
       return

-    {previewPane, previewItem} = @getExistingPreview(editSession)
-    filePath = editSession.getPath()
+    {previewPane, previewItem} = @getExistingPreview(editor)
+    filePath = editor.getPath()
     if previewItem?
       previewPane.showItem(previewItem)
       previewItem.renderMarkdown()
@@ -24,8 +24,8 @@
       activePane.splitRight(new MarkdownPreviewView(filePath))
     activePane.focus()

-  getExistingPreview: (editSession) ->
-    uri = "markdown-preview:#{editSession.getPath()}"
+  getExistingPreview: (editor) ->
+    uri = "markdown-preview:#{editor.getPath()}"
     for previewPane in atom.workspaceView.getPanes()
       previewItem = previewPane.itemForUri(uri)
       return {previewPane, previewItem} if previewItem?


:bug: Fix initialize now being a reserved package method

--- lib/minimap-pigments.coffee
+++ lib/minimap-pigments.coffee
@@ -17,7 +17,7 @@
   consumePigmentsServiceV1: (@pigments) ->
     @subscriptions.add @pigments.getProject().onDidDestroy => @pigments = null

-    @initialize() if @minimap? and @active
+    @initializeBindings() if @minimap? and @active

   deactivate: ->
     @subscriptions.dispose()
@@ -31,9 +31,9 @@

     @active = true

-    @initialize() if @pigments?
+    @initializeBindings() if @pigments?

-  initialize: ->
+  initializeBindings: ->
     @editorsSubscription = @pigments.observeColorBuffers (colorBuffer) =>
       editor = colorBuffer.editor
       minimap = @minimap.minimapForEditor(editor)


Now I don' t need stale command

Now I don' t need stale command

--- lib/mutation-manager.coffee
+++ lib/mutation-manager.coffee
@@ -2,17 +2,6 @@
 {getFirstCharacterPositionForBufferRow, getVimLastBufferRow} = require './utils'
 swrap = require './selection-wrapper'

-# keep mutation snapshot necessary for Operator processing.
-# mutation stored by each Selection have following field
-#  marker:
-#    marker to track mutation. marker is created when `setCheckpoint`
-#  createdAt:
-#    'string' representing when marker was created.
-#  checkpoint: {}
-#    key is ['will-select', 'did-select', 'will-mutate', 'did-mutate']
-#    key is checkpoint, value is bufferRange for marker at that checkpoint
-#  selection:
-#    Selection beeing tracked
 module.exports =
 class MutationManager
   constructor: (@vimState) ->
@@ -75,7 +64,6 @@
     ranges

   restoreCursorPositions: ({stay, wise, setToFirstCharacterOnLinewise}) ->
-    # stay = false
     if wise is 'blockwise'
       for blockwiseSelection in @vimState.getBlockwiseSelections()
         {head, tail} = blockwiseSelection.getProperties()
@@ -135,7 +123,7 @@
     if selectedRange.isEqual(@marker.getBufferRange()) # Check if need Clip
       point
     else
-      {start, end} = range = @marker.getBufferRange()
+      {start, end} = @marker.getBufferRange()
       end = Point.max(start, end.translate([0, -1]))
       if wise is 'linewise'
         point.row = Math.min(end.row, point.row)


Simplify `TokenizedBuffer#handleBufferChange` for row-oriented events

Only talking about rows, instead of both rows and columns makes everything a lot simpler.

--- src/app/tokenized-buffer.coffee
+++ src/app/tokenized-buffer.coffee
@@ -22,40 +22,32 @@
     @buffer.on "change.tokenized-buffer#{@id}", (e) => @handleBufferChange(e)

   handleBufferChange: (e) ->
-    oldRange = e.oldRange.copy()
-    newRange = e.newRange.copy()
-    previousStack = @stackForRow(oldRange.end.row) # used in spill detection below
+    {oldRange, newRange} = e
+    start = oldRange.start.row
+    end = oldRange.end.row
+    delta = newRange.end.row - oldRange.end.row

-    stack = @stackForRow(newRange.start.row - 1)
-    @screenLines[oldRange.start.row..oldRange.end.row] =
-      @buildScreenLinesForRows(newRange.start.row, newRange.end.row, stack)
+    previousStack = @stackForRow(end) # used in spill detection below
+
+    stack = @stackForRow(start - 1)
+    @screenLines[start..end] = @buildScreenLinesForRows(start, end + delta, stack)

     # spill detection
     # compare scanner state of last re-highlighted line with its previous state.
     # if it differs, re-tokenize the next line with the new state and repeat for
     # each line until the line's new state matches the previous state. this covers
     # cases like inserting a /* needing to comment out lines below until we see a */
-    for row in [newRange.end.row...@buffer.getLastRow()]
+    for row in [(end + delta)...@buffer.getLastRow()]
       break if _.isEqual(@stackForRow(row), previousStack)
       nextRow = row + 1
       previousStack = @stackForRow(nextRow)
       @screenLines[nextRow] = @buildScreenLineForRow(nextRow, @stackForRow(row))

-    # if highlighting spilled beyond the bounds of the textual change, update
-    # the pre and post range to reflect area of highlight changes
-    if nextRow > newRange.end.row
-      oldRange.end.row += (nextRow - newRange.end.row)
-      newRange.end.row = nextRow
-      endColumn = @buffer.lineForRow(nextRow).length
-      newRange.end.column = endColumn
-      oldRange.end.column = endColumn
+    # if highlighting spilled beyond the bounds of the textual change, update the
+    # end of the affected range to reflect the larger area of highlighting
+    end = Math.max(end, nextRow - delta) if nextRow

-    start = oldRange.start.row
-    end = oldRange.end.row
-    delta = newRange.end.row - oldRange.end.row
-    bufferChange = e
-
-    @trigger "change", { start, end, delta, bufferChange }
+    @trigger "change", { start, end, delta, bufferChange: e }

   getTabLength: ->
     @tabLength


Adjust logging levels

Adjust logging levels

--- lib/pushservices/wns.coffee
+++ lib/pushservices/wns.coffee
@@ -25,7 +25,7 @@
                         if @conf.launchTemplate and info.version >= 7.5
                             try
                                 launch = payload.compileTemplate(@conf.launchTemplate)
-                                @logger?.debug("Launch: #{launch}")
+                                @logger?.silly("Launch: #{launch}")
                             catch e
                                 @logger?.error("Cannot compile WNS param template: #{e}")
                                 return
@@ -53,14 +53,14 @@
                     options = { client_id: @conf.client_id, client_secret: @conf.client_secret }
                     if launch?
                         options["launch"] = launch
-                    @logger?.verbose("WNS client URL: #{info.token}")
+                    @logger?.silly("WNS client URL: #{info.token}")
                     sender info.token, note, options, (error, result) =>
                         if error
                             if error.shouldDeleteChannel
                                 @logger?.warn("WNS Automatic unregistration for subscriber #{subscriber.id}")
                                 subscriber.delete()
                         else
-                            @logger?.verbose("WNS result: #{JSON.stringify result}")
+                            @logger?.debug("WNS result: #{JSON.stringify result}")
                 catch error
                     @logger?.error("WNS Error: #{error}")


format

format

--- src/coffee/services/core.coffee
+++ src/coffee/services/core.coffee
@@ -47,7 +47,6 @@
           @display = true
           if def['show_on']? then this._doDisplay(def['show_on'], true)
           if def['hide_on']? then this._doDisplay(def['hide_on'], false)
-

       class Form extends Element
         constructor: (def) ->


Fix interaction between react and qtip2

Fix interaction between react and qtip2

If qtip is already activated for an element but title attribute is readded
later and thus triggers the event, replace the tooltip content instead of
immediate stop.

Fixes #491.

--- resources/assets/coffee/_classes/tooltip-default.coffee
+++ resources/assets/coffee/_classes/tooltip-default.coffee
@@ -22,11 +22,14 @@
   onMouseOver: (event) =>
     el = event.currentTarget

-    return if el._tooltip
+    title = el.getAttribute 'title'
+    el.removeAttribute 'title'
+
+    if el._tooltip
+      $(el).qtip 'set', 'content.text': title
+      return

     el._tooltip = true
-
-    title = el.getAttribute 'title'

     at = el.getAttribute('data-tooltip-position') || 'top center'

@@ -58,6 +61,5 @@
           height: 8

     el.setAttribute 'data-orig-title', title
-    el.removeAttribute 'title'

     $(el).qtip options, event


Disable defalut configurations of debuging.

--- lib/tree-view-finder.coffee
+++ lib/tree-view-finder.coffee
@@ -9,23 +9,23 @@
   config:
     entireWindow:
       type: 'boolean'
-      default: true
+      default: false
       title: 'Use entire window'
     debugTreeViewFinder:
       type: 'boolean'
-      default: true
+      default: false
       title: 'Enable debug information from tree-view-finder.coffee'
     debugFinderTool:
       type: 'boolean'
-      default: true
+      default: false
       title: 'Enable debug information from finder-tool.coffee'
     debugFileInfo:
       type: 'boolean'
-      default: true
+      default: false
       title: 'Enable debug information from file-info.coffee'
     debugHistory:
       type: 'boolean'
-      default: true
+      default: false
       title: 'Enable debug information from history'

   subscriptions: null


color2 ->

color2 ->

--- test/color2.coffee
+++ test/color2.coffee
@@ -170,9 +170,9 @@

 test "#equal", ->
   color1 = Color(255, 255, 255, 1)
-  Color = Color([255, 255, 255])
-
-  ok color1.equal(Color)
+  color2 = Color([255, 255, 255])
+
+  ok color1.equal(color2)

 test "#toString", ->
   noAlpha = Color(30, 40, 23)
@@ -199,14 +199,12 @@
   equalEnough hsl[3], 1.0

 test "#hue", ->
-  color = Color(34, 54, 239)
-
-  Color = color.hue(20)
-
-  equalEnough Color.r, 84
-  equalEnough Color.g, 37
-  equalEnough Color.b, 239
-  equalEnough Color.a, 1.0
+  color = Color(34, 54, 239).hue(20)
+
+  equalEnough color.r, 84
+  equalEnough color.g, 37
+  equalEnough color.b, 239
+  equalEnough color.a, 1.0

 test "#hue$", ->
   color = Color(34, 54, 239)
@@ -219,137 +217,125 @@
   equalEnough color.a, 1.0

 test "#complement", ->
-  color = Color(10, 30, 50)
-
-  Color = color.complement()
-
-  equalEnough Color.r, 51
-  equalEnough Color.g, 31
-  equalEnough Color.b, 10
-  equalEnough Color.a, 1.0
-
-test "#complement$", ->
-  color = Color(10, 30, 50)
-
-  color.complement$()
+  color = Color(10, 30, 50).complement()

   equalEnough color.r, 51
   equalEnough color.g, 31
   equalEnough color.b, 10
   equalEnough color.a, 1.0

+test "#complement$", ->
+  color = Color(10, 30, 50)
+
+  color.complement$()
+
+  equalEnough color.r, 51
+  equalEnough color.g, 31
+  equalEnough color.b, 10
+  equalEnough color.a, 1.0
+
 test "#grayscale", ->
-  color = Color(30, 40, 29)
-
-  Color = color.grayscale()
-
-  equalEnough Color.r, 35
-  equalEnough Color.g, 35
-  equalEnough Color.b, 35
-  equalEnough Color.a, 1.0
-
-test "#grayscale$", ->
-  color = Color(30, 40, 29)
-
-  color.grayscale$()
+  color = Color(30, 40, 29).grayscale()

   equalEnough color.r, 35
   equalEnough color.g, 35
   equalEnough color.b, 35
   equalEnough color.a, 1.0

+test "#grayscale$", ->
+  color = Color(30, 40, 29)
+
+  color.grayscale$()
+
+  equalEnough color.r, 35
+  equalEnough color.g, 35
+  equalEnough color.b, 35
+  equalEnough color.a, 1.0
+
 test "#saturate", ->
-  color = Color(100, 200, 150)
-
-  Color = color.saturate(0.3)
-
-  equalEnough Color.r, 69
-  equalEnough Color.g, 232
-  equalEnough Color.b, 150
-  equalEnough Color.a, 1.0
-
-test "#saturate$", ->
-  color = Color(100, 200, 150)
-
-  color.saturate$(0.3)
+  color = Color(100, 200, 150).saturate(0.3)

   equalEnough color.r, 69
   equalEnough color.g, 232
   equalEnough color.b, 150
   equalEnough color.a, 1.0

+test "#saturate$", ->
+  color = Color(100, 200, 150)
+
+  color.saturate$(0.3)
+
+  equalEnough color.r, 69
+  equalEnough color.g, 232
+  equalEnough color.b, 150
+  equalEnough color.a, 1.0
+
 test "#desaturate", ->
-  color = Color(69, 232, 150)
-
-  Color = color.desaturate(0.3)
-
-  equalEnough Color.r, 100
-  equalEnough Color.g, 200
-  equalEnough Color.b, 150
-  equalEnough Color.a, 1.0
-
-test "#desaturate$", ->
-  color = Color(69, 232, 150)
-
-  color.desaturate$(0.3)
+  color = Color(69, 232, 150).desaturate(0.3)

   equalEnough color.r, 100
   equalEnough color.g, 200
   equalEnough color.b, 150
   equalEnough color.a, 1.0

+test "#desaturate$", ->
+  color = Color(69, 232, 150)
+
+  color.desaturate$(0.3)
+
+  equalEnough color.r, 100
+  equalEnough color.g, 200
+  equalEnough color.b, 150
+  equalEnough color.a, 1.0
+
 test "#darken", ->
-  color = Color(45, 64, 39)
-
-  Color = color.darken(0.1)
-
-  equalEnough Color.r, 22
-  equalEnough Color.g, 32
-  equalEnough Color.b, 19
-  equalEnough Color.a, 1.0
-
-test "#darken$", ->
-  color = Color(45, 64, 39)
-
-  color.darken$(0.1)
+  color = Color(45, 64, 39).darken(0.1)

   equalEnough color.r, 22
   equalEnough color.g, 32
   equalEnough color.b, 19
   equalEnough color.a, 1.0

+test "#darken$", ->
+  color = Color(45, 64, 39)
+
+  color.darken$(0.1)
+
+  equalEnough color.r, 22
+  equalEnough color.g, 32
+  equalEnough color.b, 19
+  equalEnough color.a, 1.0
+
 test "#lighten", ->
-  color = Color(22, 32, 19)
-
-  Color = color.lighten(0.1)
-
-  equalEnough Color.r, 45
-  equalEnough Color.g, 64
-  equalEnough Color.b, 39
-  equalEnough Color.a, 1.0
-
-test "#lighten$", ->
-  color = Color(22, 32, 19)
-
-  color.lighten$(0.1)
+  color = Color(22, 32, 19).lighten(0.1)

   equalEnough color.r, 45
   equalEnough color.g, 64
   equalEnough color.b, 39
   equalEnough color.a, 1.0

+test "#lighten$", ->
+  color = Color(22, 32, 19)
+
+  color.lighten$(0.1)
+
+  equalEnough color.r, 45
+  equalEnough color.g, 64
+  equalEnough color.b, 39
+  equalEnough color.a, 1.0
+
 test "#mixWith", ->
   color1 = Color(50, 40, 60, 0.3)
-  Color = Color(10, 5, 16, 0.2)
-
-  mixedColor = color1.mixWith(Color)
+  color2 = Color(10, 5, 16, 0.2)
+
+  mixedColor = color1.mixWith(color2)

   equalEnough mixedColor.r, 30
   equalEnough mixedColor.g, (45 / 2).round()
   equalEnough mixedColor.b, (76 / 2).round()
   equalEnough mixedColor.a, 0.5 / 2

-  weightedMixedColor = color1.mixWith(Color, 0.1)
+  weightedMixedColor = color1.mixWith(color2, 0.1)

   equalEnough weightedMixedColor.r, ((50 * 0.1) + (10 * 0.9)).round()
   equalEnough weightedMixedColor.g, ((40 * 0.1) + (5 * 0.9)).round()
@@ -358,18 +344,18 @@

 test "#mixWith$", ->
   color1 = Color(50, 40, 60, 0.3)
-  Color = Color(10, 5, 16, 0.2)
+  color2 = Color(10, 5, 16, 0.2)

   color3 = Color(50, 40, 60, 0.3)

-  color1.mixWith$(Color)
+  color1.mixWith$(color2)

   equalEnough color1.r, 30
   equalEnough color1.g, (45 / 2).round()
   equalEnough color1.b, (76 / 2).round()
   equalEnough color1.a, 0.5 / 2

-  color3.mixWith$(Color, 0.1)
+  color3.mixWith$(color2, 0.1)

   equalEnough color3.r, ((50 * 0.1) + (10 * 0.9)).round()
   equalEnough color3.g, ((40 * 0.1) + (5 * 0.9)).round()
@@ -385,22 +371,22 @@
   equalEnough color.a, 1.0

 test "Color.mix", ->
-  color1 = Color(50, 40, 60, 0.3)
-  Color = Color(10, 5, 16, 0.2)
-
-  mixedColor = Color.mix(color1, Color)
-
-  equalEnough mixedColor.r, 30
-  equalEnough mixedColor.g, (45 / 2).round()
-  equalEnough mixedColor.b, (76 / 2).round()
-  equalEnough mixedColor.a, 0.5 / 2
-
-  weightedMixedColor = Color.mix(color1, Color, 0.1)
-
-  equalEnough weightedMixedColor.r, ((50 * 0.1) + (10 * 0.9)).round()
-  equalEnough weightedMixedColor.g, ((40 * 0.1) + (5 * 0.9)).round()
-  equalEnough weightedMixedColor.b, ((60 * 0.1) + (16 * 0.9)).round()
-  equalEnough weightedMixedColor.a, (0.3 * 0.1) + (0.2 * 0.9)
+  mixedColor = Color.mix(
+    Color("red"),
+    Color("sky blue")
+  )
+
+  equalEnough mixedColor.r, 173
+  equalEnough mixedColor.g, 94
+  equalEnough mixedColor.b, 127
+  equalEnough mixedColor.a, 1
+
+  weightedMixedColor = Color.mix(Color(0, 255, 0, 1), Color(255, 0, 255, 0.6), 0.1)
+
+  equalEnough weightedMixedColor.r, ((0 * 0.1) + (255 * 0.9)).round()
+  equalEnough weightedMixedColor.g, ((255 * 0.1) + (0 * 0.9)).round()
+  equalEnough weightedMixedColor.b, ((0 * 0.1) + (255 * 0.9)).round()
+  equalEnough weightedMixedColor.a, (1 * 0.1) + (0.6 * 0.9)

 test "accepts named colors", ->
   white = Color("white")


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/color2.coffee
+++ test/color2.coffee
@@ -155,6 +155,13 @@
   raises ->
     Color2("A Fake Color")

+test "#copy", ->
+  color = Color2(123, 231, 2)
+  copiedColor = color.copy()
+
+  ok color.equal(copiedColor)
+  ok color != copiedColor
+
 test "#equal", ->
   color1 = Color2(255, 255, 255, 1)
   color2 = Color2([255, 255, 255])


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/color2.coffee
+++ test/color2.coffee
@@ -63,4 +63,7 @@
   equal color.b.round(), 46
   equal color.a, 0.21

+test "accepts an hsla string as the first argument and an alpha value as the second. The alpha value takes precedence over the hsla string alpha value", ->
+  color = Color2('hsla(45, 0.3, 0.5, 0.1)', 0.47)
+
 module()


Chain off of property assertions in tests to make sure they are not undefined

--- test/common.coffee
+++ test/common.coffee
@@ -118,7 +118,7 @@
   describe "the isTextInDOM property", ->
     it "finds text somewhere in the DOM", ->
       casper.then ->
-        expect("THEODORE ROOSEVELT").to.be.textInDOM
+        expect("THEODORE ROOSEVELT").to.be.textInDOM.and.be.ok

     it "does not find text that is not in the DOM", ->
       casper.then ->
@@ -127,7 +127,7 @@
   describe "the matchTitle property", ->
     it "matches a regular expression (/Title/)", ->
       casper.then ->
-        expect(/Title/).to.matchTitle
+        expect(/Title/).to.matchTitle.and.be.ok

     it "does not match an given regular expression (/^Title/)", ->
       casper.then ->
@@ -143,18 +143,13 @@

   describe "BDD 'should' framework", ->
     it "should include the new asserts", ->
-      "#header_1".should.be.inDOM
-      "#header_X".should.not.be.inDOM
-
-  describe.skip "TDD 'assert' framework", ->
-    it "should have bound methods inDOM and others", ->
-      assert.inDOM("#header_1")
-
+      "#header_1".should.be.inDOM.and.visible.and.ok
+      "#header_X".should.not.be.inDOM.and.visible

   describe "the matchCurrentUrl property", ->
     it "matches /localhost/", ->
       casper.then ->
-        expect(/localhost/).to.matchCurrentUrl
+        expect(/localhost/).to.matchCurrentUrl.and.be.ok

     it "does not match /some_remote_host/", ->
       casper.then ->
@@ -202,7 +197,7 @@
   describe "the trueOnRemote method", ->
     it "catches true function expressions", ->
       casper.then ->
-        expect("function () { return true; }").to.be.trueOnRemote
+        expect("function () { return true; }").to.be.trueOnRemote.and.be.ok

     it "catches true simple expressions", ->
       casper.then ->
@@ -297,17 +292,15 @@
       casper.then ->
         expect(-> typeof jQuery).to.matchOnRemote("undefined")

-        expect('jquery-1.8.3').to.not.be.loaded
-
+        expect('jquery-1.8.3').to.not.be.loaded.now

     it "checks for jQuery loaded by CDN", ->
       casper.then ->
         jQueryCDN = 'http://code.jquery.com/jquery-1.8.3.min.js'
         casper.waitStart()
-        casper.page.includeJs(jQueryCDN, ->
-          console.log("\t(Loaded #{jQueryCDN.green})")
+        casper.page.includeJs jQueryCDN, ->
+          console.log("\t(Loaded #{jQueryCDN})")
           casper.waitDone()
-        )

         # includeJs is basically equivalent to:
         # v = document.createElement("script");
@@ -318,8 +311,3 @@
         expect(-> typeof jQuery).to.not.matchOnRemote("undefined")
         (-> typeof jQuery).should.not.matchOnRemote('undefined')
         expect('jquery-1.8.3.min.js').to.be.loaded
-
-
-
-
-


fix spec

fix spec

--- angular/test/protractor/notifications_spec.coffee
+++ angular/test/protractor/notifications_spec.coffee
@@ -14,7 +14,7 @@
       'shared an outcome',
       'poll is closing soon',
       'started a poll',
-      'liked your comment',
+      'reacted to your comment',
       'made you a coordinator',
       'participated in',
       'added options to'


only need one s3_uploads_complete trigger

--- app/assets/javascripts/s3_direct_upload.js.coffee
+++ app/assets/javascripts/s3_direct_upload.js.coffee
@@ -52,7 +52,6 @@
           $.post(to, content)

         data.context.remove() if data.context && settings.remove_completed_progress_bar # remove progress bar
-        $uploadForm.trigger("s3_upload_complete", [content])

         current_files.splice($.inArray(data, current_files), 1) # remove that element from the array
         $uploadForm.trigger("s3_uploads_complete") unless current_files.length


poll query view if it's not populated

poll query view if it's not populated

execute the polling on the button view, so that it's executed for both regular measures and stratified measures

--- app/assets/javascripts/views/query_view.js.coffee
+++ app/assets/javascripts/views/query_view.js.coffee
@@ -8,7 +8,7 @@
         @popChart.maximumValue(@model.result().IPP)
         d3.select(@el).select('.pop-chart').datum(@model.result()).call(@popChart)
   initialize: ->
-    @popChart = PopHealth.viz.populationChart().width(125).height(40).maximumValue(PopHealth.patientCount)
+    @popChart = PopHealth.viz.populationChart().width(125).height(25).maximumValue(PopHealth.patientCount)
   shouldDisplayPercentageVisual: -> !@model.isContinuous() and PopHealth.currentUser.shouldDisplayPercentageVisual()
   resultValue: -> if @model.isContinuous() then @model.observation() else @model.performanceRate()
   fractionTop: -> if @model.isContinuous() then @model.measurePopulation() else @model.numerator()
@@ -21,6 +21,14 @@
   template: JST['patient_results/query_buttons']
   events:
     'click .population-btn': 'changeFilter'
+    model:
+      change: ->
+        if @model.isPopulated()
+          clearInterval(@timeout) if @timeout?
+        else
+          @timeout ?= setInterval =>
+            @model.fetch()
+          , 3000
   initialize: ->
     @currentPopulation ?= 'IPP'
   ipp: -> @model.ipp()


made reloading more eager, and made forcing a reload now possible (without having multiple timeouts stagger) Conflicts: 	app/backbone/collections/channels.coffee


add Deferred tests using Mocha

add Deferred tests using Mocha

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -119,6 +119,13 @@
             log: true
             reporter: 'Spec'

+      mocha:
+        test:
+          src: ['tests/mocha/**/*.html']
+          options:
+            log: true
+            reporter: 'Spec'
+
       exec:
         whatever:
           cmd: (command) -> command


Added cleaning in watch task

Added cleaning in watch task

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -77,7 +77,7 @@
     watch:
       dist:
         files: ['<%= config.src %>/{,**/}*.coffee']
-        tasks: ['coffee:dist', 'urequire:dist']
+        tasks: ['coffee:dist', 'urequire:dist', 'clean:global']
       test:
         files: ['<%= config.test %>/{,**/}*.coffee']
         tasks: ['coffee:test', 'mochacli']
@@ -85,7 +85,7 @@
     mochacli:
       options:
         reporter: 'nyan'
-#        bail: true
+        bail: true
       all: ['<%= config.test %>/*.js']

   grunt.registerTask 'test', [


Work around grunt.file bug.

Work around grunt.file bug.

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -16,7 +16,12 @@
       options:
         inline: true

-    clean: ['_build', '_public/*']
+    clean:
+      # Note: Grunt 0.4.5 file.js has an invalid test for whether the
+      # target is contained in the cwd. Work-around is the force option.
+      derived: ['_build', '_public/*']
+      options:
+        force: true

     copy:
       js:


Add message for reminding to update the change log for new version

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -439,6 +439,7 @@
         run "rm -rf #{ pkg.name }"

     grunt.registerTask 'release-help', 'Prints the post-release steps', ->
+        grunt.log.ok 'Did you remember to update the cilantro/changelog module?'
         grunt.log.ok 'Push the code and tags: git push origin develop && git push --tags'
         grunt.log.ok "Go to #{ pkg.homepage }/releases to update the release descriptions and upload the binaries"


Disable source maps

Disable source maps

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -64,7 +64,7 @@
 					ext: '.js'
 				]
 				options:
-					sourceMap: true
+					sourceMap: false

 		# Lints CoffeeScript files
 		coffeelint:


update annotator path

update annotator path

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -20,7 +20,7 @@
   bbs: 'blueimp-bootstrap-image-gallery/js/bootstrap-image-gallery.min'
   d3: 'd3/d3.min'
   dropzone: 'dropzone/downloads/dropzone'
-  penguinator: 'penguinator/index'
+  penguinator: 'penguinator/dist/penguinator'
   gmaps: 'gmaps/gmaps'
   modernizr: 'webshim/js-webshim/minified/extras/modernizr-custom'
   webshims: 'webshim/js-webshim/minified/polyfiller'


Grunt-codo

Grunt-codo

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -25,9 +25,16 @@
         dest: "lib/"
         ext: ".js"

+    # just run 'codo' on the command line (using .codoopts),
+    # and everything will work.
+    # grunt-codo doesn't seem to produce consistent output at the
+    # moment.
     codo:
       options:
         undocumented: true
+        name: "Feedly API"
+        readme: "README.md"
+        extra: ["LICENSE.md"]
       all:
         src: ["src/feedly.coffee"]


Use default Mocha reporter.

Use default Mocha reporter.

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -173,7 +173,7 @@
       test:
         src: ['specs/**/*.coffee']
         options:
-          reporter: 'progress'
+          #reporter: 'progress'
           require: 'coffee-script/register'

     # Acceptance testing with cucumber


change testing framework to Mocha

change testing framework to Mocha

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -113,10 +113,6 @@
         files: [ 'tests/qunit/*/*.html' ]

       mocha:
-        all: 'tests/mocha/*.html'
-        core: 'test/mocha/enchant.js/*.html'
-
-      mocha:
         test:
           src: ['tests/mocha/**/*.html']
           options:
@@ -146,4 +142,4 @@
   grunt.loadTasks 'tasks/'

   # Default task.
-  grunt.registerTask 'default', [ 'jshint:core', 'concat', 'uglify', 'qunit', 'lang:en', 'lang:ja', 'lang:de', 'build' ]
+  grunt.registerTask 'default', [ 'jshint:core', 'concat', 'uglify', 'mocha', 'lang:en', 'lang:ja', 'lang:de', 'build' ]


fix(grunt): configure proxies for e2e/integration specs

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -85,6 +85,7 @@
   # run e2e integration tests
   grunt.registerTask "test:e2e", [
     "build:dev"
+    "configureProxies"
     "connect:e2e"
     "karma:e2e"
   ]
@@ -92,6 +93,7 @@
   # run casperjs integration tests
   grunt.registerTask "test:casperjs", [
     "build:dev"
+    "configureProxies"
     "connect:e2e"
     "casper"
   ]
@@ -103,8 +105,10 @@
     # run unit tests and generate code coverage report
     "karma:coverage"

+    "configureProxies"
+    "connect:e2e"
+
     # run all integration tests
-    "connect:e2e"
     "karma:e2e"
     "casper"
   ]


Add cookieRewrite option to proxy to fix Checkout API issues

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -30,6 +30,7 @@
   else
     portalProxyOptions = url.parse("http://#{portalHost}/")
   portalProxyOptions.preserveHost = true
+  portalProxyOptions.cookieRewrite = "${accountName}.vtexlocal.com.br"

   rewriteLocation = (location) ->
     return location