Fix and add more karma tests

Fix and add more karma tests

--- karma/test-controllers.coffee
+++ karma/test-controllers.coffee
@@ -663,6 +663,36 @@
   )

   #=======================================================================
+  # Tests for LabelController
+  #=======================================================================
+  describe('LabelController', () ->
+    LabelService = null
+    $scope = null
+
+    beforeEach(inject((_LabelService_) ->
+      LabelService = _LabelService_
+
+      $scope = $rootScope.$new()
+      $window.contextData = {label: test.tea}
+      $controller('LabelController', {$scope: $scope})
+    ))
+
+    it('onDeleteLabel', () ->
+      confirmModal = spyOnPromise($q, $scope, UtilsService, 'confirmModal')
+      deleteLabel = spyOnPromise($q, $scope, LabelService, 'delete')
+      spyOn(UtilsService, 'navigate')
+
+      $scope.onDeleteLabel()
+
+      confirmModal.resolve()
+      deleteLabel.resolve()
+
+      expect(LabelService.delete).toHaveBeenCalledWith(test.tea)
+      expect(UtilsService.navigate).toHaveBeenCalledWith('/org/home/#/labels')
+    )
+  )
+
+  #=======================================================================
   # Tests for PartnerController
   #=======================================================================
   describe('PartnerController', () ->
@@ -725,7 +755,7 @@
       deletePartner.resolve()

       expect(PartnerService.delete).toHaveBeenCalledWith(test.moh)
-      expect(UtilsService.navigate).toHaveBeenCalledWith('/partner/')
+      expect(UtilsService.navigate).toHaveBeenCalledWith('/org/home/#/partners')
     )
   )


Added ability to change the server log level with an environment variable.

--- src/Log.coffee
+++ src/Log.coffee
@@ -87,7 +87,7 @@
       console.timeEnd(name)

 # Allows setting the logging level via GET variable
-if typeof Window != 'undefined'
+if Window?
   logGet = Window.GET('log')
   if logGet
     Log.setLevel(logGet)
@@ -113,3 +113,8 @@
 if Meteor?
   # Log is already defined in the logging package, so we define a different global variable for now.
   Logger = Log
+  if Meteor.isServer
+    logLevel = process.env.LOG_LEVEL
+    if logLevel?
+      console.log('Log level:', logLevel)
+      Logger.setLevel(logLevel)


:bug: use non-standard date header because nginx

--- src/api.coffee
+++ src/api.coffee
@@ -31,7 +31,7 @@
 delay = (ms, fn) -> setTimeout(fn, ms)

 setNow = (jqXhr) ->
-  TimeActions.setFromString(jqXhr.getResponseHeader('Date'))
+  TimeActions.setFromString(jqXhr.getResponseHeader('X-App-Date'))

 apiHelper = (Actions, listenAction, successAction, httpMethod, pathMaker) ->
   listenAction.addListener 'trigger', (args...) ->


--- src/apm.coffee
+++ src/apm.coffee
@@ -111,7 +111,7 @@

     null

-  setupApmRcFile = ->
+  setupApmRcFile: ->
     rcPath = path.resolve(__dirname, '..', '.apmrc')
     cachePath = path.join(@getAtomDirectory(), '.apm')
     try


Fix unit routing logic.

Fix unit routing logic.

Implement home route.

--- src/app.coffee
+++ src/app.coffee
@@ -45,13 +45,20 @@
             @selected_events = options.selected_events
             @search_results = options.search_results
             window.debug_search_results = @search_results
+        reset: () ->
+            @units.reset []
+            @services.reset []
+            @selected_units.reset []
+            @selected_events.reset []
+            @search_results.reset []
         setUnits: (units) ->
             @services.set []
             @units.reset units.toArray()
         setUnit: (unit) ->
             @services.set []
             @units.reset [unit]
-
+        getUnit: (id) ->
+            return @units.get id
         selectUnit: (unit) ->
             @router.navigate "unit/#{unit.id}/"
             @_select_unit unit
@@ -159,14 +166,19 @@
                 @search_results.reset []

         render_unit: (id) ->
-            unit = new Models.Unit id: id
-            unit.fetch
-                success: =>
-                    @_select_unit unit
+            unit = @getUnit id
+            if unit?
+                @_select_unit unit
+            else
+                unit = new Models.Unit id: id
+                @setUnit unit
+                unit.fetch
+                    success: =>
+                        @_select_unit unit
         render_service: (id) ->
             console.log 'render_service', id
         render_home: ->
-            console.log 'home'
+            @reset()

     class AppRouter extends Backbone.Marionette.AppRouter
         appRoutes:


Additional parameter to stopSong (in coffeescript)

Add current_song parameter to stopSong method, which Turntable will now require to prevent issues of "double-skipping" when the current DJ skips a song at the same time an SU is forcing one.

--- src/bot.coffee
+++ src/bot.coffee
@@ -500,7 +500,7 @@

   stopSong: (callback) ->
-    rq = api: 'room.stop_song', roomid: @roomId
+    rq = api: 'room.stop_song', roomid: @roomId, current_song: @currentSongId
     @_send rq, callback


prevent selecting null object

prevent selecting null object

--- src/chz.coffee
+++ src/chz.coffee
@@ -38,7 +38,7 @@
       else if activeIndex == items.length and $scope.items.indexOf($scope.activeItem) < $scope.items.length - 1
         $scope.offset += d
         search($scope.prevSearch, 'down')
-      else
+      else if items[activeIndex]
         $scope.activeItem = items[activeIndex]

     search = (q, dir) ->


Added multi-file support to the -j option

--- src/cli.coffee
+++ src/cli.coffee
@@ -10,6 +10,27 @@
 handle_error = (err) -> console.log err.stack if err

 compile = (input_path, output_directory, js, namespace = 'templates') ->
+  if Array.isArray input_path
+    i = 0
+    body = ''
+    appendTemplate = ->
+      if i >= input_path.length
+        output = """
+          (function(){
+            this.#{namespace} || (this.#{namespace} = {});
+            #{body}
+          }).call(this);
+        """
+        write input_path[0], namespace, output, output_directory, '.js'
+      else
+        fs.readFile input_path[i], 'utf-8', (err, contents) ->
+          handle_error err
+          name = path.basename input_path[i], path.extname(input_path[i])
+          func = coffeecup.compile contents, options
+          body += "this.#{namespace}[#{JSON.stringify name}] = #{func};\n"
+          i += 1
+          appendTemplate()
+    return appendTemplate()
   fs.readFile input_path, 'utf-8', (err, contents) ->
     handle_error err

@@ -78,7 +99,10 @@
       coffeecup.render contents, options

   if args.length > 0
-    file = args[0]
+    if args.length > 1 and options.js
+      file = args[..]
+    else
+      file = args[0]

     if options.watch
       fs.watchFile file, {persistent: true, interval: 500}, (curr, prev) ->


fix typos

fix typos

--- src/cli.coffee
+++ src/cli.coffee
@@ -34,7 +34,7 @@
 fetchForPage = (cookieStore, pageNo) ->
   throw new Error("invalid pageNo: #{pageNo}") if pageNo < 0 or 6 < pageNo
   request
-    jar: jar
+    jar: cookieStore
     url: 'https://my.jcb.co.jp/iss-pc/member/details_inquiry/detail.html'
     qs:
       detailMonth: pageNo
@@ -76,7 +76,7 @@
         .then ({ label, amount } = {}) ->
           result[label] = amount if label?
         .then ->
-          deleyedResolve result, 500
+          delayedResolve result, 500
     , Promise.resolve {}
   .then (months) ->
     console.log months


Removed forgotten Esy.ui

Removed forgotten Esy.ui

--- src/esy.coffee
+++ src/esy.coffee
@@ -137,8 +137,6 @@
     filename = filepath.substr filepath.lastIndexOf('/') + 1
     return filename

-class Esy.ui
-
 class Esy.color

   hexToRgb: (hex) ->


Change where start.sh is in dockerfile

Change where start.sh is in dockerfile

--- src/gen.coffee
+++ src/gen.coffee
@@ -111,7 +111,7 @@
       else if parsed.python == '3'
         console.log 'WARN: You are using Python 3.0. All python cmd commands must be ran using "python3"'
         fs.appendFileSync @docker, @from+'python3.0\n'
-  @dockerfile = 'COPY ./instances/web /container/app\nCOPY tmp/container'+@id+'/start.sh /container/start.sh\nEXPOSE '+parsed.port+'\nCMD cd /container && sh ./start.sh'
+  @dockerfile = 'COPY ./instances/web /container/app\nCOPY .tubs/tub'+@id+'/start.sh /container/start.sh\nEXPOSE '+parsed.port+'\nCMD cd /container && sh ./start.sh'
   fs.appendFileSync @docker, @dockerfile
   console.log 'Preparing to start...'
   run('sh', ['~/.web/tubs/build.sh', '.tubs/tub'+@id+'/Dockerfile', 'webos/tub'+@id, parsed.public+':'+parsed.port, 'webos/tub'+@id])


* shim the defineProperty if no exists.

* shim the defineProperty if no exists.

--- src/defineProperty.coffee
+++ src/defineProperty.coffee
@@ -1,5 +1,11 @@
 isObject        = require './is/type/object'
 defineProperty  = Object.defineProperty
+if !defineProperty
+  defineProperty = (obj, key, descriptor)->
+    value = descriptor.value if descriptor
+    obj[key] = value
+    return
+

 module.exports  = (object, key, value, aOptions)->
   writable = true


