Reorganize specs (same content, ideas)

Reorganize specs (same content, ideas)

--- test/PreferPoetModeTest.coffee
+++ test/PreferPoetModeTest.coffee
@@ -10,13 +10,37 @@

 describe 'PreferPoetMode', ->

-  describe 'standalone function', ->
+  describe 'acceptable inputs', ->

-    it 'is ok if no unneeded parens are used', ->
+    it 'is ok with a basic fn invocation', ->
       results = coffeelint.lint 'alert "Hello CoffeeScript!"', config
       expect(results.length).to.equal 0

-    it 'is not ok if unneeded parens are used', ->
+    it 'is ok with a basic method invocation', ->
+      results = coffeelint.lint 'Math.pow 2, 3', config
+      expect(results.length).to.equal 0
+
+    it 'is ok with a fn invocation that takes a fn as an arg', ->
+      input = '''
+      runLater ->
+        alert "Hello CoffeeScript!"
+      '''
+      results = coffeelint.lint input, config
+      expect(results.length).to.equal 0
+
+    it 'is ok with mixed explicit/implicit paren usage', ->
+      input = """
+      gulp.task 'compile', ->
+        gulp.src(src)
+          .pipe(coffee())
+          .pipe(gulp.dest('./src'))
+      """
+      results = coffeelint.lint input, config
+      expect(results.length).to.equal 0
+
+  describe 'problematic inputs', ->
+
+    it 'rejects a fn invocation where unneeded parens are used', ->
       results = coffeelint.lint 'alert("Hello CoffeeScript!")', config
       expect(results.length).to.equal 1
       result = results[0]
@@ -24,13 +48,7 @@
       expect(result.lineNumber).to.equal 1
       expect(result.line).to.equal 'alert("Hello CoffeeScript!")'

-  describe 'function on an object', ->
-
-    it 'is ok if no unneeded parens are used', ->
-      results = coffeelint.lint 'Math.pow 2, 3', config
-      expect(results.length).to.equal 0
-
-    it 'is not ok if unneeded parens are used', ->
+    it 'rejects a method invocation where unneeded parens are used', ->
       results = coffeelint.lint 'Math.pow(2, 3)', config
       expect(results.length).to.equal 1
       result = results[0]
@@ -38,17 +56,7 @@
       expect(result.lineNumber).to.equal 1
       expect(result.line).to.equal 'Math.pow(2, 3)'