make a category called config param to pass the configuration parameters to

--- src/donations-form.coffee
+++ src/donations-form.coffee
@@ -466,13 +466,11 @@
       $form.append $("<input type=\"hidden\" name=\"card_token\" />").val(token)

       fullConfig = $.extend(JSON.parse($("#donations-config").attr('defaults')), config)
-      addtionalParams = {}
-      $.extend(addtionalParams, { key : val} if key.substring(0,2) == "ak") for key, val of fullConfig

       req = $.ajax(
         url: "#{config['pathtoserver']}/charges"
         type: "post"
-        data: $.extend({}, $("#donation-form").serializeObject(), addtionalParams)
+        data: $.extend({}, $("#donation-form").serializeObject(), {'config' : addtionalParams})
       )

       req.done (response, textStatus, jqXHR) ->


* minor change

* minor change

--- test/normal-attribute-manager-test.coffee
+++ test/normal-attribute-manager-test.coffee
@@ -15,4 +15,3 @@

 test('NormalPropertyManager', Manager)
-


[update] Add and fix snippets.

[update] Add and fix snippets.

--- snippets/snippets.cson
+++ snippets/snippets.cson
@@ -1,31 +1,87 @@
 '.bve-map-2.02':
+  #自軌道の平面曲線
   'curve':
     'prefix': 'curve'
     'body': 'Curve'
-  'setCenter':
-    'prefix': '.SetCenter'
-    'body': '.SetCenter(${1:x});${2:}'
+    'description': '自軌道の平面曲線を表すマップ要素。'
+    'rightLabelHTML': '自軌道の平面曲線'
+
+  #自軌道の勾配
+  'gradient':
+    'prefix': 'gradient'
+    'body': 'Gradient'
+    'description': '自軌道の勾配を表すマップ要素。'
+    'rightLabelHTML': '自軌道の勾配'
+
+  #他軌道
+  'track':
+    'prefix': 'Track'
+    'body': 'Track[\'${1:trackKey}\']${2:}'
+    'description': '他軌道を表すマップ要素。'
+    'rightLabelHTML': '他軌道'
+  'position':
+    'prefix': '.Position'
+    'body': '.Position(${1:x},${2:y});${3:}'
+    'description': '現在の距離程における他軌道の位置を設定する。x: 自軌道からのx座標[m],y: 自軌道からのy座標[m]'
+    'rightLabelHTML': '他軌道'
+  #ストラクチャ
+  'structure':
+    'prefix': 'Structure'
+    'body': 'Structure[\'${1:structureKey}\']${2:}'
+    'description': 'ストラクチャを表すマップ要素。'
+    'rightLabelHTML': 'ストラクチャ'
+  'structure.put':
+    'prefix': '.Put'
+    'body': '.Put(\'${1:trackKey}\',${2:x},${3:y},${4:z},${5:rx},${6:ry},${7:rz},${8:tilt},${9:span});${10:}'
+    'description': 'ストラクチャを設置する。'
+    'rightLabelHTML': 'ストラクチャ'
+  'structure.put0':
+    'prefix': '.Put0'
+    'body': '.Put(\'${1:trackKey}\',${2:tilt},${3:span});${4:}'
+    'description': 'ストラクチャを設置する。'
+    'rightLabelHTML': 'ストラクチャ'
+  #連続ストラクチャ
+  'repeater':
+    'prefix': 'Repeater'
+    'body': 'Repeater[\'${1:repeaterKey}\']${2:}'
+    'description': '連続ストラクチャを表すマップ要素。'
+    'rightLabelHTML': '連続ストラクチャ'
+  'repeater.begin':
+    'prefix': '.Begin'
+    'body': '.Begin(\'${1:trackKey}\',${2:x},${3:y},${4:z},${5:rx},${6:ry},${7:rz},${8:tilt},${9:span},${10:interval},\'${11:structureKey}\');${12:}'
+    'description': 'ストラクチャの連続配置を現在の距離程から開始する。'
+    'rightLabelHTML': '連続ストラクチャ'
+  'repeater.begin0':
+    'prefix': '.Begin0'
+    'body': '.Begin0(\'${1:trackKey}\',${2:tilt},${3:span},${4:interval},\'${5:structureKey}\');${6:}'
+    'description': 'ストラクチャの連続配置を現在の距離程から開始する。'
+    'rightLabelHTML': '連続ストラクチャ'
+  #停車場
+  #閉塞
+  #地上信号機
+  #地上子
+  #速度制限
+  #先行列車
+  #光源
+  #霧効果
+  #風景描画距離
+  #運転台の明るさ
+  #軌道変位
+  #粘着特性
+  #音
+  #固定音源
+  #走行音
+  #フランジきしり音
+  #分岐器通過音
+  #他列車
+  #数学関数
+  #他マップの挿入
+  #その他
   'beginTransition':
     'prefix': '.BeginTransition'
     'body': '.BeginTransition();'
-  'track':
-    'prefix': 'Track'
-    'body': 'Track[\'${1:trackKey}\']${2:}'
-  'position':
-    'prefix': '.Position'
-    'body': '.Position(${1:x},${2:y});${3:}'
-  'repeater':
-    'prefix': 'Repeater'
-    'body': 'Repeater[\'${1:repeaterKey}\']${2:}'
-  'repeater.begin':
-    'prefix': '.Begin'
-    'body': '.Begin(\'${1:trackKey}\',${2:x},${3:y},${4:z},${5:rx},${6:ry},${7:rz},${8:tilt},${9:span},${10:interval},${11:structureKey});${12:}'
-  'repeater.begin0':
-    'prefix': '.Begin0'
-    'body': '.Begin0(\'${1:trackKey}\',${2:tilt},${3:span},${4:interval},${5:structureKey});${6:}'
-  'structure':
-    'prefix': 'Structure'
-    'body': 'Structure[\'${1:structureKey}\']${2:}'
+    'description': '緩和曲線,縦曲線,カントの逓減の遷移を現在の距離程から開始する。'
   'load':
     'prefix': '.Load'
     'body': '.Load(\'${1:filePath}\');${2:}'
+    'description': 'リストファイルを読み込む。各ファイルのキーを使用する前にこの構文を記述する必要がある。'


fixed typo

fixed typo

--- snippets/ts-react.cson
+++ snippets/ts-react.cson
@@ -56,7 +56,7 @@
       class ${1:ComponentName} extends React.Component {
         public render() {
           return (
-            ${2:Body}
+            ${3:Body}
           );
         }
       }
@@ -96,7 +96,7 @@
       class ${1:ComponentName} extends React.Component {
           public render() {
               return (
-                ${2:Body}
+                ${3:Body}
               );
           }
       }


:lizard:

:lizard:

--- scripts/fliptable.coffee
+++ scripts/fliptable.coffee
@@ -35,4 +35,8 @@
       '(/¯◡ ‿ ◡)/¯ ~ ┻━┻',
       '┻━┻ ︵ ლ(⌒-⌒ლ)',
     ]
-    msg.send msg.random flips
+
+    if /geckomuerto/i.test(msg.message.user.name.trim())
+      msg.send '┬─┬ ノ( ゜-゜ノ)',
+    else
+      msg.send msg.random flips


Be more aggressive in reusing/removing blank

Fixes #4744

--- web/volume/slot.coffee
+++ web/volume/slot.coffee
@@ -398,7 +398,6 @@
           else
             $scope.form.edit.$setPristine()

-        blank.fillData() if blank && this == blank
         $scope.playing = 0
         updateSelection()
         updatePlayerHeight()
@@ -649,6 +648,10 @@
           , (res) =>
             delete @file
             delete @progress
+            if !blank
+              blank = this
+            else if $.isEmptyObject(@data)
+              @removed()
             return
         return


some speedups but still ~1.5s to test a 4096-bit n

--- src/prime.iced
+++ src/prime.iced
@@ -17,6 +17,18 @@
 class Timer
   constructor : () -> @start = Date.now()
   stop : -> (Date.now() - @start)
+class Avg
+  constructor : () ->
+    @tot = 0
+    @n = 0
+  start : () ->
+    @_t = Date.now()
+  stop : () ->
+    s = (Date.now() - @_t)
+    console.log "ran in #{s}"
+    @tot += s
+    @n++
+  avg : -> @tot/@n

 #=================================================================

@@ -252,24 +264,26 @@
 # @param {BigInteger} n
 # @return {Boolean} true if the check succeeds and false otherwise.
 #
+fta = new Avg()
 fermat2_test = (n) ->
-  tmr = new Timer()
+  fta.start()
   t = nbv(1)
   bl = n.bitLength()
   bl--
   for i in [bl..0]
-    t = t.square()
+    t = t.modPowInt(2,n)
+    #t = t.square()

     # .t in jsbn is equivalent to _mp_size in GNU bigint.  _mp_size
     # is the "number of limbs" in the bigint
-    if t.t > n.t
-      t = t.mod(n)
+    #if t.t > n.t
+    #  t = t.mod(n)
     if n.testBit(i)
       t = t.shiftLeft(1)
   if t.compareTo(n) > 0
     t = t.mod(n)
   ret = (t.compareTo(nbv(2)) is 0)
-  console.log "ran in #{tmr.stop()}"
+  fta.stop()
   ret

 #--------------
@@ -457,7 +471,7 @@
   while go
     await srf.recharge defer()
     p = new BigInteger nbits, srf
-    p = prime_search p, 4 * sieve.length * nbits, sieve, iters
+    p = prime_search p, 2 * sieve.length * nbits, sieve, iters
     go = (p.compareTo(BigInteger.ZERO) is 0)
     console.log "iter #{i++} -> #{go}"
   cb p
@@ -470,7 +484,8 @@
 exports.miller_rabin = miller_rabin
 exports.random_prime = random_prime

-await random_prime 3072, 32, defer p
+await random_prime 4096, 30, defer p
 console.log p.toString()
+console.log "avg -> #{fta.avg()}"
 process.exit -1


Code review

Code review

--- MediaAdminBundle/Resources/public/coffee/MediaModalView.coffee
+++ MediaAdminBundle/Resources/public/coffee/MediaModalView.coffee
@@ -8,7 +8,7 @@
   events:
     'click .mediaModalClose': 'closeModal'
     'click .media-modal-menu-folder' : 'showFolder'
-    'click .ajax-add': 'openFormMedia'
+    'click .ajax-add': 'openForm'
     'click .media-modal-menu-new-folder' : 'openFormFolder'

   initialize: (options) ->
@@ -67,16 +67,12 @@
         $('.modal-body-menu', currentModal).html response
     return

-  openFormMedia: (event) ->
-    event.preventDefault()
-    @openForm event
-
   openFormFolder: (event) ->
-    event.preventDefault()
     @updateNavigation($(event.target))
     @openForm event

   openForm: (event) ->
+    event.preventDefault()
     displayLoader $(".modal-body-content", @$el)
     folderName = $(".js-widget-title", @$el).text()
     domContainer = $(".modal-body-content", @$el)


trying to replicate what happens IRL but no dice

--- spec/installed-package-view-spec.coffee
+++ spec/installed-package-view-spec.coffee
@@ -61,3 +61,20 @@
       view = new InstalledPackageView(pack, new PackageManager())
       keybindingsTable = view.find('.package-keymap-table tbody')
       expect(keybindingsTable.children().length).toBe 0
+
+  fit "displays the correct enablement state", ->
+    availablePackageView = null
+
+    waitsForPromise ->
+      atom.packages.activatePackage('status-bar')
+
+    runs ->
+      expect(atom.packages.isPackageActive('status-bar')).toBe(true)
+      atom.packages.disablePackage('status-bar')
+      expect(atom.packages.isPackageDisabled('status-bar')).toBe(true)
+
+      pack = atom.packages.getLoadedPackage('status-bar')
+      view = new InstalledPackageView(pack, new PackageManager())
+      availablePackageView = view.find('.available-package-view')
+      console.log(availablePackageView)
+      expect(availablePackageView.hasClass('disabled')).toBe(true)


negative includes 0

negative includes 0

--- scripts/sentiment.coffee
+++ scripts/sentiment.coffee
@@ -134,7 +134,7 @@
     output

   onlyNegative = (list) ->
-    _.filter(list || [], (x) -> (x.score_average < 0))
+    _.filter(list || [], (x) -> (x.score_average <= 0))

   onlyPositive = (list) ->
     _.filter(list || [], (x) -> (x.score_average > 0))


Use grunt-coffeelint’s (v0.0.8) all new configFile option.

--- gruntfile.coffee
+++ gruntfile.coffee
@@ -62,9 +62,8 @@
                 src: ['<%= yeoman.app %>/scripts/*{.js,.js.map}']

         coffeelint:
-            # `grunt-coffeelint` does not support this natively
-            # [yet](https://github.com/vojtajina/grunt-coffeelint/pull/23).
-            options: grunt.file.readJSON('.coffeelintrc')
+            options:
+                configFile: '.coffeelintrc'
             all: [
                 '*.coffee',
                 '<%= yeoman.test %>/*.coffee'


Refactor

Refactor

--- lib/assets/javascripts/views/post/repost.js.coffee
+++ lib/assets/javascripts/views/post/repost.js.coffee
@@ -30,7 +30,7 @@
     @parentView().hide()

   post: =>
-    TentStatus.Models.Post.instances.all[@post_cid]
+    TentStatus.Models.Post.find(cid: @post_cid)

   context: (post) =>
     parent_post = @parentPost()


Add index for Messages pinned

Add index for Messages pinned

--- packages/rocketchat-lib/server/models/Messages.coffee
+++ packages/rocketchat-lib/server/models/Messages.coffee
@@ -11,6 +11,7 @@
 		@tryEnsureIndex { 'msg': 'text' }
 		@tryEnsureIndex { 'file._id': 1 }, { sparse: 1 }
 		@tryEnsureIndex { 'mentions.username': 1 }, { sparse: 1 }
+		@tryEnsureIndex { 'pinned': 1 }, { sparse: 1 }

 	# FIND ONE


:art: Cleanup

:art: Cleanup

--- spec/jumpy-spec.coffee
+++ spec/jumpy-spec.coffee
@@ -1,7 +1,6 @@
 path = require 'path'
 {Views, Commands} = require 'atom'
 {$} = require 'space-pen'
-_ = require 'lodash'

 NUM_ALPHA_TEST_WORDS = 26 * 3


add Workout,WorkoutHeader, and WorkoutsMeta classes

--- app/pub/workout.coffee
+++ app/pub/workout.coffee
@@ -1,23 +1,69 @@
 WORKOUT_SEPARATOR = '\n\n'

 Workouts = (text) ->
-	this._workouts = text.split(WORKOUT_SEPARATOR)
+	this._chunks = text.split(WORKOUT_SEPARATOR)
+	meta = this._meta = new WorkoutsMeta()
+	this._workouts = this._chunks.reduce((workouts, workoutChunk, idx) ->
+		w = new Workout(workoutChunk)
+		if w.isValid()
+			workouts.push(w)
+		else
+			meta.add(workoutChunk)
+
+		workouts
+	, [])
 	this

 Workouts.prototype.getAll = () ->
 	this._workouts.slice()

+Workouts.prototype.getAllMeta = () ->
+	this._meta.getAll()
+
+WorkoutsMeta = (textChunks) ->
+	this._meta = []
+	this
+
+WorkoutsMeta.prototype.add = (metaText) ->
+	this._meta.push(metaText)
+
+WorkoutsMeta.prototype.getAll = () ->
+	this._meta.slice()
+
+Workout = (workoutText) ->
+	this._chunks = workoutText.split('\n')
+	this._header = new WorkoutHeader(this._chunks[0])
+	this._exercises = this._chunks.slice(1)
+	this
+
+Workout.prototype.isValid = () ->
+	this._header.isValid()
+
+WorkoutHeader = (headerText) ->
+	DATE_REGEXP = /^(\d+\/\d+\/\d+)\s/
+	this._workoutDate = headerText.match(DATE_REGEXP)?[1]
+	this
+
+WorkoutHeader.prototype.isValid = () ->
+	!!this._workoutDate
+
+Exercises = (exercises) -> this

 WorkoutsView = (workouts) ->
-	html = ''
+	html = []

-	for workout in workouts.getAll()
-		html +=
-			'
' +
-				workout +
-			'
'
+	html.push workouts.getAllMeta().map (metaSection) ->
+		'
' +
+			metaSection +
+		'
'

-	this._html = html
+
+	html.push workouts.getAll().map (workout) ->
+		'
' +
+			workout +
+		'
'
+
+	this._html = html.join('')
 	this

 WorkoutsView.prototype.render = () ->


regex match dataset/view on preview

regex match dataset/view on preview

--- server/code/index.coffee
+++ server/code/index.coffee
@@ -192,10 +192,10 @@
   req.logout()
   resp.redirect '/'

-app.get '/preview/:box', (req, resp) ->
+app.get new RegExp('/preview/(\\w+)/?(\\w+)?/?'), (req, resp) ->
   resp.render 'preview',
     user: JSON.stringify req.user.effective
-    boxName: req.params.box
+    boxName: req.params[0]
     boxServer: process.env.CU_BOX_SERVER

 # API!


re-add locations table for syncing

re-add locations table for syncing

--- _source/lib/collections/location.coffee
+++ _source/lib/collections/location.coffee
@@ -1,7 +1,7 @@

-# Apollos.locations = new Mongo.Collection "locations"
+Apollos.locations = new Mongo.Collection "locations"

-Apollos.generateSchema "location",
+location = Apollos.generateSchema
   locationId:
     type: Number
     decimal: false
@@ -38,3 +38,5 @@
   postalCode:
     type: String
     optional: true
+
+Apollos.locations.attachSchema location


Get meta tags from html in wrong order

Get meta tags from html in wrong order

--- packages/rocketchat-oembed/server/server.coffee
+++ packages/rocketchat-oembed/server/server.coffee
@@ -86,6 +86,9 @@
 		content.body.replace /<meta.*(?:name|property)=['"]([^'"]*)['"].*content=['"]([^'"]*)['"].*>/gmi, (meta, name, value) ->
 			metas[changeCase.camelCase(name)] = value

+		content.body.replace /<meta.*content=['"]([^'"]*)['"].*(?:name|property)=['"]([^'"]*)['"].*>/gmi, (meta, name, value) ->
+			metas[changeCase.camelCase(name)] = value
+
 		if metas.fragment is '!' and not withFragment?
 			return OEmbed.getUrlMeta url, true


Refactored application.

Refactored application.

--- app/scripts/app.coffee
+++ app/scripts/app.coffee
@@ -1,7 +1,7 @@
 class Task
 	constructor: (title, isDone = false) ->
-		@title = ko.observable(title);
-		@done = ko.observable(isDone);
+		@title = ko.observable(title)
+		@done = ko.observable(isDone)

 # Maps an object to a Task.
 Task.fromPOCO = (poco) ->
@@ -9,41 +9,34 @@
 	done = poco.done || false

 	return new Task title, done
+class AppViewModel
+    constructor: ->
+        @newTask = ko.observable new Task()
+        @tasks   = ko.observableArray([])

-class AppViewModel
-	constructor: ->
-		# This is required due to how scope works in JavaScript.
-		self = @
+    addTask: =>
+        title = @newTask().title()

-		self.newTask = ko.observable new Task()
+        # Adds a new task to the collection.
+        @tasks.push new Task title, false

-		self.tasks = ko.observableArray([])
+        # Clear task container.
+        @newTask.title('')

-		self.addTask = ->
+     fetch: (url = 'http://localhost:9000/demo_tasks.json') =>
+        $.getJSON url,
+            (data) ->
+                if data instanceof Array inst true
+                    throw 'Service should return an array.'

-			title = self.newTask().title()
-
-			self.tasks.push new Task title, false
-
-			# Clear title
-			self.newTask().title('')
-
-		self.fetch = (serviceUrl = 'http://localhost:9000/demo_tasks.json') ->
-			# Request JSON from serviceUrl
-			$.getJSON serviceUrl,
-				(data) ->
-					if data instanceof Array isnt true
-						throw 'Service should return an array.'
-
-					data.forEach (t) ->
-						self.tasks.push Task.fromPOCO t
-				,
-				(err) ->
-					throw err
-
+                data.forEach (t) ->
+                    @tasks.push Task.fromPOCO t
+            ,
+            (err) ->
+                throw {msg: 'Unable to fetch tasks.', inner: err}

 window.App = new AppViewModel()

 App.fetch()

-ko.applyBindings App+ko.applyBindings App


fix indentation

fix indentation

--- src/index.coffee
+++ src/index.coffee
@@ -74,7 +74,7 @@
       throw new Error()

   write: ->
-      throw new Error()
+    throw new Error()

 class Text extends Node
   constructor: (options) ->


Improved initFetch behaviour.

Improved initFetch behaviour.

--- app/assets/javascripts/app/models/_application_model.js.coffee
+++ app/assets/javascripts/app/models/_application_model.js.coffee
@@ -327,12 +327,13 @@

     # fetch init collection
     if param.initFetch is true
-      @one 'refresh', (collection) =>
-        @initFetchActive = false
-        callback(collection)
       if !@initFetchActive
-        @initFetchActive = true
+        @one 'refresh', (collection) =>
+          @initFetchActive = true
+          callback(collection)
         @fetch( {}, { clear: true } )
+      else
+        callback( @all() )

     # return key
     key


Fixed duration ignore date

Fixed duration ignore date

--- lib/actions/views/logs.coffee
+++ lib/actions/views/logs.coffee
@@ -34,7 +34,8 @@
   $.get "/logs/json/log/" + base + "/" + name + "/" + id, (data) ->
     clear()
     document.title = "Logs for " + base + "/" + name + "/" + id
-    data.date = ignore_date = TimeFormat.formatDateTime(data.start * 1000)
+    data.date = TimeFormat.formatDateTime(data.start * 1000)
+    ignore_date = TimeFormat.formatDate(data.start * 1000)
     data.duration = if data.time then TimeFormat.formatDuration(data.time * 1000) else "<i><running></i>"
     renderElements "#content", "#t-show-log",
       base: base


return true from _allowEsc and _blockEsc

--- app/assets/javascripts/tenon/features/asset_uploader.js.coffee
+++ app/assets/javascripts/tenon/features/asset_uploader.js.coffee
@@ -28,9 +28,11 @@

   _blockEsc: =>
     @allowEsc = false
+    return true

   _allowEsc: =>
     @allowEsc = true
+    return true

   _drawAsset: (e, data) =>
     @_progressBarStatus(data.context, 'success')


Remove conditional http verb based on user agent.

--- app/assets/javascripts/models/base.coffee
+++ app/assets/javascripts/models/base.coffee
@@ -20,15 +20,8 @@
       opts.add_data_to_each[attribute]
     )