-  describe 'standalone function with another function as an argument', ->
-
-    it 'is ok if no unneeded parens are used', ->
-      input = '''
-      runLater ->
-        alert "Hello CoffeeScript!"
-      '''
-      results = coffeelint.lint input, config
-      expect(results.length).to.equal 0
-
-    it 'is not ok if unneeded parens are used', ->
+    it 'rejects a fn invocation that takes an fn as an arg with unneeded parens', ->
       input = '''
       runLater(->
         alert "Hello CoffeeScript!")
@@ -60,19 +68,7 @@
       expect(result.lineNumber).to.equal 2
       expect(result.line).to.equal '  alert "Hello CoffeeScript!")'

-  describe 'chained function invocations', ->
-
-    it 'is ok if no unneeded parens are used', ->
-      input = """
-      gulp.task 'compile', ->
-        gulp.src(src)
-          .pipe(coffee())
-          .pipe(gulp.dest('./src'))
-      """
-      results = coffeelint.lint input, config
-      expect(results.length).to.equal 0
-
-    it 'is not ok if unneeded parens are used', ->
+    it 'rejects mixed explicit/implict paren usage if the last is not implicit', ->
       input = """
       gulp.task('compile', ->
         gulp.src(src)


Replace unfinished pieces of doc

Replace unfinished pieces of doc

--- vendor/assets/javascripts/brainstem/loaders/abstract-loader.coffee
+++ vendor/assets/javascripts/brainstem/loaders/abstract-loader.coffee
@@ -193,7 +193,7 @@
   ###*
    * Called when all loading (including nested loads) are complete.
    * Updates the `externalObject` with the data that was gathered and resolves the promise.
-   * @return {[type]} [description]
+   * @return {undefined}
   ###
   _onLoadingCompleted: =>
     @_updateObjects(@externalObject, @internalObject)
@@ -258,7 +258,7 @@
   ###*
    * This needs to return a constructor for the model that associations will be compared with.
    * This typically will be the current collection's model/current model constructor.
-   * @return {Brainstem.Model} [description]
+   * @return {Brainstem.Model}
   ###
   _getModel: ->
     throw "Implement in your subclass"


handle hg converted gpg lines

handle hg converted gpg lines

running parse_commits if it included commits converted from mercurial kiln repositories would fail
we can see this in git@github.com:somecallmechief/oj.git by running
git rev-list 07bba --pretty=raw --max-count=1


removed undefined comparison

removed undefined comparison

--- src/config.coffee
+++ src/config.coffee
@@ -59,14 +59,10 @@
     return argv['msvs_version']

   getInstalledVisualStudioFlag: ->
-    msvsVersion = @getMsvsVersion()
-    if msvsVersion != undefined
+    msvsVersion = @getMsvsVersion() || process.env.GYP_MSVS_VERSION
+    if msvsVersion
       return msvsVersion
-
-    msvsVersion = process.env.GYP_MSVS_VERSION
-    if msvsVersion != undefined
-      return msvsVersion
-
+
     vs2012Path = path.join(@x86ProgramFilesDirectory(), "Microsoft Visual Studio 11.0", "Common7", "IDE")
     return '2012' if fs.existsSync(vs2012Path)


atom: fix config

atom: fix config

--- .atom/config.cson
+++ .atom/config.cson
@@ -1,19 +1,13 @@
 "*":
   editor:
-    fontSize: 12
+    fontSize: 14
     tabLength: 4
     invisibles: {}
     showInvisibles: true
     preferredLineLength: 100
   core:
     audioBeep: false
-<<<<<<< HEAD
-    projectHome: "~/dev/mnubo/main"
-=======
-    disabledPackages: [
-      "jshint"
-    ]
->>>>>>> atom: update config
+    projectHome: "~/dev"
   "exception-reporting":
     userId: "c0191c2d-2e42-2a6b-6160-e625d859884b"
   welcome:
@@ -55,9 +49,9 @@
 ".source.ts.tsx":
   editor:
     preferredLineLength: 100
+".source.ts":
+  editor:
+    preferredLineLength: 100
 ".diff.source":
   editor:
     preferredLineLength: 100
-".source.ts":
-  editor:
-    preferredLineLength: 100


Update atom config

Update atom config

--- .atom/config.cson
+++ .atom/config.cson
@@ -1,4 +1,5 @@
 "*":
+  "advanced-open-file": {}
   core:
     customFileTypes:
       "source.js": [
@@ -26,5 +27,7 @@
     coloured: false
   "one-light-ui":
     layoutMode: "Compact"
+  "tree-view":
+    squashDirectoryNames: true
   welcome:
     showOnStartup: false


don't set selection initially when editing text area

--- app/assets/javascripts/typus_markitup/modules/listener.js.coffee
+++ app/assets/javascripts/typus_markitup/modules/listener.js.coffee
@@ -38,7 +38,6 @@
       if match
         [all, classes, image, link, alt, caption] = match
         @activateToolbarButton(button, [image, caption, alt, link, classes])
-        @setSelection(@el, start, end)
       else
         @deactivateToolbarButton(button)

@@ -49,10 +48,6 @@
   deactivateToolbarButton: (button) ->
     button.removeClass('active')
     button.data('params', null)
-
-  setSelection: (el, start, end) ->
-    # TODO: compatibility shim needed here for some browsers https://developer.mozilla.org/en-US/docs/DOM/Input.setSelectionRange
-    el.setSelectionRange(start, end)

 ##
 # Plugin definition


fix preview tab

fix preview tab

--- app/assets/javascripts/uploadcare/widget/tabs/preview-tab.coffee
+++ app/assets/javascripts/uploadcare/widget/tabs/preview-tab.coffee
@@ -45,10 +45,10 @@
             tryToLoadVideoPreview(file, source.file)

       @file.done ifCur (info) =>
+        if @__state == 'video'
+          return
         state = if info.isImage then 'image' else 'regular'
-        if state != 'image' and info.sourceInfo.source == 'camera'
-          state = 'video'
-        if (state != 'image' and state != 'video') or state != @__state
+        if state != 'image' or state != @__state
           @__setState(state, {file: info})

       @file.fail ifCur (error, info) =>
@@ -62,7 +62,7 @@
         not blob.size or
         blob.size >= @settings.multipartMinSize
       )
-        return df.reject('???')
+        return df.reject().promise()

       utils.image.drawFileToCanvas(
@@ -87,15 +87,14 @@
             @element('image').attr('src', src)
             @initImage(size)
             df.resolve()
-      .fail () =>
-        return df.reject('fail')
+      .fail(df.reject)

       df.promise()

     __tryToLoadVideoPreview: (file, blob) =>
       if (
-        file.state() != 'pending' or
-          not blob.size
+        not URL or
+        not blob.size
       )
         return


Can't rely on Array.isArray ...

Can't rely on Array.isArray ...

--- helpers.coffee
+++ helpers.coffee
@@ -55,8 +55,8 @@
 exports.flatten = flatten = (array) ->
   flattened = []
   for element in array
-    if Array.isArray(element)
-      flattened = flattened.concat flatten(element)
+    if element instanceof Array
+      flattened = flattened.concat flatten element
     else
       flattened.push element
   flattened


fix breaking tests

fix breaking tests

--- test/bitbucket-pr_test.coffee
+++ test/bitbucket-pr_test.coffee
@@ -162,7 +162,6 @@
       pre = new SlackPullRequestEvent(MOCK_ROBOT, ISSUE_UPDATED_RESP, 'issue:updated')
       action = pre.issueUpdated()

-      expect( action.text ).to.eql 'Issue updated by Emma'
       expect( action.color ).to.eql COLORS.updated
       expect( action.fields[0].title ).to.eql 'Emma changed'
       expect( action.fields[0].value ).to.eql "*status*: open -> on hold"


:green_heart: Does not test for file moves on linux

--- spec/csv-editor-spec.coffee
+++ spec/csv-editor-spec.coffee
@@ -1,5 +1,6 @@
 require './helpers/spec-helper'

+os = require 'os'
 fs = require 'fs'
 fsp = require 'fs-plus'
 path = require 'path'
@@ -238,35 +239,37 @@
                   ['1', '2']
                 ])

-    describe 'when the file is moved', ->
-      [spy, newPath, spyTitle] = []
-
-      beforeEach ->
-        jasmine.useRealClock?()
-
-        openFixture('sample.csv', {})
-        runs ->
-          spy = jasmine.createSpy('did-change-path')
-          spyTitle = jasmine.createSpy('did-change-title')
-          csvEditor.onDidChangePath(spy)
-          csvEditor.onDidChangeTitle(spyTitle)
-
-          newPath = path.join(projectPath, 'new-file.csv')
-          fsp.removeSync(newPath)
-          fsp.moveSync(csvEditor.getPath(), newPath)
-
-        waitsFor 'change path callback called', -> spy.callCount > 0
-
-      it 'detects the change in path', ->
-        expect(spy).toHaveBeenCalledWith(newPath)
-        expect(csvEditor.getPath()).toEqual(newPath)
-
-      it 'changes the key path to the settings', ->
-        expect(tableEditPackage.csvConfig.get(csvDest)).toBeUndefined()
-        expect(tableEditPackage.csvConfig.get(newPath)).toBeDefined()
-
-      it 'dispatches a did-change-title event', ->
-        expect(spyTitle).toHaveBeenCalledWith('new-file.csv')
+    # File moves aren't detected on linux
+    if os.platform() is 'darwin'
+      describe 'when the file is moved', ->
+        [spy, newPath, spyTitle] = []
+
+        beforeEach ->
+          jasmine.useRealClock?()
+
+          openFixture('sample.csv', {})
+          runs ->
+            spy = jasmine.createSpy('did-change-path')
+            spyTitle = jasmine.createSpy('did-change-title')
+            csvEditor.onDidChangePath(spy)
+            csvEditor.onDidChangeTitle(spyTitle)
+
+            newPath = path.join(projectPath, 'new-file.csv')
+            fsp.removeSync(newPath)
+            fsp.moveSync(csvEditor.getPath(), newPath)
+
+          waitsFor 'change path callback called', -> spy.callCount > 0
+
+        it 'detects the change in path', ->
+          expect(spy).toHaveBeenCalledWith(newPath)
+          expect(csvEditor.getPath()).toEqual(newPath)
+
+        it 'changes the key path to the settings', ->
+          expect(tableEditPackage.csvConfig.get(csvDest)).toBeUndefined()
+          expect(tableEditPackage.csvConfig.get(newPath)).toBeDefined()
+
+        it 'dispatches a did-change-title event', ->
+          expect(spyTitle).toHaveBeenCalledWith('new-file.csv')

     describe 'when the file is deleted', ->
       [deleteSpy] = []


View is merged

View is merged

--- www/src/theoricus/mvc/view.coffee
+++ www/src/theoricus/mvc/view.coffee
@@ -5,14 +5,19 @@

   # $ reference to dom element
   el: null
-   # @property [String] class path
+
+  # @property [String] class path
   classpath : null
+
   # @property [String] class name
   classname : null
+
   # @property [String] namespace
   namespace : null
+
   # @property [theoricus.core.Process] process
   process   : null
+
    ###
   @param [theoricus.Theoricus] @the   Shortcut for app's instance
   ###
@@ -32,9 +37,10 @@
       @el = $ el

       if template == null
-        tmpl_folder = @namespace.singularize()
+        tmpl_folder = @namespace.replace(/\./g, '/')
         tmpl_name   = @classname.underscore()
-        Factory.template "#{tmpl_folder}/#{tmpl_name}", ( template )=>
+
+        @template "#{tmpl_folder}/#{tmpl_name}", ( template ) =>
           @render_template template

    render_template:( template )->
@@ -49,10 +55,6 @@
     @set_triggers?()
     @after_render?(@data)

-    ###
-    In case you define an "on_resize" handler it will be
-    # automatically binded and triggered
-    ###
     if @on_resize?
       $( window ).unbind 'resize', @on_resize
       $( window ).bind   'resize', @on_resize
@@ -115,29 +117,73 @@
   ###
   Destroy the view after the 'out' animation, the default behavior is to just
   empty it's container element.
+
+  before_destroy will be called just before emptying it.
   ###
-  destroy:->
+  destroy: () ->
+    if @on_resize?
+      $( window ).unbind 'resize', @on_resize
+
+    @before_destroy?()
     @el.empty()

-   # ~> Shortcuts
+  # ~> Shortcuts

   ###
   Shortcut for application navigate
-   @param [String] url URL to navigate
+
+  @param [String] url URL to navigate
   ###
   navigate:( url )->
     @the.processes.router.navigate url

   ###
   Shortcut for Factory.view method
-   @param [String] path    Path to view file
+
+  @param [String] path    Path to view file
   ###
   view:( path, fn )->
     Factory.view path, @process, fn

   ###
   Shortcut for Factory.template method
-   @param [String] url Path to template file
+
+  @param [String] url Path to template file
   ###
   template:( path, fn )->
-    Factory.template path, fn+    Factory.template path, fn
+
+  ###
+  instantiates a view, render on container passing current data
+  ###
+  require: ( view, container, data = @data, template ) ->
+    view = @view view, ( view ) =>
+
+      if container
+
+        # if user passes a selector instead of a object
+        if container instanceof String
+          container = @el.find container
+
+        # if user passes an object ref, jQuerify it
+        unless container instanceof jQuery
+          container = $ container
+
+        view.render data, @el.find container, template
+
+      view
+
+  find: ( selector ) => @el.find selector
+
+  ###
+  Takes a selector or array of selectors
+  Adds click event handler to each of them
+  ###
+  link: ( a_selector ) ->
+
+    $( a_selector ).each ( index, selector ) =>
+      @find( selector ).click ( event ) =>
+
+        @navigate $( event.delegateTarget ).attr( 'href' )
+
+        return off


Update remaining Asterix to Asterisk

Update remaining Asterix to Asterisk

--- src/app/text-mate-scope-selector-matchers.coffee
+++ src/app/text-mate-scope-selector-matchers.coffee
@@ -69,7 +69,7 @@

 module.exports = {
   AndMatcher
-  AsterixMatcher
+  AsteriskMatcher
   CompositeMatcher
   NegateMatcher
   OrMatcher


Use new /clone JSON endpoint

Use new /clone JSON endpoint

--- app/assets/javascripts/admin/services/bulk_products.js.coffee
+++ app/assets/javascripts/admin/services/bulk_products.js.coffee
@@ -1,4 +1,4 @@
-angular.module("ofn.admin").factory "BulkProducts", (PagedFetcher, dataFetcher) ->
+angular.module("ofn.admin").factory "BulkProducts", (PagedFetcher, dataFetcher, $http) ->
   new class BulkProducts
     products: []

@@ -11,14 +11,8 @@
       PagedFetcher.fetch url, (data) => @addProducts data.products

     cloneProduct: (product) ->
-      dataFetcher("/admin/products/" + product.permalink_live + "/clone.json").then (data) =>
-        # Ideally we would use Spree's built in respond_override helper here to redirect the
-        # user after a successful clone with .json in the accept headers
-        # However, at the time of writing there appears to be an issue which causes the
-        # respond_with block in the destroy action of Spree::Admin::Product to break
-        # when a respond_overrride for the clone action is used.
-        id = data.product.id
-        dataFetcher("/api/products/" + id + "?template=bulk_show").then (newProduct) =>
+      $http.post("/api/products/" + product.id + "/clone").success (data) =>
+        dataFetcher("/api/products/" + data.id + "?template=bulk_show").then (newProduct) =>
           @unpackProduct newProduct
           @insertProductAfter(product, newProduct)


Comments

Comments

--- app/assets/javascripts/tastes_bitter/javascript_errors.coffee
+++ app/assets/javascripts/tastes_bitter/javascript_errors.coffee
@@ -15,5 +15,5 @@
   xhr.open 'POST', '/__javascript_errors', true
   xhr.send form

-  # Return `false` to call the default handler. Returning `true` would skip it.
+  # Return `false` to call the default handler.
   false


Revert "library:"

Revert "library:"

This reverts commit ad212bef740b040208ebe04a0f47b55f954662ee.

--- src/library.coffee
+++ src/library.coffee
@@ -10,7 +10,7 @@
   ".yml":     "msgflo-register-foreign --forever=true --role #ROLE #FILENAME"
   ".js":      "msgflo-nodejs --name #ROLE #FILENAME"
   ".coffee":  "msgflo-nodejs --name #ROLE #FILENAME"
-  ".py":      "msgflo-python #FILENAME #ROLE --iips #IIPS"
+  ".py":  "msgflo-python #FILENAME #ROLE"
   ".json":    "noflo-runtime-msgflo --name #ROLE --graph #COMPONENT --iips #IIPS"
   ".fbp":     "noflo-runtime-msgflo --name #ROLE --graph #COMPONENT --iips #IIPS"


Fix graph for stats. Related to #531

Fix graph for stats. Related to #531

--- admin/static/coffee/models.coffee
+++ admin/static/coffee/models.coffee
@@ -141,10 +141,9 @@
                 keys_set = 0
                 for serializer_id of _s.serializers
                     serializer = _s.serializers[serializer_id]
-                    if serializer.btree?
-
-                        keys_read = parseFloat(serializer.btree.keys_read)
-                        keys_set = parseFloat(serializer.btree.keys_set)
+                    if serializer['btree-primary']?
+                        keys_read = parseFloat(serializer['btree-primary'].keys_read)
+                        keys_set = parseFloat(serializer['btree-primary'].keys_set)
                         if not isNaN(keys_read)
                             __s.keys_read += keys_read
                         if not isNaN(keys_set)


remove old diffmatchpatch workaround code

--- src/editor.coffee
+++ src/editor.coffee
@@ -7,63 +7,6 @@
 #= require tandem/keyboard
 #= require tandem/selection
 #= require tandem/renderer
-
-DIFF_DELETE = -1
-DIFF_INSERT = 1
-DIFF_EQUAL = 0
-
-dmp = new diff_match_patch
-
-stripNewlineAttributes = (delta) ->
-  deltas = []
-  _.each(delta.deltas, (delta) ->
-    if delta.text?
-      texts = delta.text.split("\n")
-      _.each(texts, (text, index) ->
-        deltas.push(new JetInsert(text, _.clone(delta.attributes)))
-        deltas.push(new JetInsert("\n")) if index < texts.length - 1
-      )
-    else
-      deltas.push(delta)
-  )
-  delta = new JetDelta(delta.startLength, delta.endLength, deltas)
-  delta.compact()
-  return delta
-
-diffToDelta = (diff) ->
-  console.assert(diff.length > 0, "diffToDelta called with diff with length <= 0")
-  originalLength = 0
-  finalLength = 0
-  deltas = []
-  # For each difference apply them separately so we do not disrupt the cursor
-  for [operation, value] in diff
-    switch operation
-      when DIFF_DELETE
-        # Deletes implied
-        originalLength += value.length
-      when DIFF_INSERT
-        deltas.push(new JetInsert(value))
-        finalLength += value.length
-      when DIFF_EQUAL
-        deltas.push(new JetRetain(originalLength, originalLength + value.length))
-        originalLength += value.length
-        finalLength += value.length
-  return new JetDelta(originalLength, finalLength, deltas)
-
-getEfficientDiff = (oldText, newText) ->
-  diff = dmp.diff_main(oldText, newText)
-  if (diff.length > 2)
-    dmp.diff_cleanupSemantic(diff)
-    dmp.diff_cleanupEfficiency(diff)
-  return diff
-
-mergeDiffs = (diff1, diff2) ->
-  return diff1.concat(diff2)
-
-deltaToText = (delta) ->
-  return _.map(delta.deltas, (delta) ->
-    return if delta.text? then delta.text else ""
-  ).join('')

 class TandemEditor extends EventEmitter2
@@ -275,7 +218,6 @@
     index = 0       # Stores where the last retain end was, so if we see another one, we know to delete
     offset = 0      # Tracks how many characters inserted to correctly offset new text
     oldDelta = @doc.toDelta()
-    delta = stripNewlineAttributes(delta)
     cursors = {}
     _.each(delta.deltas, (delta) =>
       if JetDelta.isInsert(delta)


follow docs

follow docs

--- src/follow.coffee
+++ src/follow.coffee
@@ -3,7 +3,7 @@
 velocity so that it will approach another object.

-# Make an enemy fol
+# Make an enemy follow the p
 player = GameObject
   health: 50


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/follow.coffee
+++ src/follow.coffee
@@ -1,6 +1,6 @@
 ###*
 The Follow module provides a simple method to set an object's
-t
+so that it is

 # Health regeneration


updated atom config

updated atom config

--- .atom/config.cson
+++ .atom/config.cson
@@ -17,6 +17,7 @@
       ".sass-cache"
       ".idea"
     ]
+    projectHome: "/Users/sp/Projects"
     themes: [
       "one-dark-ui"
       "chester-atom-syntax"
@@ -42,6 +43,8 @@
     breakOnSingleNewline: true
     liveUpdate: false
     useGitHubStyle: true
+  "project-manager":
+    includeGitRepositories: true
   tabs:
     addNewTabsAtEnd: true
     enableVcsColoring: true


Atom: disable spell-check (replaced by linter-spellcheck)

--- .atom/config.cson
+++ .atom/config.cson
@@ -14,6 +14,7 @@
       "latex"
       "linter-chktex"
       "linter-pep257"
+      "spell-check"
     ]
   editor:
     invisibles: {}


camelCase, again :)

camelCase, again :)

--- javascripts/agora.coffee
+++ javascripts/agora.coffee
@@ -7,14 +7,14 @@
   @use 'Storage'
   @use 'Session'

-  get_user = (username, cb) ->
+  getUser = (username, cb) ->
     user = @session('user/' + username)
     if user
       cb(user)
     else
       $.get('/user/' + username, {}, (data) -> cb(data))

-  format_date = (timestamp) ->
+  formatDate = (timestamp) ->
     pad = (number) ->
       if number < 10
         '0' + number
@@ -25,7 +25,7 @@

   @before (context) ->
     @user = @session('user')
-    @get_user = (username, data) -> get_user.apply(@, [username, data])
+    @getUser = (username, data) -> getUser.apply(@, [username, data])
     if context.path != '#/login'
       if !@user
         $('.user-info').fadeOut()
@@ -43,12 +43,12 @@
   @get '#/u/:username', { token: @session( 'token' ) }, (context) ->
     username = @params.username
     $.get '/user/' + username, { token: @session( 'token' ) }, (user) ->
-      context.partial('templates/profile.template', { user: user, date: format_date(user.joindate) })
+      context.partial('templates/profile.template', { user: user, date: formatDate(user.joindate) })

   # Own profile page
   @get '#/u', (context) ->
     $.get '/user/' + @user.username, { token: @session( 'token' ) }, (user) ->
-      context.partial('templates/profile.template', { user: user, date: format_date(user.joindate) })
+      context.partial('templates/profile.template', { user: user, date: formatDate(user.joindate) })

   # Login box
   @get '#/login', (context) ->
@@ -119,8 +119,8 @@
             if index < thread.posts.length
               post = thread.posts[index]
               content = showdown.makeHtml(post.source)
-              context.get_user post.username, (post_user) ->
-                context.render('templates/post.template', {post: {content: content, date: format_date(post.date), user: post_user}}).then (post) ->
+              context.getUser post.username, (postUser) ->
+                context.render('templates/post.template', {post: {content: content, date: formatDate(post.date), user: postUser}}).then (post) ->
                   $(post).appendTo('.thread')
                   render0(index + 1)
             else
@@ -170,7 +170,7 @@
         token: @session('token')
     }, (data) ->
       content = showdown.makeHtml($('.post-source').val())
-      context.render('templates/post.template', {post: {content: content, user: context.user, date: format_date(data.date)}}).then (postnode) ->
+      context.render('templates/post.template', {post: {content: content, user: context.user, date: formatDate(data.date)}}).then (postnode) ->
         $(postnode).hide().appendTo('.thread').slideDown()
         $('.new-post').detach().appendTo('.thread')
         $('.post-preview').click()


remove logs

remove logs

--- test/integration/login.coffee
+++ test/integration/login.coffee
@@ -109,9 +109,7 @@
     context 'when I fill in my new password', ->
       before (done) ->
         @browser.fill '#password', newPass
-        console.log "FILLED"
         @browser.pressButton '#content .btn-primary', =>
-          console.log "PRESSED"
           @browser.wait done

       it 'sets my password', ->


Added missing widget registration.

Added missing widget registration.

--- app/assets/javascripts/app/controllers/maintenance_widget.js.coffee
+++ app/assets/javascripts/app/controllers/maintenance_widget.js.coffee
@@ -1,7 +1,7 @@
 class App.MaintananceWidget extends App.Controller
   constructor: ->
     super
-
+
     # bind on event to show message
     App.Event.bind 'session:maintanance', (data) =>
       console.log('hannes was here')
@@ -23,3 +23,5 @@
       backdrop: false,
       keyboard: false,
     )
+
+App.Config.set( 'maintanance', App.MaintananceWidget, 'Widgets' )


reuse the same mesh when enlarged

reuse the same mesh when enlarged

--- lib/assets/javascripts/jax/partition/octree.js.coffee
+++ lib/assets/javascripts/jax/partition/octree.js.coffee
@@ -91,7 +91,9 @@

     @subdivide()
     @reEvaluateObjects()
-    @_mesh = null
+    @mesh.halfSize = @size
+    @mesh.offset = @position
+    @mesh.invalidate()

   ###
   Subdivides this octree, but does not actually instantiate any of its


:traffic_light:  :v: PASS ALL THE TESTS :v: :traffic_light:

...by removing them.

Here's the thing: now that the grammar is contained in the repository
PowerShell/EditorSyntax, it's not helpful to have grammar-based tests in
this repository.

--- spec/powershell-spec.coffee
+++ spec/powershell-spec.coffee
@@ -8,14 +8,6 @@
   beforeEach ->
     waitsForPromise ->
       atom.packages.activatePackage("language-powershell")
-    this.addMatchers
-      toHaveScopes: (scopes) ->
-        notText = if @isNot then "not" else ""
-        this.message = (expected) =>
-          "Expected token \"#{@actual.value}\" to #{notText} have scopes [#{expected}]. Instead found: [#{@actual.scopes.toString()}]"
-
-        allScopesPresent = scopes.every (scope) =>
-          return scope in @actual.scopes

     runs ->
       grammar = atom.grammars.grammarForScopeName('source.powershell')
@@ -23,383 +15,3 @@
   it "parses the grammar", ->
     expect(grammar).toBeTruthy()
     expect(grammar.scopeName).toBe "source.powershell"
-
-  describe "comments", ->
-    it "parses comments at the end of lines", ->
-      {tokens} = grammar.tokenizeLine("$foo = 'bar' # a trailing comment")
-      expect(tokens[0]).toEqual value: "$", scopes: ["source.powershell", "keyword.other.powershell"]
-      expect(tokens[1]).toEqual value: "foo", scopes: ["source.powershell", "variable.other.readwrite.powershell"]
-      expect(tokens[2]).toEqual value: " ", scopes: ["source.powershell"]
-      expect(tokens[3]).toEqual value: "=", scopes: ["source.powershell", "keyword.operator.assignment.powershell"]
-      expect(tokens[4]).toEqual value: " ", scopes: ["source.powershell"]
-      expect(tokens[5]).toEqual value: "'", scopes: ["source.powershell", "string.quoted.single.powershell"]
-      expect(tokens[6]).toEqual value: "bar", scopes: ["source.powershell", "string.quoted.single.powershell"]
-      expect(tokens[7]).toEqual value: "'", scopes: ["source.powershell", "string.quoted.single.powershell"]
-      expect(tokens[8]).toEqual value: " ", scopes: ["source.powershell"]
-      expect(tokens[9]).toEqual value: "#", scopes: ["source.powershell", "comment.line.number-sign.powershell"]
-      expect(tokens[10]).toEqual value: " a trailing comment", scopes: ["source.powershell", "comment.line.number-sign.powershell"]
-
-    it "parses comments at the beginning of lines", ->
-      {tokens} = grammar.tokenizeLine("# a leading comment")
-      expect(tokens[0]).toEqual value: "#", scopes: ["source.powershell", "comment.line.number-sign.powershell"]
-      expect(tokens[1]).toEqual value: " a leading comment", scopes: ["source.powershell", "comment.line.number-sign.powershell"]
-
-  describe "start of variable", ->
-    it "parses the dollar sign at the beginning of a variable separately", ->
-      {tokens} = grammar.tokenizeLine("$var")
-      expect(tokens[0]).toEqual value: "$", scopes: ["source.powershell", "keyword.other.powershell"]
-      expect(tokens[1]).toEqual value: "var", scopes: ["source.powershell", "variable.other.readwrite.powershell"]
-
-  describe "Double-quoted strings", ->
-    describe "String with content", ->
-      tokens = null
-
-      beforeEach ->
-        {tokens} = grammar.tokenizeLine("\"Hi there! and welcome to 'string-making': 101.\"")
-
-      it "should mark all parts of the string with the same scope", ->
-        for token in tokens
-          expect(token).toHaveScopes ["string.quoted.double.powershell"]
-
-      it "should tokenize the opening double-quote", ->
-        expect(tokens[0].value).toEqual "\""
-        expect(tokens[0]).toHaveScopes ["string.quoted.double.powershell"]
-
-      it "should tokenize content of the string", ->
-        expect(tokens[1].value).toEqual "Hi there! and welcome to 'string-making': 101."
-
-      it "should tokenize the closing double-quote", ->
-        expect(tokens[2].value).toEqual "\""
-        expect(tokens[2]).toHaveScopes ["string.quoted.double.powershell"]
-
-    describe "Empty string", ->
-      tokens = null
-
-      beforeEach ->
-        {tokens} = grammar.tokenizeLine("\"\"")
-
-      it "should mark all parts of the string with the same scope", ->
-        for token in tokens
-          expect(token).toHaveScopes ["string.quoted.double.powershell"]
-
-    describe "Variables within a string", ->
-      tokens = null
-      expectedDollarSignScopes = ["keyword.other.powershell"]
-
-      beforeEach ->
-        {tokens} = grammar.tokenizeLine("\"Hi there $name `$bob\"")
-
-      it "should mark all parts of the string with the same scope", ->
-        for token in tokens
-          expect(token).toHaveScopes ["source.powershell", "string.quoted.double.powershell"]
-
-      it "should tokenize content", ->
-        expect(tokens[1].value).toEqual "Hi there "
-
-      it "should tokenize the beginning of variable names as embedded punctuation", ->
-        expect(tokens[2].value).toEqual "$"
-        expect(tokens[2]).toHaveScopes expectedDollarSignScopes
-
-      it "should tokenize variable names", ->
-        expect(tokens[3].value).toEqual "name"
-        expect(tokens[3]).toHaveScopes ["source.powershell", "string.quoted.double.powershell", "variable.other.readwrite.powershell"]
-
-      it "should not tokenize as a variable when leading $ has been escaped", ->
-        expect(tokens[5].value).toEqual "`$"
-        expect(tokens[5]).toHaveScopes ["source.powershell", "string.quoted.double.powershell", "constant.character.escape.powershell"]
-        expect(tokens[5]).not.toHaveScopes ["source.powershell", "embedded.variable.other.powershell"]
-
-        expect(tokens[6].value).toEqual "bob"
-        expect(tokens[6]).not.toHaveScopes ["source.powershell", "embedded.variable.other.powershell"]
-
-  describe "Keywords", ->
-    describe "Block keywords", ->
-      # TODO: Add "sequence", "workflow" to keywords
-      keywords = [
-        "begin", "data", "dynamicparam", "end", "inlinescript", "parallel", "process"
-      ]
-
-      it "tokenizes keywords", ->
-        for keyword in keywords
-          {tokens} = grammar.tokenizeLine keyword
-          expect(tokens[0].value).toEqual keyword
-          expect(tokens[0]).toHaveScopes ["source.powershell", "keyword.control.powershell"]
-
-    describe "Flow keywords", ->
-      describe "If-else statements", ->
-        tokens = null
-
-        beforeEach ->
-          {tokens} = grammar.tokenizeLine("if($answer.length -lt 10) { echo $answer } elseif($answer.length -lt 100) { echo \"You talk a lot\" } else { echo \"?\"}")
-
-        it "should highlight 'if'", ->
-          expect(tokens[0]).toEqual value: "if", scopes: ["source.powershell","keyword.control.powershell"]
-
-        it "should highlight 'elseif'", ->
-          expect(tokens[14]).toEqual value: "elseif", scopes: ["source.powershell","keyword.control.powershell"]
-
-        it "should highlight 'else'", ->
-          expect(tokens[29]).toEqual value: "else", scopes: ["source.powershell","keyword.control.powershell"]
-
-      describe "Do-until statements", ->
-        tokens = null
-
-        beforeEach ->
-          {tokens} = grammar.tokenizeLine("do { echo $i; $i += 1 } until($i -gt 100)")
-
-        it "should highlight 'do'", ->
-          expect(tokens[0]).toEqual value: "do", scopes: ["source.powershell","keyword.control.powershell"]
-        it "should highlight 'until'", ->
-          expect(tokens[13]).toEqual value: "until", scopes: ["source.powershell","keyword.control.powershell"]
-
-      describe "'For' statements", ->
-        tokens = null
-
-        beforeEach ->
-          {tokens} = grammar.tokenizeLine("for($i=0;i<10;$i++) { echo $i }")
-
-        it "should highlight 'for'", ->
-          expect(tokens[0]).toEqual value: "for", scopes: ["source.powershell","keyword.control.powershell"]
-
-      describe "'ForEach' statements", ->
-        tokens = null
-
-        beforeEach ->
-          {tokens} = grammar.tokenizeLine("foreach($i in $array) { echo $i }")
-
-        it "should tokenize 'ForEach'", ->
-          expect(tokens[0].value).toEqual "foreach"
-          expect(tokens[0]).toHaveScopes ["source.powershell", "keyword.control.powershell"]
-
-        it "should tokenize 'in'", ->
-          expect(tokens[5].value).toEqual "in"
-          expect(tokens[5]).toHaveScopes ["source.powershell", "keyword.control.powershell"]
-
-      describe "Try-Catch-Finally statements", ->
-        tokens = null
-
-        beforeEach ->
-          {tokens} = grammar.tokenizeLine("try { throw \"FAIL\" } catch [System.IO.IOException] { Get-OutOfTrouble } finally { Get-OutOfTown }")
-
-        it "should tokenize 'Try'", ->
-          expect(tokens[0].value).toEqual "try"
-          expect(tokens[0]).toHaveScopes ["source.powershell", "keyword.control.powershell"]
-
-        it "should tokenize 'Catch'", ->
-          expect(tokens[8].value).toEqual "catch"
-          expect(tokens[8]).toHaveScopes ["source.powershell", "keyword.control.powershell"]
-
-        it "should tokenize 'Finally'", ->
-          expect(tokens[36].value).toEqual "finally"
-          expect(tokens[36]).toHaveScopes ["source.powershell", "keyword.control.powershell"]
-
-    describe "Logical operator keywords", ->
-      logicalOperators = [ "-and", "-or", "-xor", "-not", "-eq", "-lt", "-gt", "-le", "-ge", "-ne" ]
-
-      it "tokenizes logical operators", ->
-        for operator in logicalOperators
-          {tokens} = grammar.tokenizeLine operator
-          expect(tokens[0]).toEqual value: operator, scopes: ["source.powershell","keyword.operator.logical.powershell"]
-
-    describe "Unary operators", ->
-      unaryOperators = ["!"]
-
-      it "tokenizes unary operators", ->
-        for operator in unaryOperators
-          {tokens} = grammar.tokenizeLine operator
-          expect(tokens[0]).toEqual value: operator, scopes: ["source.powershell","keyword.operator.unary.powershell"]
-
-    describe "Bitwise operator keywords", ->
-      # TODO: add `-shl` and `-sh` upon resolution of SublimeText/PowerShell#101
-      bitwiseOperators = [ "-bAnd", "-bOr", "-bXor", "-bNot" ]
-
-      it "tokenizes bitwise operators", ->
-        for operator in bitwiseOperators
-          {tokens} = grammar.tokenizeLine operator
-          expect(tokens[0]).toEqual value: operator, scopes: ["source.powershell","keyword.operator.bitwise.powershell"]
-
-    describe "Comparison operator keywords", ->
-      comparisonOperators = [
-        "-notlike", "-like", "-match", "-notmatch", "-contains", "-notcontains",
-        "-in", "-notin", "-replace"
-      ]
-
-      it "tokenizes comparison operators", ->
-        for operator in comparisonOperators
-          {tokens} = grammar.tokenizeLine operator
-          expect(tokens[0]).toEqual value: operator, scopes: ["source.powershell","keyword.operator.comparison.powershell"]
-
-      it "tokenizes comparison operators regardless of case", ->
-        for operator in comparisonOperators
-          {tokens} = grammar.tokenizeLine operator.toUpperCase()
-          expect(tokens[0]).toEqual value: operator.toUpperCase(), scopes: ["source.powershell","keyword.operator.comparison.powershell"]
-
-      it "tokenizes comparison operators when prepended with a case sensitivity marker", ->
-        for operator in comparisonOperators
-          insensitiveOperator = operator.replace('-', '-i')
-          {tokens} = grammar.tokenizeLine insensitiveOperator
-          expect(tokens[0]).toEqual value: insensitiveOperator, scopes: ["source.powershell","keyword.operator.comparison.powershell"]
-
-          sensitiveOperator = operator.replace('-', '-c')
-          {tokens} = grammar.tokenizeLine sensitiveOperator
-          expect(tokens[0]).toEqual value: sensitiveOperator, scopes: ["source.powershell","keyword.operator.comparison.powershell"]
-
-      it "will not tokenize the operators if there's more characters", ->
-        for operator in comparisonOperators
-          operatorPlus = operator + "ual"
-          {tokens} = grammar.tokenizeLine operatorPlus
-          expect(tokens.length).toBe(2)
-          expect(tokens[0]).not.toHaveScopes ["source.powershell", "keyword.operator.comparison.powershell"]
-          expect(tokens[1]).not.toHaveScopes ["source.powershell", "keyword.operator.comparison.powershell"]
-
-  # Automatic variables. Ref: https://technet.microsoft.com/en-us/library/hh847768.aspx
-  # Skip while things settle out on the parent grammar: SublimeText/PowerShell#103
-  xdescribe "Automatic variables", ->
-    automaticVariables = [
-      "$$", "$?", "$^", "$_",
-      "$Args",
-      "$ConsoleFileName",
-      "$Event", "$EventArgs", "$EventSubscriber", "$ExecutionContext",
-      "$false", "$ForEach",
-      "$Host", "$Home",
-      "$Input",
-      "$LastExitCode",
-      "$Matches", "$MyInvocation",
-      "$NestedPromptLevel", "$null",
-      "$OFS",
-      "$PID", "$Profile", "$PSBoundParameters", "$PSCmdlet", "$PSCommandPath",
-      "$PSCulture", "$PSDebuggingContext", "$PSHome", "$PSItem", "$PSScriptRoot",
-      "$PSSenderInfo", "$PSUICulture", "$PSVersionTable", "$Pwd",
-      "$Sender", "$ShellID", "$StackTrace",
-      "$This", "$true"
-    ]
-
-    it "tokenizes automatic variables", ->
-      for automaticVariable in automaticVariables
-        {tokens} = grammar.tokenizeLine automaticVariable
-        expect(tokens[0].value).toEqual "$"
-        expect(tokens[0]).toHaveScopes ["source.powershell", "keyword.other.powershell"]
-        if tokens[1]?
-          expect(tokens[1].value).toEqual automaticVariable.substr(1)
-          expect(tokens[1]).toHaveScopes ["source.powershell", "support.constant.automatic.powershell"]
-
-  describe "Escaped characters", ->
-    # TODO: add `--%` upon resolution of SublimeText/PowerShell#104
-    escapedCharacters = [
-      "`n", "`\"", "`\'", "`a", "`b", "`r", "`t", "`f", "`0", "`v", "``"
-    ]
-
-    it "tokenizes escaped characters", ->
-      for character in escapedCharacters
-        {tokens} = grammar.tokenizeLine character
-        expect(tokens[0].value).toEqual character
-        expect(tokens[0]).toHaveScopes ["source.powershell", "constant.character.escape.powershell"]
-
-  describe "Constants", ->
-    describe "Constant values in kilobytes, megabytes, and gigabytes", ->
-      constants = [ "10GB", "53gb", "12MB", "128mb", "1000KB", "1200kb" ]
-
-      it "tokenizes constant value in bytes", ->
-        for constant in constants
-          {tokens} = grammar.tokenizeLine constant
-          for token in tokens
-            expect(token).toHaveScopes ["source.powershell", "constant.numeric.scientific.powershell"]
-
-    describe "Constant float values", ->
-      constants = [
-        "1.0", "0.89324", "123124235.2385923234"
-      ]
-
-      scientificConstants = [
-        "3.23e24", "2.33e-12", "9.11e+21", "21e6", "7e-12", "12e+24"
-      ]
-
-      it "tokenizes constant float values", ->
-        for constant in constants
-          {tokens} = grammar.tokenizeLine constant
-          expect(tokens[0].value).toEqual constant
-          expect(tokens[0]).toHaveScopes ["source.powershell", "support.constant.powershell", "constant.numeric.scientific.powershell"]
-
-      it "tokenizes scientific numbers", ->
-        for scientificConstant in scientificConstants
-          {tokens} = grammar.tokenizeLine scientificConstant
-          expect(tokens[0]).toHaveScopes ["source.powershell", "support.constant.powershell", "constant.numeric.scientific.powershell"]
-          expect(tokens[1].value.substr(0, 1)).toBe "e"
-          expect(tokens[1]).toHaveScopes ["source.powershell", "constant.numeric.scientific.powershell", "keyword.operator.math.powershell"]
-          expect(tokens[2]).toHaveScopes ["source.powershell", "support.constant.powershell", "constant.numeric.scientific.powershell"]
-
-    describe "Constant hexadecimal values", ->
-      constants = [ "0x1234", "0x1FF2", "0xff2e" ]
-
-      it "tokenizes constant hexadecimal integer values", ->
-        for constant in constants
-          {tokens} = grammar.tokenizeLine constant
-          expect(tokens[0].value).toEqual "0x"
-          expect(tokens[0]).toHaveScopes ["source.powershell", "constant.numeric.hexadecimal.powershell", "keyword.operator.math.powershell"]
-          expect(tokens[1].value).toEqual constant.substr(2)
-          expect(tokens[1]).toHaveScopes ["source.powershell", "constant.numeric.hexadecimal.powershell", "support.constant.powershell"]
-
-  # TODO: Fix these later. They seem to highlight correctly but the tests are weird
-  xdescribe "Types", ->
-    types = [ "[string]", "[Int32]", "[System.Diagnostics.Process]"]
-
-    it "tokenizes type annotations", ->
-      for type in types
-        {tokens} = grammar.tokenizeLine type
-        expectedType = type.substr(1, type.length - 2)
-        expect(tokens[0].value).toEqual "["
-        expect(tokens[0]).toHaveScopes ["source.powershell", "storage.type.powershell", "punctuation.storage.type.begin.powershell"]
-        expect(tokens[1].value).toEqual expectedType
-        expect(tokens[1]).toHaveScopes ["source.powershell", "storage.type.powershell"]
-        expect(tokens[2].value).toEqual "]"
-        expect(tokens[2]).toHaveScopes ["source.powershell", "punctuation.storage.type.end.powershell"]
-
-  describe "Escape characters", ->
-
-    it "escapes variables", ->
-      {tokens} = grammar.tokenizeLine("`$a")
-      expect(tokens[0].value).toBe "`$"
-      expect(tokens[0]).toHaveScopes ["source.powershell", "constant.character.escape.powershell"]
-
-    it "escapes any character", ->
-      {tokens} = grammar.tokenizeLine("`_")
-      expect(tokens[0].value).toBe '`'
-      expect(tokens[0]).toHaveScopes ["source.powershell", "keyword.operator.other.powershell"]
-
-    it "escapes single quotes within a string", ->
-      {tokens} = grammar.tokenizeLine("$command = \'.\\myfile.ps1 -param1 `\'$myvar`\' -param2 whatever\'")
-      expect(tokens[7].value).toBe '\''
-      expect(tokens[7]).toHaveScopes ["source.powershell", "string.quoted.single.powershell"]
-
-    it "escapes double quotes within a string", ->
-      {tokens} = grammar.tokenizeLine("$command = \".\\myfile.ps1 -param1 `\"$myvar`\" -param2 whatever\"")
-      expect(tokens[7].value).toBe '`"'
-      expect(tokens[7]).toHaveScopes ["source.powershell", "constant.character.escape.powershell", "string.quoted.double.powershell"]
-
-  describe "Line continuations", ->
-
-    it "considers a backtick followed by a newline as a line continuation", ->
-      {tokens} = grammar.tokenizeLine("`\n")
-      expect(tokens[0].value).toEqual("`")
-      expect(tokens[0]).toHaveScopes ["source.powershell", "keyword.operator.other.powershell"]
-
-  describe "indentation", ->
-    editor = null
-
-    beforeEach ->
-      editor = atom.workspace.buildTextEditor()
-      editor.setGrammar(grammar)
-
-    expectPreservedIndentation = (text) ->
-      editor.setText(text)
-      editor.autoIndentBufferRows(0, text.split("\n").length - 1)
-      expect(editor.getText()).toBe text
-
-    it "preserves indentation", ->
-      indentFixturesFolder = path.join(__dirname, "fixtures", "indents")
-
-      fixtures = for fixture in fs.readdirSync(indentFixturesFolder)
-        fs.readFileSync(path.join(indentFixturesFolder, fixture), 'utf8')
-
-      for fixture in fixtures
-        expectPreservedIndentation fixture


Use => for clearer code

Use => for clearer code

--- lib/iridium/casperjs/lib/iridium/qunit_adapter.coffee
+++ lib/iridium/casperjs/lib/iridium/qunit_adapter.coffee
@@ -1,54 +1,54 @@
-currentTest = {}
-startTime = null
+@currentTest = {}
+@startTime = null

-QUnit.testStart (context) ->
-  currentTest = {}
-  currentTest.name = context.name
-  currentTest.assertions = 0
-  currentTest.backtrace = []
-  startTime = (new Date()).getTime()
+QUnit.testStart (context) =>
+  @currentTest = {}
+  @currentTest.name = context.name
+  @currentTest.assertions = 0
+  @currentTest.backtrace = []
+  @startTime = (new Date()).getTime()

-QUnit.log (context) ->
+QUnit.log (context) =>
   if context.result
-    currentTest.assertions++
+    @currentTest.assertions++
     return

   stackTrace = []
-  currentTest.backtrace = []
+  @currentTest.backtrace = []

   # qunit handles exceptions in a werid way. It prepends "Died"
   # to the stacktrace and shoves that in message
   if context.message.match(/^Died/)
-    currentTest.error = true
-    currentTest.message = context.source
+    @currentTest.error = true
+    @currentTest.message = context.source
     stackTrace = context.message

   # General Assertion Error
   else if context.message
-    currentTest.assertions++
-    currentTest.failed = true
-    currentTest.message = context.message
+    @currentTest.assertions++
+    @currentTest.failed = true
+    @currentTest.message = context.message
     stackTrace = context.source

   # Failed expectations
   else if context.expected
-    currentTest.failed = true
-    currentTest.message = "Expected: #{context.expected}, Actual: #{context.actual}"
+    @currentTest.failed = true
+    @currentTest.message = "Expected: #{context.expected}, Actual: #{context.actual}"
     stackTrace = context.source

   # format the backtrace accordingly
   for line in stackTrace.split("\n")
     matches = line.match(/(file:\/\/|https?:\/\/|\/.+:\d+)/)
     if matches
-      currentTest.backtrace.push matches[1]
+      @currentTest.backtrace.push matches[1]
     else
-      currentTest.backtrace.push line
+      @currentTest.backtrace.push line

-QUnit.testDone (context) ->
-  currentTest.time = (new Date()).getTime() - startTime
-  window.logger.message(currentTest)
+QUnit.testDone (context) =>
+  @currentTest.time = (new Date()).getTime() - @startTime
+  window.logger.message(@currentTest)

-QUnit.done (context) ->
+QUnit.done (context) =>
   window.unitTestsDone = true

 QUnit.config.autorun = false


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/number_extensions.coffee
+++ test/number_extensions.coffee
@@ -113,7 +113,8 @@
   points = [
     Point(1, 0)
     Point(0, 1)
-    Point(-1)
+    Point(-1, 0)
+    Point
   ]
   4.circularPoints (p, i) ->
     ok p.equals(points[i])


:white_check_mark: for search-occurrence

--- spec/occurrence-spec.coffee
+++ spec/occurrence-spec.coffee
@@ -258,7 +258,7 @@

     beforeEach ->
       searchEditor = vimState.searchInput.editor
-      searchEditorElement = searchEditor.element
+      searchEditorElement = vimState.searchInput.editorElement
       jasmine.attachToDOM(getView(atom.workspace))
       settings.set('incrementalSearch', true)
       set
@@ -728,6 +728,70 @@
             xxx: ooo: XXX: ooo xxx: ooo:
             """

+    describe "search occurrence", ->
+      [searchEditor, searchEditorElement] = []
+      beforeEach ->
+        searchEditor = vimState.searchInput.editor
+        searchEditorElement = vimState.searchInput.editorElement
+        jasmine.attachToDOM(getView(atom.workspace))
+        settings.set('incrementalSearch', true)
+        set
+          text: """
+          ooo: xxx: ooo
+          !!!: ooo: xxx:
+          ooo: xxx: ooo:
+          """
+          cursor: [0, 0]
+
+        runs ->
+          ensure 'g o',
+            occurrenceText: ['ooo', 'ooo', 'ooo', 'ooo', 'ooo']
+        waitsFor ->
+          editorElement.classList.contains('has-occurrence')
+
+      describe "tab, shift-tab", ->
+        it "search next/previous occurrence marker", ->
+          keystroke 'tab'
+          rawKeystroke('tab enter', searchEditorElement)
+          ensure cursor: [1, 5]
+
+          keystroke 'tab'
+          rawKeystroke('tab enter', searchEditorElement)
+          ensure cursor: [2, 10]
+
+          keystroke 'shift-tab'
+          rawKeystroke('shift-tab enter', searchEditorElement)
+          ensure cursor: [1, 5]
+
+          keystroke 'shift-tab'
+          rawKeystroke('shift-tab enter', searchEditorElement)
+          ensure cursor: [0, 0]
+
+      describe "space can clear preset-marker", ->
+        it "clear preset-occurrence and move to next", ->
+          keystroke 'tab'
+          rawKeystroke('tab space tab enter', searchEditorElement)
+          ensure cursor: [2, 10], occurrenceCount: 4
+
+          ensure 'g U i p',
+            text: """
+            OOO: xxx: OOO
+            !!!: ooo: xxx:
+            OOO: xxx: OOO:
+            """
+
+        it "clear preset-occurrence and move to previous", ->
+          keystroke 'shift-tab'
+          rawKeystroke('shift-tab space shift-tab enter', searchEditorElement)
+          ensure cursor: [0, 10], occurrenceCount: 4
+
+          ensure 'g U i p',
+            text: """
+            OOO: xxx: OOO
+            !!!: OOO: xxx:
+            ooo: xxx: OOO:
+            """
+
     describe "explict operator-modifier o and preset-marker", ->
       beforeEach ->
         set


Fix `for`, `for-each` tests

Fix `for`, `for-each` tests

--- spec/powershell-spec.coffee
+++ spec/powershell-spec.coffee
@@ -160,7 +160,7 @@
           {tokens} = grammar.tokenizeLine("for($i=0;i<10;$i++) { echo $i }")

         it "should highlight 'for'", ->
-          expect(tokens[0]).toEqual value: "for", scopes: ["source.powershell","keyword.control.flow.powershell"]
+          expect(tokens[0]).toEqual value: "for", scopes: ["source.powershell","keyword.control.powershell"]

       describe "'ForEach' statements", ->
         tokens = null
@@ -170,11 +170,11 @@

         it "should tokenize 'ForEach'", ->
           expect(tokens[0].value).toEqual "foreach"
-          expect(tokens[0]).toHaveScopes ["keyword.control.flow.powershell"]
+          expect(tokens[0]).toHaveScopes ["source.powershell", "keyword.control.powershell"]

         it "should tokenize 'in'", ->
           expect(tokens[5].value).toEqual "in"
-          expect(tokens[5]).toHaveScopes ["keyword.control.flow.powershell"]
+          expect(tokens[5]).toHaveScopes ["source.powershell", "keyword.control.powershell"]

       describe "Try-Catch-Finally statements", ->
         tokens = null


update test

update test

--- spec/package-card-spec.coffee
+++ spec/package-card-spec.coffee
@@ -76,7 +76,6 @@
     jasmine.attachToDOM(card.element)

     expect(card.refs.loginLink.textContent).toBe(authorName)
-    expect(card.refs.loginLink.href).toBe("https://atom.io/users/#{authorName}")

   describe "when the package is not installed", ->
     it "shows the settings, uninstall, and disable buttons", ->
@@ -536,7 +535,7 @@
             notifications = atom.notifications.getNotifications()
             expect(notifications.length).toBe 1
             notif = notifications[0]
-
+
             expect(notif.options.detail).toBe "1.0.0 -> 1.1.0"
             expect(notif.options.buttons.length).toBe(2)


CommentView: add options into settings menu

--- client/Social/Activity/views/comments/commentlistitemview.coffee
+++ client/Social/Activity/views/comments/commentlistitemview.coffee
@@ -117,7 +117,7 @@
       icon           : yes
       delegate       : this
       iconClass      : "arrow"
-      menu           : @settingsMenu data
+      menu           : @settingsMenu data, options
       callback       : (event)=> button.contextMenu event

   getBody:(data)->
@@ -200,12 +200,13 @@
     else if force
       @setTemplate @pistachio()

-  settingsMenu:(data)->
-    menu =
-      'Edit'     :
-        callback : => @showEditCommentForm data
-      'Delete'   :
-        callback : => @confirmDeleteComment data
+  settingsMenu:(data, options={})->
+    menu = {}
+    if options.edit
+      menu['Edit']   = callback : => @showEditCommentForm data
+    if options.delete
+      menu['Delete'] = callback : => @confirmDeleteComment data
+    return menu

   pistachio:->
     """


Uncomment this to get message list correctly in avatar area

--- client/app/Applications/Inbox.kdapplication/AppController.coffee
+++ client/app/Applications/Inbox.kdapplication/AppController.coffee
@@ -23,7 +23,7 @@
     callback()

   fetchMessages:(options, callback)->
-    #KD.whoami().fetchMail? options, callback
+    KD.whoami().fetchMail? options, callback

   fetchAutoCompleteForToField:(inputValue,blacklist,callback)->
     KD.remote.api.JAccount.byRelevance inputValue,{blacklist},(err,accounts)->


Only log debug messages when updating/deleting messages

--- src/message.coffee
+++ src/message.coffee
@@ -63,9 +63,10 @@
       "channel": @channel,
       "text": new_text
     }
-    @_client.logger.debug "Sending message change request"
-    @_client.logger.debug params
-    if @ts then @_client._apiCall "chat.update", params, @_onUpdateMessage
+    if @ts
+      @_client.logger.debug "Sending message change request"
+      @_client.logger.debug params
+      @_client._apiCall "chat.update", params, @_onUpdateMessage

   _onUpdateMessage: (data) ->
     @_client.logger.debug data
@@ -75,9 +76,10 @@
       "ts": @ts,
       "channel": @channel,
     }
-    @_client.logger.debug "Sending message delete request"
-    @_client.logger.debug params
-    if @ts then @_client._apiCall "chat.delete", params, @_onDeleteMessage
+    if @ts
+      @_client.logger.debug "Sending message delete request"
+      @_client.logger.debug params
+      @_client._apiCall "chat.delete", params, @_onDeleteMessage

   _onDeleteMessage: (data) ->
     @_client.logger.debug data


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -122,7 +122,7 @@
   @param {Number} borderWidth Width of the meter's border
   @param {String} color Color of the meter's inner rectangle
   @param {String} nameColor Color of the property name displayed above the meter
-  @param {String} font - Size and style of the meter's font
+  @param {String} font Size and style of the meter's font
     height - Height of the meter
     position - An x, y object representing the position of the meter
     radius - Border radius of the meter


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -112,7 +112,7 @@
     text: 'Boss Health'
     width: 150

-  # => Sets up a health meter, using all the configuration op
+  # => Sets up a health meter, using all the configuration options
   </pre></code>

   @name meter


fixing typo

fixing typo

spotted by @angrave

--- src/methods.coffee
+++ src/methods.coffee
@@ -254,7 +254,7 @@
       return

     if @access_flags.abstract
-      runtime_state.java_throw rs.get_bs_class('Ljava/lang/Error;'), "called abstract method: #{@full_signature()}"
+      runtime_state.java_throw runtime_state.get_bs_class('Ljava/lang/Error;'), "called abstract method: #{@full_signature()}"

     # Finally, the normal case: running a Java method
     ms.push(sf = new runtime.StackFrame(this,params,[]))


Add supporting test specs for tryOneRow and tryScalar

--- specs/db/database.spec.coffee
+++ specs/db/database.spec.coffee
@@ -1,8 +1,23 @@
 h = require('../test-helper')
+async = h.async
+
 fs = require('fs')

 env = "development"
 database = null
+
+tmpTable = """
+DECLARE @names TABLE(
+    FirstName VARCHAR(50),
+    LastName VARCHAR (50)
+)
+
+INSERT INTO @names VALUES ('Vincent','Vega')
+INSERT INTO @names VALUES  ('Jules','Winnfield')
+INSERT INTO @names VALUES  ('Mia','Wallace')
+INSERT INTO @names VALUES  ('Marsellus','Wallace')
+
+"""

 describe('Database', () ->
     it('should have a configuration object', () ->
@@ -30,6 +45,32 @@
         )
     )

+    it('tryScalar should behave as scalar with a unitary resultset', (done) ->
+        query = "SELECT 42"
+        database.tryScalar(query, (err, r) ->
+            done(err) if err
+            r.should.eql(42)
+            done()
+        )
+    )
+
+    it('should allow empty resultsets when using tryScalar', (done) ->
+        query = "SELECT 42 WHERE 1 = 0"
+        database.tryScalar(query, (err, r) ->
+            done(err) if err
+            done("Resultset should be null") if r?
+            done()
+        )
+    )
+
+    it('should raise an error when tryScalar finds more than 1 row', (done) ->
+        query = "#{tmpTable} SELECT FirstName FROM @names WHERE LastName = 'Wallace'"
+        database.tryScalar(query, (err, r) ->
+            err.should.match(/^Too many rows returned/)
+            done()
+        )
+    )
+
     it('should get query rows', (done) ->
         stmt = "SELECT 1 AS test"
         database.allRows(stmt, (err, data) ->
@@ -37,4 +78,30 @@
             done()
         )
     )
+
+    it('tryOneRow should behave as oneRow with a unitary resultset', (done) ->
+        query = "#{tmpTable} SELECT FirstName, LastName FROM @names WHERE LastName = 'Winnfield'"
+        database.tryOneRow(query, (err, r) ->
+            done(err) if err
+            r.should.eql({ FirstName: 'Jules', LastName: 'Winnfield' })
+            done()
+        )
+    )
+
+    it('should allow empty resultsets when using tryOneRow', (done) ->
+        query = "#{tmpTable} SELECT FirstName, LastName FROM @names WHERE FirstName = 'Pumpkin'"
+        database.tryOneRow(query, (err, r) ->
+            done(err) if err
+            done("Resultset should be null") if r?
+            done()
+        )
+    )
+
+    it('should raise an error when tryOneRow finds more than 1 row', (done) ->
+        query = "#{tmpTable} SELECT FirstName, LastName FROM @names WHERE LastName = 'Wallace'"
+        database.tryOneRow(query, (err, r) ->
+            err.should.match(/^Too many rows returned/)
+            done()
+        )
+    )
 )


Stack list: show "Remove from Sidebar" button for team default stack

--- client/home/lib/stacks/components/stacktemplateitem/index.coffee
+++ client/home/lib/stacks/components/stacktemplateitem/index.coffee
@@ -12,8 +12,7 @@
     unless template.get 'inUse'
       return ADD TO SIDEBAR

-    unless template.get 'isDefault'
-      return REMOVE FROM SIDEBAR
+    return REMOVE FROM SIDEBAR

   render: ->


cleared up snapshot CTA phrasing

cleared up snapshot CTA phrasing

--- client/landing/app/CommonViews/opinions/opinionviewheader.coffee
+++ client/landing/app/CommonViews/opinions/opinionviewheader.coffee
@@ -112,7 +112,7 @@

   updateRemainingText:=>
     if not @parent? or  @parent.constructor is DiscussionActivityOpinionView
-      @allItemsLink.updatePartial "View entire Discussion"
+      @allItemsLink.updatePartial "View all Answers"
     else
       remainingOpinions = @getData().repliesCount-@getDelegate().items.length
       if (remainingOpinions)<@maxCommentToShow


teams: login: copy change

teams: login: copy change

--- client/landing/site.landing/coffee/team/tabs/teamlogintab.coffee
+++ client/landing/site.landing/coffee/team/tabs/teamlogintab.coffee
@@ -48,9 +48,9 @@
     return  unless domains

     @inviteDesc.updatePartial if domains.length > 1
-      "If you have an email address from one of these domains #{domainsPartial}, you can join here."
-    else "If you have an email address from #{domains.first}, you can join here."
       domainsPartial = KD.utils.getAllowedDomainsPartial domains
+      "If you have an email address from one of these domains #{domainsPartial}, you can join here."
+    else "If you have a #{domains.first} email address, you can join here."

   pistachio: ->


Call correct function

Call correct function

--- bokehjs/test/models/transforms/linear_interpolator_transform.coffee
+++ bokehjs/test/models/transforms/linear_interpolator_transform.coffee
@@ -32,7 +32,7 @@
       expect(mapper.v_compute([0, 2, 5])).to.be.deep.equal new Float64Array [10, 14, 20]

     it "should map to a Float64Array", ->
-      expect(mapper.v_map_to_target([-1,0,5,10,11])).to.be.instanceof Float64Array
+      expect(mapper.v_compute([-1,0,5,10,11])).to.be.instanceof Float64Array

   describe "creation with inline ranges", ->
     mapper = generate_interpolator_inline()
@@ -48,4 +48,4 @@
       expect(mapper.v_compute([0, 2, 5])).to.be.deep.equal new Float64Array [10, 14, 20]

     it "should map to a Float64Array", ->
-      expect(mapper.v_map_to_target([-1,0,5,10,11])).to.be.instanceof Float64Array
+      expect(mapper.v_compute([-1,0,5,10,11])).to.be.instanceof Float64Array


Added fill() method to NDArray class.

Added fill() method to NDArray class.

--- src/ndarray.coffee
+++ src/ndarray.coffee
@@ -239,6 +239,8 @@
       be equal to @see{ndim} property

     @return [int] flattened position
+
+    TODO: testing with more than 1 dimension
     ###
     flatPosition: (p) ->

@@ -249,6 +251,19 @@
         f = 0
         for d in [0...@ndim]
             f += @stride[d]*p[d]
+
+
+    ###
+    Fill the array with a given constant value
+
+    @param [dtype] value fill value
+    ###
+    fill: (value) ->
+
+        for n in [0...@length]
+            @data[n] = value
+
+

 ###
 Creates a 1D array of elements in sequences from start to stop with step increments


limit display variations in duration time

--- js/libs/time.coffee
+++ js/libs/time.coffee
@@ -99,11 +99,9 @@
       display_minutes = "0" + display_minutes

     if hours > 0
-      "#{hours}:#{display_minutes}"
-    else if minutes >= 1
-      "#{minutes}:#{display_seconds}"
+      "#{hours}:#{display_minutes}:#{display_seconds}"
     else
-      "#{seconds}s"
+      "#{display_minutes}:#{display_seconds}"

   as_estimated_duration: (duration) =>
     seconds = Math.floor(duration / 1000)


misc cleanup on settings model

misc cleanup on settings model

--- public/dreamcatcher/models/settings.coffee
+++ public/dreamcatcher/models/settings.coffee
@@ -1,18 +1,3 @@
-# ORIGINAL
-# $.Model 'Dreamcatcher.Models.Settings',{
-#
-#   update: ( sharingLevel, success, error ) ->
-#     $.ajax {
-#       type: 'put'
-#       url: '/user.json'
-#       dataType: 'json'
-#       data:
-#         'user[default_sharing_level]': parseInt sharingLevel
-#     }
-#
-# },
-# {}
-
 $.Model 'Dreamcatcher.Models.Settings',{

   update: ( params, success, error ) ->


blind fix(?)

blind fix(?)

--- js/views/map.coffee
+++ js/views/map.coffee
@@ -16,7 +16,7 @@
       "orientationchange resize pageshow": "updateMap"
       "tap .category-filter": "categories"
       "pagehide": "removeTooltips"
-      "tap": "removeTooltips"
+      "tap a": "removeTooltips"

     mapElement: "map"
     routeLayer: null


Add dummy commands prior to package activation so they appear in palette

Fixes #3846

--- src/package.coffee
+++ src/package.coffee
@@ -338,7 +338,9 @@
     for selector, commands of @getActivationCommands()
       for command in commands
         do (selector, command) =>
-          atom.commands.commandRegistered(command)
+          # Add dummy command so it appears in menu.
+          # The real command will be registered on package activation
+          @activationCommandSubscriptions.add atom.commands.add selector, command, ->
           @activationCommandSubscriptions.add(atom.commands.onWillDispatch (event) =>
             return unless event.type is command
             currentTarget = event.target


factored out coupling the query model with the search results collection

--- core/app/backbone/views/autocompleted_add_to_channel_view.coffee
+++ core/app/backbone/views/autocompleted_add_to_channel_view.coffee
@@ -1,4 +1,11 @@
 #= require ./generic/text_input_view
+searchCollection = (type)->
+  model = new Backbone.Model text: ''
+  collection = new type()
+  model.on 'change', -> collection.searchFor model.get('text')
+
+  [model, collection]
+
 class window.AutoCompletedAddToChannelView extends Backbone.Marionette.Layout
   tagName: "div"
   className: "add-to-channel"
@@ -18,11 +25,10 @@
       collection: @collection
       mainView: this

-    @model = new Backbone.Model text: ''
-    @model.on 'change', => @autoCompleteCurrentValue()
+    [@model, @search_collection] = searchCollection(TopicSearchResults)
+
     @_text_input_view = new TextInputView model: @model

-    @search_collection = new TopicSearchResults()
     @filtered_search_collection = collectionDifference(TopicSearchResults,
       'slug_title', @search_collection, @collection)

@@ -76,7 +82,3 @@
   enable: ->
     @$el.removeClass("disabled")
     @_text_input_view.enable()
-
-  autoCompleteCurrentValue: ->
-    searchValue = @model.get('text')
-    @search_collection.searchFor searchValue


fixed Model.User.Configuration error

fixed Model.User.Configuration error

--- app/assets/javascripts/controller.coffee
+++ app/assets/javascripts/controller.coffee
@@ -66,28 +66,28 @@

       #ScaleTrianglesPlane
-      "l" : -> View.scaleTrianglesPlane -User.Configuration.scaleValue
-      "k" : -> View.scaleTrianglesPlane User.Configuration.scaleValue
+      "l" : -> View.scaleTrianglesPlane -Model.User.Configuration.scaleValue
+      "k" : -> View.scaleTrianglesPlane Model.User.Configuration.scaleValue

       #Move
-      "w" : -> View.move [0, User.Configuration.moveValue, 0]
-      "s" : -> View.move [0, -User.Configuration.moveValue, 0]
-      "a" : -> View.move [User.Configuration.moveValue, 0, 0]
-      "d" : -> View.move [-User.Configuration.moveValue, 0, 0]
-      "space" : -> View.move [0, 0, User.Configuration.moveValue]
-      "shift + space" : -> View.move [0, 0, -User.Configuration.moveValue]
+      "w" : -> View.move [0, Model.User.Configuration.moveValue, 0]
+      "s" : -> View.move [0, -Model.User.Configuration.moveValue, 0]
+      "a" : -> View.move [Model.User.Configuration.moveValue, 0, 0]
+      "d" : -> View.move [-Model.User.Configuration.moveValue, 0, 0]
+      "space" : -> View.move [0, 0, Model.User.Configuration.moveValue]
+      "shift + space" : -> View.move [0, 0, -Model.User.Configuration.moveValue]

       #Rotate in distance
-      "left"  : -> View.yawDistance User.Configuration.rotateValue
-      "right" : -> View.yawDistance -User.Configuration.rotateValue
-      "up"    : -> View.pitchDistance -User.Configuration.rotateValue
-      "down"  : -> View.pitchDistance User.Configuration.rotateValue
+      "left"  : -> View.yawDistance Model.User.Configuration.rotateValue
+      "right" : -> View.yawDistance -Model.User.Configuration.rotateValue
+      "up"    : -> View.pitchDistance -Model.User.Configuration.rotateValue
+      "down"  : -> View.pitchDistance Model.User.Configuration.rotateValue

       #Rotate at centre
-      "shift + left"  : -> View.yaw User.Configuration.rotateValue
-      "shift + right" : -> View.yaw -User.Configuration.rotateValue
-      "shift + up"    : -> View.pitch -User.Configuration.rotateValue
-      "shift + down"  : -> View.pitch User.Configuration.rotateValue
+      "shift + left"  : -> View.yaw Model.User.Configuration.rotateValue
+      "shift + right" : -> View.yaw -Model.User.Configuration.rotateValue
+      "shift + up"    : -> View.pitch -Model.User.Configuration.rotateValue
+      "shift + down"  : -> View.pitch Model.User.Configuration.rotateValue

       #misc keys
       "n" : -> Helper.toggle()
@@ -106,8 +106,8 @@
   # for more buttons look at Input.Gamepad
   initGamepad : ->
     @input.gamepad = new Input.Gamepad(
-        "ButtonA" : -> View.move [0, 0, User.Configuration.moveValue]
-        "ButtonB" : -> View.move [0, 0, -User.Configuration.moveValue]
+        "ButtonA" : -> View.move [0, 0, Model.User.Configuration.moveValue]
+        "ButtonB" : -> View.move [0, 0, -Model.User.Configuration.moveValue]
         "LeftStickX" : View.yawDistance
         "LeftStickY" : View.pitchDistance

@@ -134,39 +134,39 @@

   #Customize Options
   setMoveValue : (value) ->
-    User.Configuration.moveValue = (Number) value
-
-    User.Configuration.push()
+    Model.User.Configuration.moveValue = (Number) value
+
+    Model.User.Configuration.push()

   setRotateValue : (value) ->
-    User.Configuration.rotateValue = (Number) value
-    User.Configuration.push()
+    Model.User.Configuration.rotateValue = (Number) value
+    Model.User.Configuration.push()

   setScaleValue : (value) ->
-    User.Configuration.scaleValue = (Number) value
-    User.Configuration.push()
+    Model.User.Configuration.scaleValue = (Number) value
+    Model.User.Configuration.push()

   setMouseRotateValue : (value) ->
-    User.Configuration.mouseRotateValue = (Number) value
-    User.Configuration.push()
+    Model.User.Configuration.mouseRotateValue = (Number) value
+    Model.User.Configuration.push()

   setMouseInversionX : (value) ->
     if value is true
-      User.Configuration.mouseInversionX = 1
-    else
-      User.Configuration.mouseInversionX = -1
-    User.Configuration.push()
+      Model.User.Configuration.mouseInversionX = 1
+    else
+      Model.User.Configuration.mouseInversionX = -1
+    Model.User.Configuration.push()

   setMouseInversionY : (value) ->
     if value is true
-      User.Configuration.mouseInversionY = 1
-    else
-      User.Configuration.mouseInversionY = -1
-    User.Configuration.push()
+      Model.User.Configuration.mouseInversionY = 1
+    else
+      Model.User.Configuration.mouseInversionY = -1
+    Model.User.Configuration.push()

   setMouseActivity : (value) ->
-    User.Configuration.mouseActive = value
-    User.Configuration.push()
+    Model.User.Configuration.mouseActive = value
+    Model.User.Configuration.push()
     if value is false
       @input.mouse.unbind()
       @input.mouse = null
@@ -174,8 +174,8 @@
       @initMouse()

   setKeyboardActivity : (value) ->
-    User.Configuration.keyboardActive = value
-    User.Configuration.push()
+    Model.User.Configuration.keyboardActive = value
+    Model.User.Configuration.push()
     if value is false
       @input.keyboard.unbind()
       @input.keyboard = null
@@ -183,8 +183,8 @@
       @initKeyboard()

   setGamepadActivity : (value) ->
-    User.Configuration.gamepadActive = value
-    User.Configuration.push()
+    Model.User.Configuration.gamepadActive = value
+    Model.User.Configuration.push()
     if value is false
       @input.gamepad.unbind()
       @input.gamepad = null
@@ -192,8 +192,8 @@
       @initGamepad()

   setMotionSensorActivity : (value) ->
-    User.Configuration.motionsensorActive = value
-    User.Configuration.push()
+    Model.User.Configuration.motionsensorActive = value
+    Model.User.Configuration.push()
     if value is false
       @input.deviceorientation.unbind()
       @input.deviceorientation = null


formatting

formatting

--- app/assets/javascripts/helpers.js.coffee
+++ app/assets/javascripts/helpers.js.coffee
@@ -13,10 +13,11 @@

 patternsToRegex = (obj) ->
   matchObj =
-    bare: if obj.bare
-            obj.bare.map toRegex
-          else
-            []
+    bare:
+      if obj.bare
+        obj.bare.map toRegex
+      else
+        []
     except:
       if obj.except
         toRegex(pattern[1 ..]) for pattern in obj.except when pattern.length > 1


Make internalsocket.post() emit legacy-compatible connect/disconnect events when needed

--- src/lib/InternalSocket.coffee
+++ src/lib/InternalSocket.coffee
@@ -87,7 +87,9 @@
   # sending semantics single IP objects can be sent without open/close brackets.
   post: (data) ->
     data = @dataDelegate() if data is undefined and typeof @dataDelegate is 'function'
+    @emitEvent 'connect', @ if data.type is 'data' and @brackets.length is 0
     @handleSocketEvent 'data', data, false
+    @emitEvent 'disconnect', @ if data.type is 'data' and @brackets.length is 0

   # ## Information Packet grouping
   #
@@ -215,10 +217,9 @@
       @brackets.push ip.data

     if ip.type is 'closeBracket'
-      unless @brackets.length
-        # Last bracket was closed, we're disconnected
-        # If we were already disconnected, no need to disconnect again
-        return if @brackets.length is 0
+      # Last bracket was closed, we're disconnected
+      # If we were already disconnected, no need to disconnect again
+      return if @brackets.length is 0
       # Add group name to bracket
       ip.data = @brackets.pop()

@@ -227,9 +228,7 @@

     # Emit the legacy event
     legacyEvent = @ipToLegacy ip
-    @emitEvent 'connect', @ if ip.type is 'data' and @brackets.length is 0 and autoConnect
     @emitEvent legacyEvent.event, legacyEvent.payload
-    @emitEvent 'disconnect', @ if ip.type is 'data' and @brackets.length is 0 and autoConnect

 exports.InternalSocket = InternalSocket


Condition fix

Condition fix

--- src/js/faber/controllers/EditorController.coffee
+++ src/js/faber/controllers/EditorController.coffee
@@ -18,8 +18,7 @@
   componentsService.init(faberConfig.components or [])

   validateElementBlock = (block) ->
-    if $scope.validateBlock block
-      if block.blocks?.length > 0
+    if $scope.validateBlock block and block.blocks?.length > 0
         block.blocks = validateImported block.blocks
     return block


make things work more with chrome dev tools

 - the .less filename shows up in styles inspector
 - clicking on it takes you to the file
 - editing there and saving triggers grunt's reload and applies

Inline editing of styles doesn't work though - as soon as you edit,
the file/line goes away


Correct logic to add build and tag information to Saucelabs


test($Gruntfile): Add tests for all supported browsers


fix(grunt): index version not bumped

fix(grunt): index version not bumped

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -330,6 +330,16 @@
           {
             from: /(theme:)( +)(.+)/g
             to: "$1$2<%= config.amsf_theme_new %>"
+          }
+        ]
+
+      amsf__site__update_version:
+        src: ["<%= config.app %>/_pages/index.html"]
+        dest: "<%= config.app %>/_pages/index.html"
+        replacements: [
+          {
+            from: /("amsf-version">)\d+\.\d+\.\d+/g
+            to: "$1<%= config.pkg.version %>"
           }
         ]

@@ -383,15 +393,12 @@

     bump:
       options:
-        files: [
-          "package.json"
-          "<%= config.app %>/_pages/index.html"
-        ]
+        files: ["package.json"]
+        updateConfigs: ["pkg"]
         commitMessage: 'chore: release v%VERSION%'
         commitFiles: ["-a"]
         tagMessage: 'chore: create tag %VERSION%'
         push: false
-        regExp: true

   grunt.registerTask "reset", "Reset user availability", (target) ->
     grunt.config.set "replace.availability.replacements.0.to", "$1 true"
@@ -451,6 +458,7 @@
     grunt.task.run [
       "bump-only:#{type or 'patch'}"
       "conventionalChangelog"
+      "replace:amsf__site__update_version"
       "bump-commit"
     ]


* minor change

* minor change

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -52,7 +52,7 @@
           'src/**/*.js'
           'test/*.coffee'
         ]
-
+

   #grunt.loadTasks('tasks')


check for dependencies existance

check for dependencies existance

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -1,3 +1,5 @@
+fs = require('fs')
+
 module.exports = (grunt) ->
   files_3d = [
     "bower_components/stats.js/src/Stats.js"
@@ -68,6 +70,13 @@
     "bower_components/socket.io-client/dist/socket.io.js"
   ]

+  all_2d_files = files_2d.concat(extras)
+  all_3d_files = files_3d.concat(extras)
+
+  for file in all_3d_files.concat(all_2d_files)
+    unless fs.existsSync(file)
+      throw "ERROR: #{file} does not exist!"
+
   grunt.initConfig
     pkg: grunt.file.readJSON("package.json")
     shell:
@@ -88,8 +97,8 @@
           mangle: false
           beautify: true
         files: [
-          "build/coffee-engine-2d.js": files_2d.concat(extras)
-          "build/coffee-engine-3d.js": files_3d.concat(extras)
+          "build/coffee-engine-2d.js": all_2d_files
+          "build/coffee-engine-3d.js": all_3d_files
         ]

   grunt.registerTask "compile:coffee:watch", ["shell:compile-coffee-watch"]


it seems the bacon.when dispatch needs a re-impl now

--- src/Bacon.coffee
+++ src/Bacon.coffee
@@ -820,6 +820,7 @@
         subscribe.apply(this, [sink])

 Bacon.dependsOn = (a,b) ->
+  # TODO: the allDeps thing could be pre-calculated and optimized for quick lookup
   if a == b
     return false
   deps = a.allDeps
@@ -836,15 +837,11 @@
   independent = (waiter) ->
     !_.any(waiters, ((other) -> Bacon.dependsOn(waiter.obs, other.obs)))
   whenDone = (obs, f) ->
-    if !_.any(waiters, (w) -> w.obs==obs)
-      waiters.push {obs, f}
+    waiters.push {obs, f}
   flush = ->
     if waiters.length
       #console.log "flushing, waiters", (_.map _.toString, (_.map ((x) -> x.obs), waiters))
       ok = _.filter independent, waiters
-
-      # TODO: still something amiss. Doesn't block updates..
-      #
       firstIndex = _.indexWhere waiters, independent
       throw "no independent observable" if firstIndex < 0
       {f} = waiters.splice(firstIndex, 1)[0]
@@ -1041,6 +1038,7 @@
             source.push e.value
             if source.sync
               UpdateBarrier.whenDone resultStream, ->
+                # TODO this needs re-impl to work correctly
                 for p in pats
                    if match(p)
                      val = -> p.f(sources[i.index].consume() for i in p.ixs ...)


add log message

add log message

--- src/alias.coffee
+++ src/alias.coffee
@@ -24,6 +24,7 @@
   config = process.env.HUBOT_GROUP_ALIAS

   if !config
+    console.log "Warning: Configuration HUBOT_GROUP_ALIAS is not defined."
     return

   groups = config.split(';')


brain内でadapterがnullで、起動時にエラーが発生していたので修正。

--- src/brain.coffee
+++ src/brain.coffee
@@ -12,8 +12,8 @@
       talks:    { }
       _private: { }

-    @getUsers = robot.adapter.users
-    @getTalks = robot.adapter.talks
+    @getUsers = -> robot.adapter.users
+    @getTalks = -> robot.adapter.talks

     @autoSave = true

@@ -99,7 +99,8 @@
   #
   # Returns an Array of User objects.
   users: ->
-    if getUsers? then @data.users = @getUsers()
+    getUsers = @getUsers()
+    if getUsers? then @data.users = getUsers()
     @data.users

   # Public: Get a User object given a unique identifier.
@@ -159,7 +160,8 @@
   #
   # Returns an Array of Talk objects.
   rooms: ->
-    if getTalks? then @data.talks = @getTalks()
+    getTalks = @getTalks()
+    if getTalks? then @data.talks = getTalks()
     @data.talks


Add a default prompt. Prevents the server from appearing to hang.

--- src/child.coffee
+++ src/child.coffee
@@ -50,10 +50,10 @@
     # Send back the generated prompt.
     # If no prompt is generated, we fall back to the environment's existing prompt.
     # As a result, by registering no prompt sections, Impromptu can be used strictly
-    # for its background updating capabilities.
+    # for its background updating capabilities. If PS1 exists, falls back to "`pwd` $".
     process.send
       type: 'end'
-      data: results || env.PS1 || ''
+      data: results || env.PS1 || "#{process.cwd()} $ "

     # Run the background update.
     # We synchronously perform the background update to optimize for speed of prompt


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/clamp.coffee
+++ src/clamp.coffee
@@ -4,7 +4,7 @@

   self.bind "update", ->
     for property in I.clamps
-      property.value = property.value.cl
+      property.value = property.value.clamp(property.min)

       {approachBy, target} = cooldownOptions


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/color.coffee
+++ src/color.coffee
@@ -1571,7 +1571,7 @@
 ]

 names.each (element) ->
-  lookup[element[1].toLowerCase().replace(/ /g, "")] = Color(element[0])
+  lookup[element[1].toLowerCase().replace(/ /g, "")] = element[0]

 log lookup


forgot to include lodash

forgot to include lodash

--- cmdblu/sms.coffee
+++ cmdblu/sms.coffee
@@ -2,6 +2,7 @@
 Device = require './src/device'
 {spawn} = require 'child_process'
 request = require 'request'
+_ = require 'lodash'

 device_uuid = process.env.DEVICE_UUID
 device_token = process.env.DEVICE_TOKEN


Require Directory from pathwatcher

Require Directory from pathwatcher

--- src/project.coffee
+++ src/project.coffee
@@ -8,9 +8,9 @@
 {Emitter, Subscriber} = require 'emissary'
 Serializable = require 'serializable'
 TextBuffer = require 'text-buffer'
+{Directory} = require 'pathwatcher'

 Editor = require './editor'
-Directory = require './directory'
 Task = require './task'
 Git = require './git'


s/repositoryPromisesByDirectory/repositoryPromisesByPath/g

--- src/project.coffee
+++ src/project.coffee
@@ -43,7 +43,7 @@
     # to either a {Repository} or null. Ideally, the {Directory} would be used
     # as the key; however, there can be multiple {Directory} objects created for
     # the same real path, so it is not a good key.
-    @repositoryPromisesByDirectory = new Map();
+    @repositoryPromisesByPath = new Map();

     # Note that the GitRepositoryProvider is registered synchronously so that
     # it is available immediately on startup.
@@ -132,7 +132,7 @@
   # * `null` if no repository can be created for the given directory.
   repositoryForDirectory: (directory) ->
     path = directory.getRealPathSync()
-    promise = @repositoryPromisesByDirectory.get(path)
+    promise = @repositoryPromisesByPath.get(path)
     unless promise
       promises = @repositoryProviders.map (provider) ->
           provider.repositoryForDirectory directory
@@ -142,13 +142,13 @@
           repo = repos[0] or null

           # If no repository is found, remove the entry in for the directory in
-          # @repositoryPromisesByDirectory in case some other RepositoryProvider is
+          # @repositoryPromisesByPath in case some other RepositoryProvider is
           # registered in the future that could supply a Repository for the
           # directory.
           if repo is null
-            @repositoryPromisesByDirectory.delete path
+            @repositoryPromisesByPath.delete path
           repo
-      @repositoryPromisesByDirectory.set(path, promise)
+      @repositoryPromisesByPath.set(path, promise)
     promise

   ###


Comment fixes.

Comment fixes.

--- src/runtime.coffee
+++ src/runtime.coffee
@@ -443,11 +443,12 @@
         )
       )
       @meta_stack().push(nf)
-      # Setup the stack with the method.
+      # Add the arguments to the stack.
       @push_array args
-      # Call the method.
+      # Setup dat stack frame
       method.setup_stack(@)
-      # Push ourselves back into the execution loop.
+      # Push ourselves back into the execution loop
+      # to call the method!
       @run_until_finished((->), false, @stashed_done_cb)

   run_until_finished: (setup_fn, no_threads, done_cb) ->


Fixing an issue in the dumper where we assume stack/local objects are nonnull. Adding the ability to dump on internal JVM errors.

--- src/runtime.coffee
+++ src/runtime.coffee
@@ -58,8 +58,8 @@
       name: @name
       pc: @pc
       native: @native
-      stack: (obj.serialize?(visited) ? obj for obj in @stack)
-      locals: (obj.serialize?(visited) ? obj for obj in @locals)
+      stack: (obj?.serialize?(visited) ? obj for obj in @stack)
+      locals: (obj?.serialize?(visited) ? obj for obj in @locals)
     }

 # Contains all the mutable state of the Java program.
@@ -334,6 +334,7 @@
     else
       error "\nInternal JVM Error:", e
       error e.stack if e?.stack?
+      @dump_state() if jvm.dump_state
       done_cb false
     return


added batch to fetch githubarchive

added batch to fetch githubarchive

--- src/service.coffee
+++ src/service.coffee
@@ -378,3 +378,22 @@
     scala: 'scala'
   map[lang]

+getYesterday = ->
+  now = new Date
+  year = now.getFullYear()
+  month = "0#{now.getMonth() + 1}".slice(-2)
+  date = "0#{now.getDate() - 1}".slice(-2)
+  time = now.toLocaleTimeString().substr(0, 2) * 1
+  "#{year}-#{month}-#{date}-#{time}"
+
+archiveRule = new schedule.RecurrenceRule()
+archiveRule.hour = [new schedule.Range(0, 23)]
+archiveRule.minute = [10]
+
+schedule.scheduleJob archiveRule, ->
+  datetime = getYesterday()
+  service.fetchGithubArchive datetime, (err) ->
+    if err?
+      logger.error "fetcharchive", {err: err}
+    else
+      logger.info 'fetched githubarchive', {datetime: datetime}


attach conversation error handle

attach conversation error handle

--- src/sm-cmds.coffee
+++ src/sm-cmds.coffee
@@ -229,6 +229,8 @@
                     result = _.concat(result, data.messages)
                     latest_ts = _.last(data.messages).ts if data.messages and data.messages.length > 1
                     cb1(null)
+                  .catch (r) ->
+                    resp.reply "Fail to attaching converstaion to Service Manager Incident #{id}.\n*Reason*: #{r}"
               (err)->
                 cb(null, result)
             )


SubtreeMixin: factor reducer map out to a closure

--- src/subtree.coffee
+++ src/subtree.coffee
@@ -10,35 +10,35 @@
 	parentComponent[key] = component
 	childPath = parentComponent.path.concat( [ key ] )
 	component.__willMount(parentComponent.store, childPath, parentComponent)
-	parentComponent.__reducerMap[key] = component.reducer
+	# Return the reducer
+	component.reducer

 applyDescriptor = (parentComponent, key, descriptor) ->
 	attachComponent(parentComponent, key, createComponent(descriptor))

 export SubtreeMixin = {
 	componentWillMount: ->
+		# Sanity check that our component supports subtrees
 		if process.env.NODE_ENV isnt 'production'
 			invariant(typeof @getSubtree is 'function', "redux-component of type #{@displayName} (mounted at location #{@path}) is using SubtreeMixin, but does not have a getSubtree() method.")

+		# Get the subtree structure
 		subtree = @getSubtree()
-		@__reducerMap = {}
-		# Conjure child components
+		# Conjure child components and gather their reducers
+		__reducerMap = {}
 		for key, descriptor of subtree
-			applyDescriptor(@, key, descriptor)
-
-		# Create reducer
-		reducer = combineReducers(@__reducerMap)
+			__reducerMap[key] = applyDescriptor(@, key, descriptor)
+		# Create composite reducer for parent component
+		reducer = combineReducers(__reducerMap)
 		@getReducer = -> reducer

 		# Monkey-patch didMount to call subtree didMounts in the right order.
 		myDidMount = @__originalDidMount = @componentDidMount
-		@componentDidMount = =>
-			@[k]?.componentDidMount?() for k of @__reducerMap
+		@componentDidMount = ->
+			@[k]?.componentDidMount?() for k of __reducerMap
 			myDidMount?.call(@)

 	componentWillUnmount: ->
-		# Undo monkey-patch.
-		delete @__reducerMap
 		@componentDidMount = @__originalDidMount
 }


Update victory.coffee

Update victory.coffee

removed a few images.

--- src/victory.coffee
+++ src/victory.coffee
@@ -36,7 +36,6 @@
   "http://rack.3.mshcdn.com/media/ZgkyMDEzLzA4LzA1L2U1L2NvbGJlcnRyZXBvLjVjNmYxLmdpZgpwCXRodW1iCTg1MHg1OTA-CmUJanBn/710824a0/764/colbert-report.jpg",
   "http://rack.1.mshcdn.com/media/ZgkyMDEzLzA4LzA1LzYyL2FuY2hvcm1hbi42NjJkYS5naWYKcAl0aHVtYgk4NTB4NTkwPgplCWpwZw/009ee80f/1c0/anchorman.jpg",
   "http://rack.3.mshcdn.com/media/ZgkyMDEzLzA4LzA1LzFmL2hhcnJ5cG90dGVyLjYxNjYzLmdpZgpwCXRodW1iCTg1MHg1OTA-CmUJanBn/db79fc85/147/harry-potter.jpg",
-  "http://www.velocityindiana.org/wp-content/uploads/2014/08/bff.gif",
   "http://i.kinja-img.com/gawker-media/image/upload/s--_dYUH9jW--/18vvnw5taib2ogif.gif",
   "https://31.media.tumblr.com/e844e0925dbd8699ddb68fb2408d61b6/tumblr_mqrjr2oH0G1r3kc9vo1_250.gif",
   "http://i.kinja-img.com/gawker-media/image/upload/s--0wAEcaN4--/c_fit,fl_progressive,q_80,w_636/bdbtzjrhyyuarpfbqksn.gif",


Cosmetic fixes on scroll handler of taskboard header and body.

--- app/coffee/modules/taskboard/main.coffee
+++ app/coffee/modules/taskboard/main.coffee
@@ -168,10 +168,11 @@
             toggleText(target, ["Hide statistics", "Show statistics"]) # TODO: i18n
             $rootscope.$broadcast("taskboard:graph:toggle-visibility")

-        taskboardTableBodyDom = $el.find(".taskboard-table-body")
-        taskboardTableHeaderInnerDom = $el.find(".taskboard-table-header .taskboard-table-inner")
-        taskboardTableBodyDom.scroll () ->
-            taskboardTableHeaderInnerDom.css('left', -1 * taskboardTableBodyDom.scrollLeft())
+        tableBodyDom = $el.find(".taskboard-table-body")
+        tableBodyDom.on "scroll", (event) ->
+            target = angular.element(event.currentTarget)
+            headerdom = $el.find(".taskboard-table-header .taskboard-table-inner")
+            headerdom.css("left", -1 * target.scrollLeft())

         $scope.$on "$destroy", ->
             $el.off()


fixing coffeescript

fixing coffeescript

--- widgets/graph/graph.coffee
+++ widgets/graph/graph.coffee
@@ -27,7 +27,7 @@
     @graph.series[0].data = @get('points') if @get('points')

     labels = ['now', '-1h', '-2h', '-3h', '-4h', '-5h', '-6h', '-7h', '-8h', '-9h'];
-    x_axis = new Rickshaw.Graph.Axis.Time( { graph: @graph, tickFormat: function(x) { return labels[x]; } } )
+    x_axis = new Rickshaw.Graph.Axis.Time(graph: @graph, tickFormat: (x) -> labels[x])
     y_axis = new Rickshaw.Graph.Axis.Y(graph: @graph, tickFormat: Rickshaw.Fixtures.Number.formatKMBT)
     @graph.render()


Remove old hive conf

Remove old hive conf

--- actions/hdp_hive_.coffee
+++ actions/hdp_hive_.coffee
@@ -11,11 +11,6 @@
   ctx.config.hdp.hive_conf_dir ?= '/etc/hive/conf'
   ctx.config.hdp.hive_site ?= {}
   ctx.config.hdp.hive_site['hive.metastore.uris'] ?= "thrift://#{srv2_host}:9083"
-  # Overwrite hdp properties with unworkable values
-  # Note, next 3 lines cause failure when hdp_krb5 is run independently
-  # ctx.config.hdp.hive_site['hive.metastore.kerberos.principal'] ?= ''
-  # ctx.config.hdp.hive_site['hive.server2.authentication.kerberos.principal'] ?= ''
-  # ctx.config.hdp.hive_site['hive.metastore.uris'] ?= ''
   # To prevent memory leak in unsecure mode, disable [file system caches](https://cwiki.apache.org/confluence/display/Hive/Setting+up+HiveServer2)
   # , by setting following params to true
   ctx.config.hdp.hive_site['fs.hdfs.impl.disable.cache'] ?= 'false'


Update DiplomatView.coffee (#3750)

Update DiplomatView.coffee (#3750)

--- app/views/contribute/DiplomatView.coffee
+++ app/views/contribute/DiplomatView.coffee
@@ -96,7 +96,7 @@
     'es-419': ['2xG', 'Federico Tomas', 'Jesús Ruppel', 'Mariano Luzza', 'Matthew Burt']       # español (América Latina), Spanish (Latin America)
     'es-ES': ['3rr3s3v3n', 'Anon', 'DanielRodriguezRivero', 'Matthew Burt', 'OviiiOne', 'Pouyio', 'Vindurrin']        # español (ES), Spanish (Spain)
     'zh-HANS': ['1c7', 'Adam23', 'BonnieBBS', 'Cheng Zheng', 'Vic020', 'ZephyrSails', 'julycoolwind', 'onion7878', 'spacepope', 'yangxuan8282', 'yfdyh000']      # 简体中文, Chinese (Simplified)
-    'zh-HANT': ['Adam23', 'gintau']      # 繁體中文, Chinese (Traditional)
+    'zh-HANT': ['Adam23', 'gintau', 'shuwn']      # 繁體中文, Chinese (Traditional)
     'zh-WUU-HANS': []  # 吴语, Wuu (Simplified)
     'zh-WUU-HANT': ['benojan']  # 吳語, Wuu (Traditional)
     fr: ['Anon', 'Armaldio', 'ChrisLightman', 'Elfisen', 'Feugy', 'MartinDelille', 'Oaugereau', 'Xeonarno', 'dc55028', 'jaybi', 'pstweb', 'veritable', 'xavismeh']             # français, French


Update Atom's config.cson.

Update Atom's config.cson.

--- roles/fedora_laptop/files/atom/config.cson
+++ roles/fedora_laptop/files/atom/config.cson
@@ -1,6 +1,8 @@
 "*":
   "activate-power-mode":
     autoToggle: false
+    comboMode:
+      enabled: false
   "autocomplete-plus": {}
   core:
     disabledPackages: [


canAddUser update to use owner and moderator roles instead of creator for adding users to a channel or private group

--- packages/rocketchat-ui-flextab/flex-tab/tabs/membersList.coffee
+++ packages/rocketchat-ui-flextab/flex-tab/tabs/membersList.coffee
@@ -57,7 +57,7 @@
 	canAddUser: ->
 		roomData = Session.get('roomData' + this._id)
 		return '' unless roomData
-		return roomData.t in ['p', 'c'] and roomData.u?._id is Meteor.userId()
+		return roomData.t in ['p', 'c'] and RoomModeratorsAndOwners.findOne({ rid: this._id, 'u._id': Meteor.userId(), roles: { $in: ['moderator','owner'] }})

 	autocompleteSettingsAddUser: ->
 		return {


social: temporarily fix troll users

social: temporarily fix troll users

--- workers/social/lib/social/models/account.coffee
+++ workers/social/lib/social/models/account.coffee
@@ -925,8 +925,12 @@
     callback null, @isExempt

   # returns troll users ids
+  #
+  # Adding a temporary limit of 100. We currently've 24 trolls, by the
+  # time this limit runs out we'll have switched to a scalable model of
+  # filtering troll users. SA
   @getExemptUserIds: (callback)->
-    JAccount.someData {isExempt:true}, {_id:1}, (err, cursor)->
+    JAccount.someData {isExempt:true}, {_id:1, limit:100}, {sort:_id:-1}, (err, cursor)->
       return callback err, null if err
       ids = []
       cursor.each (err, account)->


Let addTags works for JAccount

Let addTags works for JAccount

--- workers/social/lib/social/models/account.coffee
+++ workers/social/lib/social/models/account.coffee
@@ -196,7 +196,7 @@
   glanceMessages: secure (client, callback)->

   glanceActivities: secure (client, callback)->
-    @fetchActivities {'data.flags.glanced': $ne: yes}, (err, activities)->
+    @fetchActivities {'data.flags.glanced': $ne: yes}, (err, activities)->
       if err
         callback err
       else
@@ -325,11 +325,6 @@
     require('bongo').fetchChannel @getPrivateChannelName(), callback

   getPrivateChannelName:-> "private-#{@getAt('profile.nickname')}-private"
-
-  addTags: secure (client, tags, callback)->
-    Taggable::addTags.call @, client, tags, (err)->
-      if err then callback err
-      else callback null

   fetchMail:do ->
     collectParticipants = (messages, delegate, callback)->


first pass at better barres

first pass at better barres

--- lib/chord_diagram.coffee
+++ lib/chord_diagram.coffee
@@ -76,14 +76,31 @@
     ctx.strokeStyle = 'black'

   draw_barres = ->
+    ctx.fillStyle = 'black'
     for {fret, string, fret, string_count} in barres
-      {x: x1, y} = finger_coordinates(string: string, fret: fret)
-      {x: x2} = finger_coordinates(string: string + string_count - 1, fret: fret)
-      ctx.fillStyle = 'rgba(0,0,0, 0.5)'
+      {x: x1, y} = finger_coordinates {string, fret}
+      {x: x2} = finger_coordinates {string: string + string_count - 1, fret}
+      w = (x2 - x1)
+      ctx.save()
+      ctx.translate (x1 + x2) / 2, y - style.fret_height * .25
       ctx.beginPath()
-      ctx.arc x1, y, style.string_spacing / 2, Math.PI * 1/2, Math.PI * 3/2, false
-      ctx.arc x2, y, style.string_spacing / 2, Math.PI * 3/2, Math.PI * 1/2, false
+      do ->
+        ctx.save()
+        ctx.scale w, 10
+        ctx.arc 0, 0, style.string_spacing / 2 / 1/10, Math.PI, 0, false
+        ctx.restore()
+      do ->
+        ctx.save()
+        ctx.scale w, 14
+        ctx.arc 0, 0, style.string_spacing / 2 / 1/10, 0, Math.PI, true
+        ctx.restore()
       ctx.fill()
+      ctx.restore()
+      # ctx.fillStyle = 'rgba(0,0,0, 0.5)'
+      # ctx.beginPath()
+      # ctx.arc x1, y, style.string_spacing / 2, Math.PI * 1/2, Math.PI * 3/2, false
+      # ctx.arc x2, y, style.string_spacing / 2, Math.PI * 3/2, Math.PI * 1/2, false
+      # ctx.fill()

   draw_finger_positions = ->
     for position in positions
@@ -96,14 +113,17 @@
     fretted_strings = []
     fretted_strings[position.string] = true for position in positions
     closed_strings = (string for string in StringNumbers when not fretted_strings[string])
-    ctx.font = "#{style.closed_string_fontsize}pt Helvetica"
+    r = style.note_radius
     ctx.fillStyle = 'black'
-    label = 'x'
-    for string_number in closed_strings
-      m = ctx.measureText(label)
-      ctx.fillText label
-      , style.h_gutter + string_number * style.string_spacing - m.width / 2
-      , style.v_gutter + style.above_fretboard - style.fret_height * 0.5 + m.emHeightDescent
+    for string in closed_strings
+      {x, y} = finger_coordinates {string, fret: 0}
+      ctx.strokeStyle = 'black'
+      ctx.beginPath()
+      ctx.moveTo x - r, y - r
+      ctx.lineTo x + r, y + r
+      ctx.moveTo x - r, y + r
+      ctx.lineTo x + r, y - r
+      ctx.stroke()

   draw_chord_diagram_strings(ctx)
   draw_chord_diagram_frets(ctx)


Fix routing when root isn't "/"

Fix routing when root isn't "/"

--- src/marbles/history.js.coffee
+++ src/marbles/history.js.coffee
@@ -15,7 +15,11 @@
   getFragment: (fragment = window.location.pathname) =>
     fragment += search if search = window.location.search

-    fragment = fragment.substr(@options.root.length) if fragment.indexOf(@options.root) != -1
+    root = @options.root.replace(/([^\/])\/$/, '$1')
+
+    if fragment.indexOf(root) != -1
+      fragment = fragment.substr(root.length)
+
     fragment.replace(@regex.route_stripper, '')

   # start pushState handling