-    # TODO REMOVE THIS AFTER WEBKIT BUG FIX. https://github.com/thoughtbot/capybara-webkit/issues/553
-    # This conditonal is for testing but there is no easy fix at the moment.
-    # Put passes through data.  Patch dosn't.
-    if (userAgent = window?.navigator?.userAgent).match /capybara-webkit/ || userAgent.match /PhantomJS/
-      path = @route + "/save_all.json"
-      method = 'PUT'
-    else
-      path = @route + "/save_all.json"
-      method = 'PUT'
+    path = @route + "/save_all.json"
+    method = 'PUT'

     $.ajax
       type: method
@@ -57,16 +50,8 @@

   save: ->
     if !isNaN(parseFloat(@id)) && isFinite(@id)
-
-      # TODO REMOVE THIS AFTER WEBKIT BUG FIX. https://github.com/thoughtbot/capybara-webkit/issues/553
-      # This conditonal is for testing but there is no easy fix at the moment.
-      # Put passes through data.  Patch dosn't.
-      if (userAgent = window?.navigator?.userAgent).match /capybara-webkit/ || userAgent.match /PhantomJS/
-        path = @route + "/" + @id + ".json"
-        method = 'PUT'
-      else
-        path = @route + "/" + @id + ".json"
-        method = 'PATCH'
+      path = @route + "/" + @id + ".json"
+      method = 'PUT'
     else
       path = @route + ".json"
       method = "POST"


Refactring media-grid javascript actions.

--- app/assets/javascripts/undersky.js.coffee
+++ app/assets/javascripts/undersky.js.coffee
@@ -16,18 +16,18 @@
     @toggle: (e) ->
       return if e.hasModifierKey()
       e && e.preventDefault()
+      panels = $('.modal.media-panel')
+      panels.filter('.show').hide()
       columns = self.columns()
       column = $(this)
-      panels = $('.modal.media-panel').hide()
       id = column.attr('data-id')
-      if column.hasClass('actived')
-        columns.removeClass('actived').removeClass('focused')
-      else
-        columns.removeClass('actived').removeClass('focused')
+      actived = column.hasClass('actived')
+      columns.filter('.actived, .focused').removeClass('actived').removeClass('focused')
+      column.addClass('focused')
+      unless actived
         column.addClass('actived')
         panels.filter('[data-id=' + id + ']').show()
-      column.addClass('focused')
-      self.resize()
+        self.resize()

     @action: (e) ->
       switch e.which


Forgot to call clear_history(). Related to #388

--- admin/static/coffee/dataexplorer.coffee
+++ admin/static/coffee/dataexplorer.coffee
@@ -34,6 +34,7 @@

         clear_history_view: (event) =>
             @history_view.clear_history event
+            @clear_history()

         open_close_history: (event) =>
             @history_view.open_close_history event, @$('.close_queries_link')
@@ -167,7 +168,7 @@
                     @history_view.add_query query

         clear_history: =>
-            @history = []
+            @history.length = 0
             window.localStorage.rethinkdb_history = JSON.stringify @history

         initialize: (args) =>


Rename global in dataexplorer

Rename global in dataexplorer

--- admin/static/coffee/dataexplorer.coffee
+++ admin/static/coffee/dataexplorer.coffee
@@ -8,7 +8,7 @@
 r = require('rethinkdb')

-state =
+dataexplorer_state =
     current_query: null
     query_result: null
     cursor_timed_out: true
@@ -225,19 +225,19 @@
     # We give this button an "active" class that make it looks like it's pressed.
     toggle_pressed_buttons: =>
         if @history_view.state is 'visible'
-            state.history_state = 'visible'
+            dataexplorer_state.history_state = 'visible'
             @$('.clear_queries_link').fadeIn 'fast'
             @$('.close_queries_link').addClass 'active'
         else
-            state.history_state = 'hidden'
+            dataexplorer_state.history_state = 'hidden'
             @$('.clear_queries_link').fadeOut 'fast'
             @$('.close_queries_link').removeClass 'active'

         if @options_view.state is 'visible'
-            state.options_state = 'visible'
+            dataexplorer_state.options_state = 'visible'
             @$('.toggle_options_link').addClass 'active'
         else
-            state.options_state = 'hidden'
+            dataexplorer_state.options_state = 'hidden'
             @$('.toggle_options_link').removeClass 'active'

     # Show/hide the history view
@@ -563,21 +563,21 @@
         query = query.replace(/^\s*$[\n\r]{1,}/gm, '')
         query = query.replace(/\s*$/, '') # Remove the white spaces at the end of the query (like newline/space/tab)
         if window.localStorage?
-            if state.history.length is 0 or state.history[state.history.length-1].query isnt query and @regex.white.test(query) is false
-                state.history.push
+            if dataexplorer_state.history.length is 0 or dataexplorer_state.history[dataexplorer_state.history.length-1].query isnt query and @regex.white.test(query) is false
+                dataexplorer_state.history.push
                     query: query
                     broken_query: broken_query
-                if state.history.length>@size_history
-                    window.localStorage.rethinkdb_history = JSON.stringify state.history.slice state.history.length-@size_history
+                if dataexplorer_state.history.length>@size_history
+                    window.localStorage.rethinkdb_history = JSON.stringify dataexplorer_state.history.slice dataexplorer_state.history.length-@size_history
                 else
-                    window.localStorage.rethinkdb_history = JSON.stringify state.history
+                    window.localStorage.rethinkdb_history = JSON.stringify dataexplorer_state.history
                 @history_view.add_query
                     query: query
                     broken_query: broken_query

     clear_history: =>
-        state.history.length = 0
-        window.localStorage.rethinkdb_history = JSON.stringify state.history
+        dataexplorer_state.history.length = 0
+        window.localStorage.rethinkdb_history = JSON.stringify dataexplorer_state.history

     # Save the current query (the one in codemirror) in local storage
     save_current_query: =>
@@ -587,31 +587,31 @@
     initialize: (args) =>
         @TermBaseConstructor = r.expr(1).constructor.__super__.constructor.__super__.constructor

-        state = args.state
+        dataexplorer_state = args.state if args.state?
         @executing = false

         # Load options from local storage
         if window.localStorage?.options?
             try
-                state.options = JSON.parse window.localStorage.options
+                dataexplorer_state.options = JSON.parse window.localStorage.options
             catch err
                 window.localStorage.removeItem 'options'

         # Load the query that was written in code mirror (that may not have been executed before)
         if typeof window.localStorage?.current_query is 'string'
             try
-                state.current_query = JSON.parse window.localStorage.current_query
+                dataexplorer_state.current_query = JSON.parse window.localStorage.current_query
             catch err
                 window.localStorage.removeItem 'current_query'

         if window.localStorage?.rethinkdb_history?
             try
-                state.history = JSON.parse window.localStorage.rethinkdb_history
+                dataexplorer_state.history = JSON.parse window.localStorage.rethinkdb_history
             catch err
                 window.localStorage.removeItem 'rethinkdb_history'

-        @query_has_changed = state.query_result?.current_query isnt state.current_query
+        @query_has_changed = dataexplorer_state.query_result?.current_query isnt dataexplorer_state.current_query

         # Index used to navigate through history with the keyboard
         @history_displayed_id = 0 # 0 means we are showing the draft, n>0 means we are showing the nth query in the history
@@ -636,15 +636,15 @@

         @results_view_wrapper = new ResultViewWrapper
             container: @
-            view: state.view
+            view: dataexplorer_state.view

         @options_view = new OptionsView
             container: @
-            options: state.options
+            options: dataexplorer_state.options

         @history_view = new HistoryView
             container: @
-            history: state.history
+            history: dataexplorer_state.history

         @driver_handler = new DriverHandler
             container: @
@@ -714,9 +714,9 @@
             @$('.button_query').prop 'disabled', true

         # Let's bring back the data explorer to its old state (if there was)
-        if state?.query_result?
+        if dataexplorer_state?.query_result?
             @results_view_wrapper.set_query_result
-                query_result: state.query_result
+                query_result: dataexplorer_state.query_result

         @$('.results_container').html @results_view_wrapper.render(query_has_changed: @query_has_changed).$el

@@ -739,13 +739,13 @@
         @codemirror.on 'gutterClick', @handle_gutter_click

         @codemirror.setSize '100%', 'auto'
-        if state.current_query?
-            @codemirror.setValue state.current_query
+        if dataexplorer_state.current_query?
+            @codemirror.setValue dataexplorer_state.current_query
         @codemirror.focus() # Give focus

         # Track if the focus is on codemirror
         # We use it to refresh the docs once the reql_docs.json is loaded
-        state.focus_on_codemirror = true
+        dataexplorer_state.focus_on_codemirror = true

         @codemirror.setCursor @codemirror.lineCount(), 0
         if @codemirror.getValue() is '' # We show suggestion for an empty query only
@@ -754,16 +754,16 @@

         @draft = @codemirror.getValue()

-        if state.history_state is 'visible' # If the history was visible, we show it
+        if dataexplorer_state.history_state is 'visible' # If the history was visible, we show it
             @toggle_history
                 no_animation: true

-        if state.options_state is 'visible' # If the history was visible, we show it
+        if dataexplorer_state.options_state is 'visible' # If the history was visible, we show it
             @toggle_options
                 no_animation: true

     on_blur: =>
-        state.focus_on_codemirror = false
+        dataexplorer_state.focus_on_codemirror = false
         # We hide the description only if the user isn't selecting text from a description.
         if @keep_suggestions_on_blur is false
             @hide_suggestion_and_description()
@@ -1021,14 +1021,14 @@
                 @ignored_next_keyup = false
             return true

-        state.focus_on_codemirror = true
+        dataexplorer_state.focus_on_codemirror = true

         # Let's hide the tooltip if the user just clicked on the textarea. We'll only display later the suggestions if there are (no description)
         if event?.type is 'mouseup'
             @hide_suggestion_and_description()

         # Save the last query (even incomplete)
-        state.current_query = @codemirror.getValue()
+        dataexplorer_state.current_query = @codemirror.getValue()
         @save_current_query()

         # Look for special commands
@@ -1245,7 +1245,7 @@
                                         else if /^\s*"/.test(@current_extra_suggestion) is true
                                             suggestion = @current_extra_suggestion+'"'
                                 else
-                                    if state.options.electric_punctuation is false
+                                    if dataexplorer_state.options.electric_punctuation is false
                                         move_outside = true
                                     if /^\s*'/.test(@current_extra_suggestion) is true
                                         string_delimiter = "'"
@@ -1293,15 +1293,15 @@
                 return true
             # Catching history navigation
             else if event.type is 'keyup' and event.altKey and event.which is 38 # Key up
-                if @history_displayed_id < state.history.length
+                if @history_displayed_id < dataexplorer_state.history.length
                     @history_displayed_id++
-                    @codemirror.setValue state.history[state.history.length-@history_displayed_id].query
+                    @codemirror.setValue dataexplorer_state.history[dataexplorer_state.history.length-@history_displayed_id].query
                     event.preventDefault()
                     return true
             else if event.type is 'keyup' and event.altKey and event.which is 40 # Key down
                 if @history_displayed_id > 1
                     @history_displayed_id--
-                    @codemirror.setValue state.history[state.history.length-@history_displayed_id].query
+                    @codemirror.setValue dataexplorer_state.history[dataexplorer_state.history.length-@history_displayed_id].query
                     event.preventDefault()
                     return true
                 else if @history_displayed_id is 1
@@ -1309,13 +1309,13 @@
                     @codemirror.setValue @draft
                     @codemirror.setCursor @codemirror.lineCount(), 0 # We hit the draft and put the cursor at the end
             else if event.type is 'keyup' and event.altKey and event.which is 33 # Page up
-                @history_displayed_id = state.history.length
-                @codemirror.setValue state.history[state.history.length-@history_displayed_id].query
+                @history_displayed_id = dataexplorer_state.history.length
+                @codemirror.setValue dataexplorer_state.history[dataexplorer_state.history.length-@history_displayed_id].query
                 event.preventDefault()
                 return true
             else if event.type is 'keyup' and event.altKey and event.which is 34 # Page down
                 @history_displayed_id = @history.length
-                @codemirror.setValue state.history[state.history.length-@history_displayed_id].query
+                @codemirror.setValue dataexplorer_state.history[dataexplorer_state.history.length-@history_displayed_id].query
                 @codemirror.setCursor @codemirror.lineCount(), 0 # We hit the draft and put the cursor at the end
                 event.preventDefault()
                 return true
@@ -1365,7 +1365,7 @@
             @hide_suggestion_and_description()
             return false

-        if state.options.electric_punctuation is true
+        if dataexplorer_state.options.electric_punctuation is true
             @pair_char(event, stack) # Pair brackets/quotes

         # We just look at key up so we don't fire the call 3 times
@@ -1445,7 +1445,7 @@
                     @$('.suggestion_name_list').append @template_suggestion_name
                         id: i
                         suggestion: suggestion
-            if state.options.suggestions is true and show_suggestion is true
+            if dataexplorer_state.options.suggestions is true and show_suggestion is true
                 @show_suggestion()
             else
                 @hide_suggestion()
@@ -1453,7 +1453,7 @@
         else if result.description?
             @hide_suggestion()
             @description = result.description
-            if state.options.suggestions is true and event?.type isnt 'mouseup'
+            if dataexplorer_state.options.suggestions is true and event?.type isnt 'mouseup'
                 @show_description()
             else
                 @hide_description()
@@ -2405,7 +2405,7 @@

         ch = @cursor_for_auto_completion.ch+suggestion_to_write.length

-        if state.options.electric_punctuation is true
+        if dataexplorer_state.options.electric_punctuation is true
             if suggestion_to_write[suggestion_to_write.length-1] is '(' and @count_not_closed_brackets('(') >= 0
                 @codemirror.setValue @query_first_part+suggestion_to_write+')'+@query_last_part
                 @written_suggestion = suggestion_to_write+')'
@@ -2533,7 +2533,7 @@
     abort_query: =>
         @disable_toggle_executing = false
         @toggle_executing false
-        state.query_result?.force_end_gracefully()
+        dataexplorer_state.query_result?.force_end_gracefully()
         @driver_handler.close_connection()

     # Function that execute the queries in a synchronous way.
@@ -2547,8 +2547,8 @@
         @$('.profiler_enabled').slideUp 'fast'

         # The user just executed a query, so we reset cursor_timed_out to false
-        state.cursor_timed_out = false
-        state.query_has_changed = false
+        dataexplorer_state.cursor_timed_out = false
+        dataexplorer_state.query_has_changed = false

         @raw_query = @codemirror.getValue()

@@ -2556,7 +2556,7 @@

         # Execute the query
         try
-            state.query_result?.discard()
+            dataexplorer_state.query_result?.discard()
             # Separate queries
             @non_rethinkdb_query = '' # Store the statements that don't return a rethinkdb query (like "var a = 1;")
             @index = 0 # index of the query currently being executed
@@ -2580,7 +2580,7 @@

     toggle_executing: (executing) =>
         if executing == @executing
-            if executing and state.query_result?.is_feed
+            if executing and dataexplorer_state.query_result?.is_feed
                 @$('.loading_query_img').hide()
             return
         if @disable_toggle_executing
@@ -2591,7 +2591,7 @@
         if executing
             @timeout_toggle_abort = setTimeout =>
                 @timeout_toggle_abort = null
-                if not state.query_result?.is_feed
+                if not dataexplorer_state.query_result?.is_feed
                     @$('.loading_query_img').show()
                 @$('.execute_query').hide()
                 @$('.abort_query').show()
@@ -2606,7 +2606,7 @@

     # A portion is one query of the whole input.
     execute_portion: =>
-        state.query_result = null
+        dataexplorer_state.query_result = null
         while @queries[@index]?
             full_query = @non_rethinkdb_query
             full_query += @queries[@index]
@@ -2631,7 +2631,7 @@

                 if final_query
                     query_result = new QueryResult
-                        has_profile: state.options.profiler
+                        has_profile: dataexplorer_state.options.profiler
                         current_query: @raw_query
                         raw_query: @raw_queries[@index]
                         driver_handler: @driver_handler
@@ -2639,7 +2639,7 @@
                             error: (query_result, err) =>
                                 @results_view_wrapper.render_error(@query, err)
                             ready: (query_result) =>
-                                state.pause_at = null
+                                dataexplorer_state.pause_at = null
                                 if query_result.is_feed
                                     @toggle_executing true
                                     @disable_toggle_executing = true
@@ -2648,17 +2648,17 @@
                                             @disable_toggle_executing = false
                                             @toggle_executing false

-                    state.query_result = query_result
+                    dataexplorer_state.query_result = query_result

                     @results_view_wrapper.set_query_result
-                        query_result: state.query_result
+                        query_result: dataexplorer_state.query_result

                 @disable_toggle_executing = false
                 @driver_handler.run_with_new_connection rdb_query,
                     optargs:
                         binaryFormat: "raw"
                         timeFormat: "raw"
-                        profile: state.options.profiler
+                        profile: dataexplorer_state.options.profiler
                     connection_error: (error) =>
                         @save_query
                             query: @raw_query
@@ -3891,7 +3891,7 @@
                 if that.state is 'visible'
                     that.container.adjust_collapsible_panel_height
                         is_at_bottom: is_at_bottom
-        else if state is 'visible'
+        else if that.state is 'visible'
             @container.adjust_collapsible_panel_height
                 delay_scroll: true
                 is_at_bottom: is_at_bottom


Remove duplicated methos in resources/model.coffee

--- app/coffee/modules/resources/model.coffee
+++ app/coffee/modules/resources/model.coffee
@@ -127,103 +127,6 @@
     service.make_model = (name, data, cls=Model, dataTypes={}) ->
         return new cls(name, data, dataTypes)

-    service.create = (name, data, cls=Model, dataTypes={}, extraParams={}) ->
-        defered = $q.defer()
-
-        params = {
-            method: "POST"
-            url: $gmUrls.api(name)
-            headers: headers()
-            data: JSON.stringify(data)
-            params: extraParams
-        }
-
-        promise = $http(params)
-        promise.success (_data, _status) ->
-            defered.resolve(service.make_model(name, _data, cls, dataTypes))
-
-        promise.error (data, status) ->
-            defered.reject(data)
-
-        return defered.promise
-
-    service.remove = (model) ->
-        defered = $q.defer()
-        self = @
-
-        params =
-            method: "DELETE"
-            url: @getUrl()
-            headers: headers()
-
-        promise = $http(params)
-        promise.success (data, status) ->
-            defered.resolve(self)
-
-        promise.error (data, status) ->
-            defered.reject(self)
-
-        return defered.promise
-
-    service.save = (model, extraParams, patch=true) ->
-        self = @
-        defered = $q.defer()
-
-        if not @isModified() and patch
-            defered.resolve(self)
-            return defered.promise
-
-        params =
-            url: @getUrl()
-            headers: headers(),
-
-        if patch
-            params.method = "PATCH"
-        else
-            params.method = "PUT"
-
-        params.data = JSON.stringify(@.getAttrs(patch))
-
-        params = _.extend({}, params, extraParams)
-
-        promise = $http(params)
-        promise.success (data, status) ->
-            self._isModified = false
-            self._attrs = _.extend(self.getAttrs(), data)
-            self._modifiedAttrs = {}
-
-            self.applyCasts()
-            defered.resolve(self)
-
-        promise.error (data, status) ->
-            defered.reject(data)
-
-        return defered.promise
-
-    service.refresh = (model) ->
-        defered = $q.defer()
-        self = @
-
-        params = {
-            method: "GET",
-            url: @getUrl()
-            headers: headers()
-        }
-
-        promise = $http(params)
-        promise.success (data, status) ->
-            self._modifiedAttrs = {}
-            self._attrs = data
-            self._isModified = false
-            self.applyCasts()
-
-            defered.resolve(self)
-
-        promise.error (data, status) ->
-            defered.reject([data, status])
-
-        return defered.promise
-
     service.cls = Model
     service.casts = {
         int: (value) ->


debug treeViewEl.parentNode

debug treeViewEl.parentNode

--- lib/autohide-tree-view.coffee
+++ lib/autohide-tree-view.coffee
@@ -28,16 +28,12 @@
       minimum: 1

   activate: (state) ->
-    # console.log 'autohide-tree-view: activating'
     @enabled = state.enabled ? true
     @subs = new SubAtom()
     @subs.add atom.packages.onDidActivateInitialPackages =>
-      # console.log 'autohide-tree-view: initialize after activate initial packages' unless @initialized
       @initialize()
     if @enabled and atom.packages.isPackageActive 'tree-view'
-      # console.log 'autohide-tree-view: initialize before activate initial packages' unless @initialized
       @initialize()
-    # console.log 'autohide-tree-view: done activating'

   deactivate: ->
     @initialized = false
@@ -182,7 +178,7 @@

   applyHiddenWidth: (width) ->
     return unless @enabled
-    console.log 'autohide-tree-view: ', treeViewEl.parentNode?, treeViewEl.style?, treeViewEl.parentNode?.style?
+    console.log 'autohide-tree-view: ', treeViewEl.parentNode
     width = @getHiddenWidth() if isNaN parseInt width
     treeViewEl.style.width = "#{width}px"
     treeViewEl.parentNode.style.width = "#{width}px"


Check if the suggestions are up to date or not when the user hit tab

--- admin/static/coffee/dataexplorer.coffee
+++ admin/static/coffee/dataexplorer.coffee
@@ -587,6 +587,11 @@
         # Handle events on codemirror
         # Return true if we want code mirror to ignore the event
         handle_keypress: (editor, event) =>
+            if @ignored_next_keyup is true
+                if event?.type is 'keyup' and event?.which isnt 9
+                    @ignored_next_keyup = false
+                return true
+
             @prototype.focus_on_codemirror = true

             # Let's hide the tooltip if the user just clicked on the textarea. We'll only display later the suggestions if there are (no description)
@@ -621,6 +626,35 @@
                                 @show_suggestion()
                                 return true
                             else
+                                # We can retrieve the content of codemirror only on keyup events. The users may write "r." then hit "d" then "tab" If the events are triggered this way
+                                # keydown d - keydown tab - keyup d - keyup tab
+                                # We want to only show the suggestions for r.d
+                                if @written_suggestion is null
+                                    cached_query = @query_first_part+@current_element+@query_last_part
+                                else
+                                    cached_query = @query_first_part+@written_suggestion+@query_last_part
+                                if cached_query isnt @codemirror.getValue() # We fired a keydown tab before a keyup, so our suggestions are not up to date
+                                    new_element = @codemirror.getValue().slice @query_first_part.length, @codemirror.getValue().length-@query_last_part.length
+                                    regex = @create_safe_regex new_element
+                                    new_suggestions = []
+                                    console.log '+++++'
+                                    new_highlighted_suggestion = -1
+                                    for suggestion, index in @current_suggestions
+                                        if index < @current_highlighted_suggestion
+                                            new_highlighted_suggestion = new_suggestions.length
+                                        if regex.test(suggestion) is true
+                                            new_suggestions.push suggestion
+                                    @current_suggestions = new_suggestions
+                                    @current_highlighted_suggestion = new_highlighted_suggestion
+                                    @.$('.suggestion_name_list').empty()
+                                    for suggestion, i in @current_suggestions
+                                        @.$('.suggestion_name_list').append @template_suggestion_name
+                                            id: i
+                                            suggestion: suggestion
+                                    @ignored_next_keyup = true
+                                    @current_element = new_element
+
+
                                 # Switch throught the suggestions
                                 if event.shiftKey
                                     @current_highlighted_suggestion--
@@ -774,6 +808,7 @@

             @current_suggestions = []
             @current_element = ''
+            @written_suggestion = null
             @cursor_for_auto_completion = @codemirror.getCursor()

             result =
@@ -1532,10 +1567,13 @@
         # Write the suggestion in the code mirror
         write_suggestion: (args) =>
             suggestion_to_write = args.suggestion_to_write
+
             if suggestion_to_write[suggestion_to_write.length-1] is '(' and @count_not_closed_brackets('(') >= 0
                 @codemirror.setValue @query_first_part+suggestion_to_write+')'+@query_last_part
+                @written_suggestion = suggestion_to_write+')'
             else
                 @codemirror.setValue @query_first_part+suggestion_to_write+@query_last_part
+                @written_suggestion = suggestion_to_write

             @codemirror.focus() # Useful if the user used the mouse to select a suggestion
             @codemirror.setCursor


Fix bad merge

Fix bad merge

--- admin/static/coffee/dataexplorer.coffee
+++ admin/static/coffee/dataexplorer.coffee
@@ -1581,7 +1581,9 @@
                                 metadata: @saved_data.metadata

                             # Successful query, let's save it in the history
-                            @save_query @raw_query
+                            @save_query
+                                query: @raw_query
+                                broken_query: false
                     else
                         @execute_portion()


Fix incorrect variable. Fixes #46

Fix incorrect variable. Fixes #46

--- emails.coffee
+++ emails.coffee
@@ -230,7 +230,7 @@

       # create plain-text version from html
       if settings.plainText
-        opts.text = Utils.toText(html)
+        opts.text = Utils.toText(opts.html)

     catch ex
       Utils.Logger.error 'Could not render email before sending: ' + ex.message, TAG


Don't move the button when already visible

--- app/js/jail_iframe/classes/buttons.coffee
+++ app/js/jail_iframe/classes/buttons.coffee
@@ -16,10 +16,15 @@
     @frame.sizeFrameToFitContent()

   setCoordinates: (top, left) =>
+    return if @_visible
+
     @_top = top
     @_left = left

   show: =>
+    return if @_visible
+
+    @_visible = true
     @setStateClass ''
     @frame.fadeIn()

@@ -30,7 +35,9 @@
       left: left + "px"
       top: top + "px"

-  hide: => @frame.fadeOut()
+  hide: =>
+    @frame.fadeOut()
+    @_visible = false

   destroy: => @frame.destroy()


lots of module fixes.  add SpreadElement to ComputeFree

--- lib/closure-conversion.coffee
+++ lib/closure-conversion.coffee
@@ -501,7 +501,8 @@

         visitFunctionDeclaration: (n) ->
                 if n.toplevel
-                        super
+                        n.body = @visit n.body
+                        return n
                 else
                         func_exp = n
                         func_exp.type = FunctionExpression
@@ -809,6 +810,7 @@
                         when EmptyStatement        then exp.ejs_free_vars = new Set
                         when BreakStatement        then exp.ejs_free_vars = new Set
                         when ContinueStatement     then exp.ejs_free_vars = new Set
+                        when SpreadElement         then exp.ejs_free_vars = @free exp.argument
                         when UpdateExpression      then exp.ejs_free_vars = @free exp.argument
                         when ReturnStatement       then exp.ejs_free_vars = @free exp.argument
                         when UnaryExpression       then exp.ejs_free_vars = @free exp.argument
@@ -1748,66 +1750,62 @@
                 throw new Error("internal compiler error, only form \"import blah from 'blah'\" supported") if specifiers.length isnt 1
                 specifiers[0].id

-        generate_export_return = (exported, batch_exported) ->
-                exported_getters = []
-                for exp in exported
-                        exported_getters.push {
-                                type: Property,
-                                key: exp.name or exp.id,
-                                value: {
-                                        type: FunctionExpression,
-                                        params: [],
-                                        body:
-                                                type: BlockStatement
-                                                body: [
-                                                        { type: ReturnStatement, argument: exp.id }
-                                                ]
-                                },
-                                kind: "get"
+        define_export_property = (exported_id, local_id = exported_id) ->
+                console.log "exporting #{local_id.name} as #{exported_id.name}"
+                exports_id = create_identifier("exports") # XXX as with compiler.coffee, this 'exports' should be '%exports' if the module has ES6 module declarations
+
+                Object_defineProperty = {
+                        type: MemberExpression,
+                        computed: false,
+                        object: create_identifier("Object"),
+                        property: create_identifier("defineProperty")
+                }
+
+                getter = {
+                        type: FunctionExpression,
+                        params: [],
+                        defaults: [],
+                        body:
+                                type: BlockStatement
+                                body: [
+                                        { type: ReturnStatement, argument: local_id }
+                                ]
+                }
+
+                property_literal = {
+                        type: ObjectExpression,
+                        properties: [
+                                { type: Property, kind: "init", key: create_identifier("get"), value: getter }
+                        ]
+                }
+
+                return {
+                        type: ExpressionStatement,
+                        expression: {
+                                type: CallExpression
+                                callee: Object_defineProperty,
+                                arguments: [
+                                        exports_id,
+                                        create_string_literal(exported_id.name),
+                                        property_literal
+                                ]
                         }
-
-                obj_literal = { type: ObjectExpression, properties: exported_getters }
-
-                if batch_exported.length is 0
-                        return [ { type: ReturnStatement, argument: obj_literal } ]
-
-                # batch_exported.length > 0, so we need to insert
-                # loops over the import tmp id, adding the identifiers
-                # to our new export object
-
-                export_id = freshId("export")
-
-                ret = [{
-                        type: VariableDeclaration,
-                        declarations: [{
-                                type: VariableDeclarator,
-                                id:   export_id,
-                                init: obj_literal
-                        }],
-                        kind: "let"
-                }]
-
-                for batch in batch_exported
-                        spec_arg = { type: ArrayExpression, elements: batch.specifiers }
-                        ret.push { type: ExpressionStatement, expression: create_intrinsic(moduleImportBatch_id, [batch.source, spec_arg, export_id]) }
-
-                ret.push { type: ReturnStatement, argument: export_id }
-                ret
-
+                }
+
+
         visitFunction: (n) ->
                 return n if not n.toplevel

                 @exports = []
                 @batch_exports = []
-                n = super
-                n.body.body.push exret for exret in generate_export_return(@exports, @batch_exports)
-                n
+
+                super

         visitImportDeclaration: (n) ->
                 if n.specifiers.length is 0
                         # no specifiers, it's of the form:  import from "foo"
                         # don't waste a decl for this type
-                        return create_intrinsic(moduleGet_id, [n.source])
+                        return create_intrinsic(moduleGet_id, [n.source_path])

                 # otherwise create a fresh declaration for the module object
                 #
@@ -1819,7 +1817,7 @@
                         declarations: [{
                                 type: VariableDeclarator,
                                 id:   import_tmp
-                                init: create_intrinsic(moduleGet_id, [n.source])
+                                init: create_intrinsic(moduleGet_id, [n.source_path])
                         }],
                         kind: "let"
                 }
@@ -1874,11 +1872,12 @@
                                 declarations: [{
                                         type: VariableDeclarator,
                                         id:   import_tmp
-                                        init: create_intrinsic(moduleGet_id, [n.source])
+                                        init: create_intrinsic(moduleGet_id, [n.source_path])
                                 }],
                                 kind: "let"
                         }
-
+
+                        export_stuff = []
                         if n.default
                                 # export * from "foo"
                                 throw new SyntaxError("invalid export") if n.specifiers.length isnt 1 or n.specifiers[0].type isnt ExportBatchSpecifier
@@ -1899,48 +1898,59 @@
                                         }

                                         @exports.push { name: spec.name, id: spectmp }
-                        console.log escodegen.generate export_decl
-                        return export_decl
-
+                                        export_stuff.push(define_export_property(spec.name, spectmp))
+                        export_stuff.unshift(export_decl)
+                        return export_stuff
+
+                export_id = create_identifier("exports");
+
                 # export function foo () { ... }
                 if n.declaration.type is FunctionDeclaration
                         @exports.push { id: n.declaration.id }
-                        return n.declaration
+
+                        return [n.declaration, define_export_property(n.declaration.id)]

                 # export let foo = bar;
                 if n.declaration.type is VariableDeclaration
-                        @exports.push({ id: decl.id }) for decl in n.declaration.declarations
-                        return n.declaration
+                        export_defines = []
+                        for decl in n.declaration.declarations
+                                @exports.push({ id: decl.id })
+                                export_defines.push(define_export_property(decl.id))
+                        export_defines.unshift(n.declaration)
+                        return export_defines

                 # export foo = bar;
                 if n.declaration.type is VariableDeclarator
                         @exports.push { id: n.declaration.id }
-                        return n.declaration
+                        return [n.declaration, define_export_property(n.declaration.id)]

                 # export default = ...;
                 #
                 if n.default
+                        local_default_id = create_identifier "%default"
                         default_id = create_identifier "default"
                         @exports.push { id: default_id }
-                        return {
+
+                        local_decl = {
                                 type: VariableDeclaration,
                                 declarations: [{
                                         type: VariableDeclarator,
-                                        id:   default_id
+                                        id:   local_default_id
                                         init: n.declaration
                                 }],
                                 kind: "var"
                         }
+                        export_define = define_export_property(default_id, local_default_id)
+                        return [local_decl, export_define]

                 throw new Error("Unsupported type of export declaration #{n.declaration.type}")

         visitModuleDeclaration: (n) ->
-                init =
-                        type:     MemberExpression
-                        object:   create_intrinsic(moduleGet_id, [n.source])
-                        property: create_identifier "default"
-                        computed: false
-
+                # this isn't quite right.  I believe this form creates
+                # a new instance and puts new properties on it that
+                # map to the module, instead of just returning the
+                # module object.
+                init = create_intrinsic(moduleGet_id, [n.source_path])
                 return {
                         type: VariableDeclaration,
                         declarations: [{


bin/masson configure: refactor code

bin/masson configure: refactor code

--- lib/commands/configure.coffee
+++ lib/commands/configure.coffee
@@ -1,10 +1,10 @@
+
     config = require '../config'
     params = require '../params'
-    tree = require '../tree.coffee'
-    context = require '../context.coffee'
-    {merge} = require '../misc.coffee'
+    tree = require '../tree'
+    context = require '../context'
+    {merge} = require '../misc'
     each = require 'each'
-    configure = require '../configure'
     fs = require 'fs'
     path = require 'path'
     util = require 'util'
@@ -16,55 +16,34 @@
     module.exports = ->
       # behave like the first pass of run command
       # creates a context perserver by executing all configure functions
-      contexts = {}
       params = params.parse()
-      output = params.output ?= 'report'
+      provider = params.provider ?= 'JSON'
+      output =  if params.output then  "#{params.output}.#{provider.toLowerCase()}" else ''
+      provider = provider.toUpperCase()
+      ctxs_output = {}
       # JSON and CSON are suported for now: by default provider is JSON
-      provider = params.provider ?= 'JSON'
       config params.config, (err, config) =>
-        do_contexts = ->
-          for fqdn, server of config.servers
-            ctx = contexts[fqdn] = context (merge {}, config, server), params.command
-            ctx.hosts = contexts
-            ctx.tree = tree ctx.config.modules
-            ctx.modules = Object.keys ctx.tree.modules
-          each(contexts)
-          .on 'error', (err) ->
-            if err.errors
-              console.log '\n'
-              console.log "#{err.message}\n"
-              for err in err.errors
-                console.log "#{err.stack?.trim() or err.message}\n"
-            else
-              console.log "#{err.stack?.trim() or err.message}\n"
-          .parallel(true)
-          .run (host, ctx, next) =>
-            configure host, ctx
-            .on 'done', (host, ctx) =>
-              done.push host
-              out_ctxs[host] = ctx.config
-              do_progress()
-        do_progress =  ->
-          # rate is used for program which may launch configure as child process
-          rate = done.length*100/Object.keys(config.servers).length
-          process.stdout.write "#{rate}" if process.env.SPAWNED
-          return do_write() if Object.keys(config.servers).length == done.length
-        do_write =  ->
-          switch provider.toUpperCase()
-            when 'CSON'
-              output = "#{output}.cson"
-              location = "#{path.resolve process.cwd(), output}"
-              fs.writeFile location, CSON.stringify(out_ctxs), 'utf8', (err, done) ->
-                do_end(err, done)
-            else
-              output = "#{output}.json"
-              location = "#{path.resolve process.cwd(), output}"
-              fs.writeFile location, JSON.stringify(out_ctxs,null,4), 'utf8', (err, done) ->
-                do_end(err)
-        do_end = (err) ->
-          return err if err
-          process.exit(0)
         contexts = {}
-        out_ctxs = {}
-        done = []
-        do_contexts()
+        for fqdn, server of config.servers
+          ctx = contexts[fqdn] = context (merge {}, config, server), params.command
+          ctx.hosts = contexts
+          ctx.tree = tree ctx.config.modules
+          ctx.modules = Object.keys ctx.tree.modules
+        for fqdn, ctx of contexts
+          for module in Object.keys ctx.tree.modules
+            module = ctx.tree.modules[module]
+            module.configure.call ctx, ctx if module.configure
+
+          ctxs_output[fqdn] = ctx.config
+        return console.log ctxs_output if output == ''
+        for fqdn, ctx of ctxs_output
+          delete ctx.servers
+        switch provider
+          when 'CSON'
+            location = "#{path.resolve process.cwd(), output}"
+            fs.writeFile location, CSON.stringify(ctxs_output), 'utf8', (err, done) ->
+              return  if err then err else process.exit(0)
+          else
+            location = "#{path.resolve process.cwd(), output}"
+            fs.writeFile location, JSON.stringify(ctxs_output,null,4), 'utf8', (err, done) ->
+              return  if err then err else process.exit(0)


fix lastRecall not being set when asked "what do you think?"

--- scripts/learn.coffee
+++ scripts/learn.coffee
@@ -144,5 +144,8 @@
     else
       key = msg.random Object.keys memory.words
       lookup = msg.random memory.words[key]
+
+      memory.lastRecall = lookup
+      robot.brain.set('learned', memory)

       msg.send [lookup.word, lookup.action, lookup.term].join(' ')


Delete mecab.coffee

Delete mecab.coffee

--- scripts/mecab.coffee
+++ scripts/mecab.coffee
@@ -1,20 +0,0 @@
-# Description:
-#   mecabを使って形態素解析をし、SQLiteのDBに収納します。
-#
-# Dependencies:
-#   "sqlite3": "2.2.7"
-#   "mecab-acync": "0.0.8"
-#
-# Commands:
-#   None
-#
-# Authors:
-#   snowfox226
-#
-# License;
-#   Copyright (c) 2014 snowbit.
-#   Released under the Apache v2 license
-#   https://github.com/snowbit/snowbit/blob/master/LICENSE
-
-module.exports = (robot) ->
-


client-scripts js parsing (Uglify)

client-scripts js parsing (Uglify)

--- gulp/client-scripts.coffee
+++ gulp/client-scripts.coffee
@@ -53,6 +53,9 @@
     # Angular.js annotations pre-processing...
     .pipe Annotate add: yes, remove: yes, single_quotes: yes

+    # Parse js files and make them "nicer" (Uglify)
+    .pipe gulpif config.minify, uglify()
+
     # write out product
     .pipe gulpif config.sourcemaps, sourcemaps.write()
     .pipe gulp.dest path.join config.paths.dest, 'app'


[➠] Better Naming™.

[➠] Better Naming™.

--- vendor/assets/javascripts/jquery/plugins/referencesify/referencesies.js.coffee
+++ vendor/assets/javascripts/jquery/plugins/referencesify/referencesies.js.coffee
@@ -87,11 +87,11 @@
   onWindowResize: (event) =>
     clearTimeout @timeout

-    @timeout = setTimeout @onWindowResizeDone, 500
+    @timeout = setTimeout @onWindowResized, 500

     return

-  onWindowResizeDone: =>
+  onWindowResized: =>
     tranform.call @

     return


Let's not break codemirror with some return false

--- admin/static/coffee/dataexplorer.coffee
+++ admin/static/coffee/dataexplorer.coffee
@@ -379,14 +379,14 @@
                         @codemirror.replaceSelection(char_to_insert+@codemirror.getSelection()+char_to_insert)
                         event.preventDefault()
                         return true
-                    return false
+                    return true

                 if event.which is 8 # Backspace
                     if event.type isnt 'keydown'
-                        return false
+                        return true
                     previous_char = @get_previous_char()
                     if previous_char is null
-                        return false
+                        return true
                     # If the user remove the opening bracket and the next char is the closing bracket, we delete both
                     if previous_char of @matching_opening_bracket
                         next_char = @get_next_char()
@@ -399,12 +399,12 @@
                         if next_char is previous_char and @get_previous_char(2) isnt '\\'
                             @remove_next()
                             return true
-                    return false
+                    return true

                 char_to_insert = String.fromCharCode event.which
                 if char_to_insert?
                     if event.type isnt 'keypress' # We catch keypress because single and double quotes have not the same keyCode on keydown/keypres #thisIsMadness
-                        return false
+                        return true

                     if char_to_insert is '"' or char_to_insert is "'"
                         num_quote = @count_char char_to_insert
@@ -417,7 +417,7 @@
                                     return true
                                 else
                                     # We are at the begining of a string, so let's just add one quote
-                                    return false
+                                    return true
                             else
                                 # Let's add the closing/opening quote missing
                                 return true
@@ -427,9 +427,9 @@
                                 if @last_element_type_if_incomplete(stack) isnt 'string'
                                     @insert_next char_to_insert
                                 else # We add a quote inside a string, probably something like that 'He doesn|\'t'
-                                    return false
+                                    return true
                             else # Else we'll just insert one quote
-                                return false
+                                return true
                     else if @last_element_type_if_incomplete(stack) isnt 'string'
                         next_char = @get_next_char()

@@ -437,7 +437,7 @@
                             num_not_closed_bracket = @count_not_closed_brackets char_to_insert
                             if num_not_closed_bracket >= 0 # We insert a closing bracket only if it help having a balanced number of opened/closed brackets
                                 @insert_next @matching_opening_bracket[char_to_insert]
-                                return false
+                                return true
                             return true
                         else if char_to_insert of @matching_closing_bracket
                             opening_char = @matching_closing_bracket[char_to_insert]
@@ -447,7 +447,7 @@
                                     @move_cursor 1
                                     event.preventDefault()
                                 return true
-            return false
+            return true

         get_next_char: =>
             cursor_end = @codemirror.getCursor()
@@ -733,8 +733,7 @@
                 query: query_before_cursor
                 position: 0

-            if @pair_char(event, stack) is true
-                return true
+            @pair_char(event, stack)
             # If a selection is active, we just catch shift+enter
             if @codemirror.getSelection() isnt ''
                 @hide_suggestion_and_description()