Fix intermittent test failures

Fix intermittent test failures

--- test/src/system/level_2_input_test.coffee
+++ test/src/system/level_2_input_test.coffee
@@ -24,34 +24,33 @@
     inputEvents.push({type, inputType, data})

 # Borrowed from https://github.com/web-platform-tests/wpt/blob/master/input-events/input-events-exec-command.html
-performInputTypeUsingExecCommand = (command, {inputType, data}) ->
+performInputTypeUsingExecCommand = (command, {inputType, data}, callback) ->
   inputEvents = []
-  triggerInputEvent(document.activeElement, "beforeinput", {inputType, data})
-  document.execCommand(command, false, data)
-  assert.equal(inputEvents.length, 2)
-  assert.equal(inputEvents[0].type, "beforeinput")
-  assert.equal(inputEvents[1].type, "input")
-  assert.equal(inputEvents[0].inputType, inputType)
-  assert.equal(inputEvents[0].data, data)
+  requestAnimationFrame ->
+    triggerInputEvent(document.activeElement, "beforeinput", {inputType, data})
+    document.execCommand(command, false, data)
+    assert.equal(inputEvents.length, 2)
+    assert.equal(inputEvents[0].type, "beforeinput")
+    assert.equal(inputEvents[1].type, "input")
+    assert.equal(inputEvents[0].inputType, inputType)
+    assert.equal(inputEvents[0].data, data)
+    requestAnimationFrame(callback)

 testGroup "Level 2 Input", testOptions, ->
   test "insertText", (expectDocument) ->
-    performInputTypeUsingExecCommand("insertText", inputType: "insertText", data: "abc")
-    defer ->
+    performInputTypeUsingExecCommand "insertText", inputType: "insertText", data: "abc", ->
       expectDocument("abc\n")

   test "insertOrderedList", (expectDocument) ->
     insertString("abc")
-    performInputTypeUsingExecCommand("insertOrderedList", inputType: "insertOrderedList")
-    defer ->
+    performInputTypeUsingExecCommand "insertOrderedList", inputType: "insertOrderedList", ->
       assert.blockAttributes([0, 4], ["numberList", "number"])
       assert.ok isToolbarButtonActive(attribute: "number")
       expectDocument("abc\n")

   test "insertUnorderedList", (expectDocument) ->
     insertString("abc")
-    performInputTypeUsingExecCommand("insertUnorderedList", inputType: "insertUnorderedList")
-    defer ->
+    performInputTypeUsingExecCommand "insertUnorderedList", inputType: "insertUnorderedList", ->
       assert.blockAttributes([0, 4], ["bulletList", "bullet"])
       assert.ok isToolbarButtonActive(attribute: "bullet")
       expectDocument("abc\n")
@@ -59,20 +58,16 @@
   test "insertLineBreak", (expectDocument) ->
     clickToolbarButton attribute: "quote", ->
       insertString("abc")
-      performInputTypeUsingExecCommand("insertLineBreak", inputType: "insertLineBreak")
-      defer ->
-        performInputTypeUsingExecCommand("insertLineBreak", inputType: "insertLineBreak")
-        defer ->
+      performInputTypeUsingExecCommand "insertLineBreak", inputType: "insertLineBreak", ->
+        performInputTypeUsingExecCommand "insertLineBreak", inputType: "insertLineBreak", ->
           assert.blockAttributes([0, 6], ["quote"])
           expectDocument("abc\n\n\n")

   test "insertParagraph", (expectDocument) ->
     clickToolbarButton attribute: "quote", ->
       insertString("abc")
-      performInputTypeUsingExecCommand("insertParagraph", inputType: "insertParagraph")
-      defer ->
-        performInputTypeUsingExecCommand("insertParagraph", inputType: "insertParagraph")
-        defer ->
+      performInputTypeUsingExecCommand "insertParagraph", inputType: "insertParagraph", ->
+        performInputTypeUsingExecCommand "insertParagraph", inputType: "insertParagraph", ->
           assert.blockAttributes([0, 4], ["quote"])
           assert.blockAttributes([4, 5], [])
           expectDocument("abc\n\n")
@@ -80,8 +75,7 @@
   test "formatBold", (expectDocument) ->
     insertString("abc")
     getComposition().setSelectedRange([1, 2])
-    performInputTypeUsingExecCommand("bold", inputType: "formatBold")
-    defer ->
+    performInputTypeUsingExecCommand "bold", inputType: "formatBold", ->
       assert.textAttributes([0, 1], {})
       assert.textAttributes([1, 2], bold: true)
       assert.textAttributes([2, 3], {})
@@ -90,8 +84,7 @@
   test "formatItalic", (expectDocument) ->
     insertString("abc")
     getComposition().setSelectedRange([1, 2])
-    performInputTypeUsingExecCommand("italic", inputType: "formatItalic")
-    defer ->
+    performInputTypeUsingExecCommand "italic", inputType: "formatItalic", ->
       assert.textAttributes([0, 1], {})
       assert.textAttributes([1, 2], italic: true)
       assert.textAttributes([2, 3], {})
@@ -100,8 +93,7 @@
   test "formatStrikeThrough", (expectDocument) ->
     insertString("abc")
     getComposition().setSelectedRange([1, 2])
-    performInputTypeUsingExecCommand("strikeThrough", inputType: "formatStrikeThrough")
-    defer ->
+    performInputTypeUsingExecCommand "strikeThrough", inputType: "formatStrikeThrough", ->
       assert.textAttributes([0, 1], {})
       assert.textAttributes([1, 2], strike: true)
       assert.textAttributes([2, 3], {})


Remove straggling console.log

Remove straggling console.log

--- test/src/unit/location_mapper_test.coffee
+++ test/src/unit/location_mapper_test.coffee
@@ -100,7 +100,6 @@
     ],"attributes":["bulletList","bullet"]},
   ]

-  console.log element.innerHTML
   location = index: 0, offset: 0
   container = findContainer([0, 0])
   offset = 1


expose z.bind()

expose z.bind()

--- src/zorium.coffee
+++ src/zorium.coffee
@@ -74,6 +74,7 @@
 ev = require './ev'
 classKebab = require './class_kebab'
 isSimpleClick = require './is_simple_click'
+bind = require './bind'

 _.assign z,
   render: render
@@ -83,5 +84,6 @@
   ev: ev
   classKebab: classKebab
   isSimpleClick: isSimpleClick
+  bind: bind

 module.exports = z


remove console.log

remove console.log

--- plugins/bugzilla/index.coffee
+++ plugins/bugzilla/index.coffee
@@ -41,8 +41,6 @@
     # Normalize the url: https://example.com/bugzilla becomes https://example.com/bugzilla/
     config.host += "/" unless /\/$/.test(config.host)

-    console.log('config', config.host)
-
     if config.customFields
       Object.merge(payload, JSON.parse(config.customFields))


Add support for secure IRC connections.

Add support for secure IRC connections.

--- src/hubot/irc.coffee
+++ src/hubot/irc.coffee
@@ -44,6 +44,7 @@
           debug: true,
           port: options.port,
           stripColors: true,
+          secure: if options.port is "6697" then true else false,
         }

     unless options.nickpass


Fix improperly named snippet prefix

Fix improperly named snippet prefix

--- snippets/paper-input-elements.cson
+++ snippets/paper-input-elements.cson
@@ -2,7 +2,7 @@

 ".text.html":
   "paper-input-container":
-    "prefix": "paper-input"
+    "prefix": "paper-input-container"
     "body": """
     <paper-input-container id="$1">
       <label>${2:Input label}</label>


Move prompt config file to subdirectory

Move prompt config file to subdirectory

We want to allow prompts to use modules, but we shouldn't make your whole home directory the parent for our node_modules directory.

Uses ~/.impromptu and renames the file to prompt.(js|coffee), which is now more descriptive.

--- src/impromptu.coffee
+++ src/impromptu.coffee
@@ -3,10 +3,10 @@
 fs = require 'fs'
 _ = require 'underscore'

-HOME = process.env.HOME
+CONFIG_DIR = "#{process.env.HOME}/.impromptu"

 class Impromptu
-  paths: ["#{HOME}/.impromptu.coffee", "#{HOME}/.impromptu.js", "#{HOME}/.impromptu"]
+  paths: "#{CONFIG_DIR}/prompt.#{ext}" for ext in ['coffee', 'js']

   constructor: ->
     @prompt = new Impromptu.Prompt


Extract helpers

Extract helpers

--- src/impromptu.coffee
+++ src/impromptu.coffee
@@ -5,6 +5,7 @@

 class Impromptu
   @CONFIG_DIR: "#{process.env.HOME}/.impromptu"
+  @COMPILED_DIR: "#{@CONFIG_DIR}/.compiled"

   compiledPrompt: "#{@CONFIG_DIR}/.data/prompt.js"
   paths: "#{@CONFIG_DIR}/prompt.#{ext}" for ext in ['coffee', 'js']
@@ -19,34 +20,19 @@
     @module = new Impromptu.ModuleRegistry @
     @prompt = new Impromptu.Prompt @

-    unless fs.existsSync @compiledPrompt
-      configPath = _.find @paths, (path) ->
-        fs.existsSync path
+    # Make sure we have a source prompt
+    return unless sourcePrompt = _.find @paths, (path) ->
+      fs.existsSync path

-      return unless configPath
-
-      # Make the directory if needed
-      compiledPromptDir = path.dirname @compiledPrompt
-      fs.mkdir compiledPromptDir unless fs.existsSync compiledPromptDir
-
-      # If your prompt is already JS, just copy it over
-      if /\.js$/.test configPath
-        fs.createReadStream(configPath).pipe(fs.createWriteStream(@compiledPrompt))
-
-      # If you're using CS, load the CoffeeScript module to compile and cache it
-      else if /\.coffee$/.test configPath
-        coffee = require 'coffee-script'
-        compiledJs = coffee.compile fs.readFileSync(configPath, {encoding: 'utf-8'})
-        fs.writeFileSync @compiledPrompt, compiledJs
-      else
-        return
+    # Regenerate the prompt if it's been changed or doesn't exist
+    @_compilePrompt sourcePrompt if @_isPromptStale sourcePrompt

     # Load a new Impromptu module from a file.
-    configFile = require @compiledPrompt
-    return unless typeof configFile == 'function'
+    prompt = require @compiledPrompt
+    return unless typeof prompt == 'function'

     # Go!
-    configFile.call @, Impromptu, @prompt.section
+    prompt.call @, Impromptu, @prompt.section

 # Create custom errors by extending `Impromptu.Error`.


things

things

--- src/instagram.coffee
+++ src/instagram.coffee
@@ -11,7 +11,7 @@
 #
 # Commands:
 #   hubot insta tag <tag> <count>- Show recent instagram tags
-#   by default count is 1
+#   by default count is 1
 #
 # Author:
 #   raysrashmi
@@ -31,18 +31,36 @@
     else
       msg.send 'Please provied tag'
       return
-    Instagram.tags.recent
+    Instagram.tags.recent
       name: tag
       count: count
       complete: (data) ->
        for item in data
           msg.send item['images']['standard_resolution']['url']

+module.exports = (robot) ->
+  robot.respond /(kyle)( me )?(.*)/i, (msg) ->
+    count = 1
+    authenticateUser(msg)
+    if msg.match[3]
+      text = msg.match[3].trim().split(" ")
+      tag =  text[0]
+      count = parseInt(text[1]) if text[1]
+    else
+      msg.send 'Please provied tag'
+      return
+    Instagram.tags.search
+      q: 'kyleinfrontofwalls'
+      count: count
+      complete: (data) ->
+        images = item['images']['standard_resolution']['url']
+        msg.send images[Math.floor(Math.random() * images.length)]
+
 authenticateUser = (msg) ->
   config =
     client_key:     process.env.HUBOT_INSTAGRAM_CLIENT_KEY
     client_secret:  process.env.HUBOT_INSTAGRAM_ACCESS_KEY
-
+
   unless config.client_key
     msg.send "Please set the HUBOT_INSTAGRAM_CLIENT_KEY environment variable."
     return
@@ -52,6 +70,6 @@
   Instagram.set('client_id', config.client_key)
   Instagram.set('client_secret', config.client_secret)

-

+


:lipstick:

:lipstick:

--- spec/atom/line-wrapper-spec.coffee
+++ spec/atom/line-wrapper-spec.coffee
@@ -29,9 +29,9 @@
       describe "when the number of screen lines remains the same for the changed buffer line", ->
         it "re-wraps the existing lines and emits a change event for all its screen lines", ->
           buffer.insert([6, 28], '1234567')
-          expect(tokensText(wrapper.screenLineForRow(7).tokens)).toBe '      current < pivot ? left1234567.push(current) '
-          expect(tokensText(wrapper.screenLineForRow(8).tokens)).toBe ': right.push(current);'
-          expect(tokensText(wrapper.screenLineForRow(9).tokens)).toBe '    }'
+          expect(wrapper.screenLineForRow(7).text).toBe '      current < pivot ? left1234567.push(current) '
+          expect(wrapper.screenLineForRow(8).text).toBe ': right.push(current);'
+          expect(wrapper.screenLineForRow(9).text).toBe '    }'

           expect(changeHandler).toHaveBeenCalled()
           [event] = changeHandler.argsForCall[0]
@@ -41,10 +41,10 @@
       describe "when the number of screen lines increases for the changed buffer line", ->
         it "re-wraps and adds an additional screen line and emits a change event for all screen lines", ->
           buffer.insert([6, 28], '1234567890')
-          expect(tokensText(wrapper.screenLineForRow(7).tokens)).toBe '      current < pivot ? '
-          expect(tokensText(wrapper.screenLineForRow(8).tokens)).toBe 'left1234567890.push(current) : '
-          expect(tokensText(wrapper.screenLineForRow(9).tokens)).toBe 'right.push(current);'
-          expect(tokensText(wrapper.screenLineForRow(10).tokens)).toBe '    }'
+          expect(wrapper.screenLineForRow(7).text).toBe '      current < pivot ? '
+          expect(wrapper.screenLineForRow(8).text).toBe 'left1234567890.push(current) : '
+          expect(wrapper.screenLineForRow(9).text).toBe 'right.push(current);'
+          expect(wrapper.screenLineForRow(10).text).toBe '    }'

           expect(changeHandler).toHaveBeenCalled()
           [event] = changeHandler.argsForCall[0]
@@ -54,8 +54,8 @@
       describe "when the number of screen lines decreases for the changed buffer line", ->
         it "re-wraps and removes a screen line and emits a change event for all screen lines", ->
           buffer.change(new Range([6, 24], [6, 42]), '')
-          expect(tokensText(wrapper.screenLineForRow(7).tokens)).toBe '      current < pivot ?  : right.push(current);'
-          expect(tokensText(wrapper.screenLineForRow(8).tokens)).toBe '    }'
+          expect(wrapper.screenLineForRow(7).text).toBe '      current < pivot ?  : right.push(current);'
+          expect(wrapper.screenLineForRow(8).text).toBe '    }'

           expect(changeHandler).toHaveBeenCalled()
           [event] = changeHandler.argsForCall[0]
@@ -65,10 +65,10 @@
     describe "when buffer lines are inserted", ->
       it "re-wraps existing and new screen lines and emits a change event", ->
         buffer.insert([6, 21], '1234567890 abcdefghij 1234567890\nabcdefghij')
-        expect(tokensText(wrapper.screenLineForRow(7).tokens)).toBe '      current < pivot1234567890 abcdefghij '
-        expect(tokensText(wrapper.screenLineForRow(8).tokens)).toBe '1234567890'
-        expect(tokensText(wrapper.screenLineForRow(9).tokens)).toBe 'abcdefghij ? left.push(current) : '
-        expect(tokensText(wrapper.screenLineForRow(10).tokens)).toBe 'right.push(current);'
+        expect(wrapper.screenLineForRow(7).text).toBe '      current < pivot1234567890 abcdefghij '
+        expect(wrapper.screenLineForRow(8).text).toBe '1234567890'
+        expect(wrapper.screenLineForRow(9).text).toBe 'abcdefghij ? left.push(current) : '
+        expect(wrapper.screenLineForRow(10).text).toBe 'right.push(current);'

         expect(changeHandler).toHaveBeenCalled()
         [event] = changeHandler.argsForCall[0]
@@ -78,10 +78,10 @@
     describe "when buffer lines are removed", ->
       it "removes screen lines and emits a change event", ->
         buffer.change(new Range([3, 21], [7, 5]), ';')
-        expect(tokensText(wrapper.screenLineForRow(3).tokens)).toBe '    var pivot = items;'
-        expect(tokensText(wrapper.screenLineForRow(4).tokens)).toBe '    return '
-        expect(tokensText(wrapper.screenLineForRow(5).tokens)).toBe 'sort(left).concat(pivot).concat(sort(right));'
-        expect(tokensText(wrapper.screenLineForRow(6).tokens)).toBe '  };'
+        expect(wrapper.screenLineForRow(3).text).toBe '    var pivot = items;'
+        expect(wrapper.screenLineForRow(4).text).toBe '    return '
+        expect(wrapper.screenLineForRow(5).text).toBe 'sort(left).concat(pivot).concat(sort(right));'
+        expect(wrapper.screenLineForRow(6).text).toBe '  };'

         expect(changeHandler).toHaveBeenCalled()
         [event] = changeHandler.argsForCall[0]


Added 'hidden' and 'shown' events for ST.View when hidden or shown.

--- lib/ST/View.coffee
+++ lib/ST/View.coffee
@@ -153,13 +153,15 @@
   @method 'hide', ->
     @visible false if @_visible

-  @method 'setVisible', (visible) ->
-    @_visible = visible
-    if visible
-      @load() unless @_loaded
-      @element().show()
-    else
-      @element().hide()
+  @method 'setVisible', (value) ->
+    if value isnt @_visible
+      if @_visible = value
+        @load() unless @_loaded
+        @element().show()
+        @trigger 'shown'
+      else
+        @element().hide()
+        @trigger 'hidden'

   @method 'takeKeyboardFocus', ->
     stack = ST.View.keyboardFocusStack()


GetPresetCurve: Fix missing .disconnect()

Causes surrounding network to never stop

--- components/GetPresetCurve.coffee
+++ components/GetPresetCurve.coffee
@@ -21,6 +21,7 @@
     return unless c.outPorts.curve.isAttached()
     return unless payload of presets
     c.outPorts.curve.send presets[payload]
+    c.outPorts.curve.disconnect()

   c.outPorts.add 'curve'


Expose the memo as a property of the event

--- tapestry-core/src/main/coffeescript/META-INF/modules/core/pubsub.coffee
+++ tapestry-core/src/main/coffeescript/META-INF/modules/core/pubsub.coffee
@@ -127,6 +127,7 @@
     return exports if not list

     event =
+      memo: memo
       running: true
       stimulus: stimulusName
       stop: -> running = false


Include resource expansion in middleware route def processing

--- lib/adapter.coffee
+++ lib/adapter.coffee
@@ -4,6 +4,7 @@
 noService = require './noService'
 resolve = require './resolve'
 makeRouter = require './makeRouter'
+expandResources = require './expandResources'

 # Given a collection of route defs with resolved law services
@@ -13,7 +14,8 @@
 #   routeDefs :: config object for RESTful routing
 makeAdapter = (services, routeDefs) ->

-  resolved = resolve services, routeDefs
+  expandedDefs = expandResources routeDefs
+  resolved = resolve services, expandedDefs

   match = (req) ->
     method = req.method.toLowerCase()


huge clean up of git-commit-spec.coffee

huge clean up of git-commit-spec.coffee

--- spec/models/git-commit-spec.coffee
+++ spec/models/git-commit-spec.coffee
@@ -5,7 +5,6 @@
 git = require '../../lib/git'
 GitCommit = require '../../lib/models/git-commit-beta'

-# status = jasmine.createSpyObj('status', ['replace', 'trim'])
 status =
   replace: -> status
   trim: -> status
@@ -30,38 +29,29 @@
 describe "GitCommit", ->
   describe "a regular commit", ->
     it "saves the current pane", ->
-      commit = GitCommit(repo)
-      expect(commit.currentPane).toBeDefined()
+      expect(GitCommit(repo).currentPane).toBeDefined()

     describe "::start", ->
+      commit = null
+      beforeEach ->
+        mockGit()
+        commit = GitCommit(repo)
+        waitsForPromise ->
+          commit.start()
+
       it "gets the commentchar from configs", ->
-        waitsForPromise ->
-          mockGit()
-          GitCommit(repo).start().then ->
-            expect(git.cmd).toHaveBeenCalledWith ['config', '--get', 'core.commentchar']
+        expect(git.cmd).toHaveBeenCalledWith ['config', '--get', 'core.commentchar']

       it "gets staged files", ->
-        waitsForPromise ->
-          mockGit()
-          GitCommit(repo).start().then ->
-            expect(git.cmd).toHaveBeenCalledWith ['status'], cwd: repo.getWorkingDirectory()
+        expect(git.cmd).toHaveBeenCalledWith ['status'], cwd: repo.getWorkingDirectory()

       it "removes lines with '(...)' from status", ->
-        waitsForPromise ->
-          mockGit()
-          GitCommit(repo).start().then ->
-            expect(status.replace).toHaveBeenCalled()
+        expect(status.replace).toHaveBeenCalled()

       it "gets the commit template from git configs", ->
-        waitsForPromise ->
-          mockGit()
-          GitCommit(repo).start().then ->
-            expect(git.cmd).toHaveBeenCalledWith ['config', '--get', 'commit.template']
+        expect(git.cmd).toHaveBeenCalledWith ['config', '--get', 'commit.template']

       it "writes to a file and the commentchar is default '#'", ->
-        waitsForPromise ->
-          mockGit()
-          GitCommit(repo).start().then ->
-            argsTo_fsWriteFile = fs.writeFileSync.mostRecentCall.args
-            expect(argsTo_fsWriteFile[0]).toEqual Path.join(repo.getPath(), 'COMMIT_EDITMSG')
-            expect(argsTo_fsWriteFile[1].charAt(0)).toBe '#'
+        argsTo_fsWriteFile = fs.writeFileSync.mostRecentCall.args
+        expect(argsTo_fsWriteFile[0]).toEqual Path.join(repo.getPath(), 'COMMIT_EDITMSG')
+        expect(argsTo_fsWriteFile[1].charAt(0)).toBe '#'


use EA restrict for coffee directive

use EA restrict for coffee directive

--- templates/directiveComplex/name.directive.coffee
+++ templates/directiveComplex/name.directive.coffee
@@ -2,5 +2,5 @@

 angular.module('<%= scriptAppName %>').directive '<%= cameledName %>', ->
   templateUrl: '<%= htmlUrl %>'
-  restrict: 'E'
+  restrict: 'EA'
   link: (scope, element, attrs) ->


:arrow_up: add local item(inside classes...etc) routing

--- src/server/stateInitializer/routes-gen.coffee
+++ src/server/stateInitializer/routes-gen.coffee
@@ -25,6 +25,8 @@
         else
           child.children?.forEach (gchild) ->
             routes["#{prefix}#{if dir_arr.length == 1 then '' else '/' + dir_arr[0..(j - 1)].join('/')}/#{gchild.name}"] = "#{prefix}:global:#{child.id}:#{gchild.id}"
+            gchild.children?.forEach (ggchild) ->
+              routes["#{prefix}#{if dir_arr.length == 1 then '' else '/' + dir_arr[0..(j - 1)].join('/')}/#{gchild.name}/#{ggchild.name}"] = "#{prefix}:local:#{child.id}:#{gchild.id}:#{ggchild.id}"
     routes["#{prefix}"] = "#{prefix}"
     return routes


Actually do the work in another tick

Actually do the work in another tick

--- public/coffee/services.coffee
+++ public/coffee/services.coffee
@@ -225,14 +225,15 @@
     def = $q.defer()
     pending = []

-    for node in tree
-      node.collapsed = setting
-      pending.push expandTree node.children, setting
-
-    if pending.length
-      $q.all(pending).then -> def.resolve tree
-    else
-      def.resolve tree
+    $timeout ->
+      for node in tree
+        node.collapsed = setting
+        pending.push expandTree node.children, setting
+
+      if pending.length
+        $q.all(pending).then -> def.resolve tree
+      else
+        def.resolve tree

     return def.promise


Build view: Use addBottomPanel

Build view: Use addBottomPanel

`workspaceView.prependToBottom` was deprecated in 0.139.0,
use the alternative 'addBottomPanel'.

--- lib/build-view.coffee
+++ lib/build-view.coffee
@@ -32,7 +32,7 @@
     atom.config.observe 'build.minimizedHeight', @heightFromConfig

   attach: ->
-    atom.workspaceView.prependToBottom(this)
+    atom.workspace.addBottomPanel({ item: this })

   detach: (force = false) ->
     atom.workspaceView.focus();


add some documentation of the available options for Dialog.open

--- vendor/assets/javascripts/nifty/dialog.coffee
+++ vendor/assets/javascripts/nifty/dialog.coffee
@@ -24,9 +24,22 @@

   # Open a new dialog which will accept a number of possible options.
   #
+  #   id         => the ID to assign to this dialog (prefixed with 'niftyDialog-' )
+  #
   #   url        => open a dialog containing the HTML at the given URL. When
   #                 displaying using a URL, the dialog will open immediately
   #                 and containing a spinner until the data is loaded.
+  #
+  #   html       => a string of HTML which contains the HTML which should be
+  #                 displayed in the dialog.
+  #
+  #   afterLoad  => a callback to execute after the dialog has been loaded.
+  #
+  #   width      => the width of the dialog (in px, defaults to CSS-provided)
+  #
+  #   offset     => specifies a vertical offset (in px)
+  #
+  #   class      => the CSS class to assign to this dialog
   #
   open: (options={})->


Helps to actually save the detail import job.

--- jobs/import-legislation.coffee
+++ jobs/import-legislation.coffee
@@ -135,7 +135,7 @@

     db.collection("legislation").find(sessionId: job.data.session._id).toArray (err, results) -> ifSuccessful err, callback, ->
       results.forEach (legislation) ->
-        jobs.create('import legislation detail', legislation: legislation)
+        jobs.create('import legislation detail', legislation: legislation).save()

       callback()


don't pass an undefined name property

don't pass an undefined name property

--- src/kite/kite.coffee
+++ src/kite/kite.coffee
@@ -57,7 +57,7 @@
   # event handlers:
   onOpen: ->
     @readyState = READY
-    @emit 'connected', @name
+    @emit 'connected'
     @emit 'ready'
     @emit 'info', "Connected to Kite: #{ @options.url }"
     @clearBackoffTimeout()


remove noisy log from tests

remove noisy log from tests

--- test/basic.coffee
+++ test/basic.coffee
@@ -37,10 +37,7 @@
     migrator.add
       id: '1'
       up: (cb) ->
-        setTimeout () ->
-          console.log 'running callback'
-          cb()
-        , 300
+        setTimeout cb, 300
     migrator.migrate (err) ->
       return done(new Error 'migration should have failed') if not err
       err.message.should.be.equal 'migration timed-out'


fixes js bug

fixes js bug

--- app/assets/javascripts/spree/frontend/global_collect_hml.coffee
+++ app/assets/javascripts/spree/frontend/global_collect_hml.coffee
@@ -4,7 +4,7 @@

   if $select.is('*')
     $select.change ->
-      linkId = ($ this).data('link')
+      linkId = ($ this).parent('select').data('link')
       $("#{linkId}").data('payment-product', ($ this).val())

     $link.click (event) ->


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/color.coffee
+++ test/color.coffee
@@ -19,7 +19,7 @@
   equals color.a(), 0.45, 'alpha channel should equal input alpha value'

 test "Color should parse hex starting with #", ->
-  color = Color('#ffffff')
+  color = Color('ffffff')
   equals color.r(), 255, 'red channel should equal numeric equivalent of ff'
   equals color.g(), 255, 'green channel should equal numeric equivalent of ff'
   equals color.b(), 255, 'blue channel should equal numeric equivalent of ff'


[experiment] InnerPair pre-targeted version of reverse and split-by-arguments

--- lib/operator-transform-string.coffee
+++ lib/operator-transform-string.coffee
@@ -650,6 +650,11 @@
   @registerToSelectList()
   keepSeparator: false

+class SplitByArgumentsOfInnerAnyPair extends SplitByArguments
+  @extend()
+  @registerToSelectList()
+  target: "InnerAnyPair"
+
 class ChangeOrder extends TransformString
   @extend(false)
   getNewText: (text) ->
@@ -664,6 +669,10 @@
   getNewList: (rows) ->
     rows.reverse()

+class ReverseInnerAnyPair extends Reverse
+  @extend()
+  target: "InnerAnyPair"
+
 class Rotate extends ChangeOrder
   @extend()
   @registerToSelectList()


cleanup

cleanup

--- lib/operator-transform-string.coffee
+++ lib/operator-transform-string.coffee
@@ -415,10 +415,6 @@
   requireTarget: true
   supportEarlySelect: true # Experimental

-  initialize: ->
-    @subscribeForInput()
-    super
-
   focusInputForSurround: ->
     inputUI = @newInputUI()
     inputUI.onDidConfirm(@onConfirmSurround.bind(this))
@@ -471,8 +467,9 @@
   @extend()
   @description: "Surround target by specified character like `(`, `[`, `\"`"

-  subscribeForInput: ->
+  initialize: ->
     @onDidSelectTarget(@focusInputForSurround.bind(this))
+    super

   getNewText: (text) ->
     @surround(text, @input)
@@ -500,9 +497,9 @@
   @description: "Delete specified surround character like `(`, `[`, `\"`"
   requireTarget: false

-  subscribeForInput: ->
-    unless @hasTarget()
-      @focusInputForDeleteSurround()
+  initialize: ->
+    @focusInputForDeleteSurround() unless @hasTarget()
+    super

   onConfirmDeleteSurround: (input) ->
     super
@@ -533,12 +530,13 @@
     char = @editor.getSelectedText()[0]
     @vimState.hover.set(char, @vimState.getOriginalCursorPosition())

-  subscribeForInput: ->
+  initialize: ->
     if @hasTarget()
       @onDidFailSelectTarget(@abort.bind(this))
     else
       @onDidFailSelectTarget(@cancelOperation.bind(this))
       @focusInputForDeleteSurround()
+    super

     @onDidSelectTarget =>
       @showDeleteCharOnHover()


pixi render on text change

pixi render on text change

--- src/renderer/impl/pixi/level0/text.coffee
+++ src/renderer/impl/pixi/level0/text.coffee
@@ -26,6 +26,7 @@
             item.contentWidth = textElem.canvas.width / textElem.resolution
             item.contentHeight = textElem.canvas.height / textElem.resolution
             updateAlignment item
+            impl._dirty = true
             return

         updateAll = (item) ->


fix test layout requires

fix test layout requires

--- src/layout/test_layout.coffee
+++ src/layout/test_layout.coffee
@@ -1,10 +1,11 @@
 {my} = require '../my'
+{game} = require '../game'

-{game} = require '../game'
 {layout} = require '../layout'
-{header} = require '../layout/header'
-{grid} = require '../layout/grid'
-{controls} = require '../layout/controls'
+{header} = require './header'
+{controls} = require './controls'
+{grid} = require './grid'
+{sprite} = require './sprite'

 exports.test_layout = (test, rx) ->
   game_dict = game({name: 'example', level: 1})


Add \!dump command

Add \!dump command

--- lib/dispatcher.coffee
+++ lib/dispatcher.coffee
@@ -65,12 +65,18 @@
       @_invalidate key for key in keys
     else if source == '!dep'
       @_record_dep keys...
+    else if source == '!dump'
+      @_dump_link()
     else if source == '!replace'
       @_replace keys[0], keys[1..-1].join('|')
     else if keys?.length
       @_new_request source, keys
     else
       @_seed source
+
+  # Store the current links in the 'deps' key
+  _dump_link: ->
+    @_db().set 'deps', JSON.stringify(@link)

   # The given key is a 'seed' request. In test mode, completion of
   # the seed request signals termination of the workers.
@@ -156,6 +162,7 @@
   # The seed request was completed. In test mode, quit the workers.
   _unseed: ->
     @_clear_timeout()
+    @_dump_link()
     @quit() if @_test_mode

   # Called when a key is completed. Any jobs depending on this


remove unused unmet member

remove unused unmet member

--- lib/dispatcher.coffee
+++ lib/dispatcher.coffee
@@ -26,7 +26,6 @@
     @_count = {}
     @_state = {}
     @_cycles = {}
-    @_unmet = 0

   # Subscribe to the `requests` and `responses` channels.
   listen: ->
@@ -111,7 +110,6 @@
   # zero, it is rescheduled.
   _progress: (keys) ->
     for key in keys
-      @_unmet--
       unless --@_count[key]
         @_reschedule key

@@ -199,7 +197,6 @@
       when 'done' then return
       when undefined then @_reqs.push key
     (@deps[key] ?= []).push source
-    @_unmet++
     @_count[source]++

   # Take the unmet dependencies from the latest request and push


Stub logs better, attempting to send message here too

--- test/front.coffee
+++ test/front.coffee
@@ -16,15 +16,18 @@

   it 'should start a WSS', ->
     stub = new WebSocketServer({port: 3021, host: "0.0.0.0"});
-    stub.on 'connection', (ws) ->
-      console.log 'input was' + ws
+    stub.on 'connection', () ->
+      console.log 'Stub got a connection'
     stub.on 'message', (message) ->
-      console.log message
+      console.log "Stub got message:" + message
+      stub.send 'Hello'

     @front.start {port: 3020, host: "0.0.0.0", apiEndpoint: "ws://localhost:3021"}
     client = new WebSocket("ws://localhost:3020")
     client.on 'connection', () ->
-      client.send 'my message is foo'
+      client.send '{"itsjson":"morejson"}'
+    client.on 'message', (message) ->
+      console.log "Client of front-end got message:" + message

   it 'should connect to the API', ->


fix proxy

fix proxy

--- test/model.coffee
+++ test/model.coffee
@@ -156,4 +156,5 @@
       done()

     inst.age = '23'
+    inst.firstName = 'Ellen'
     inst.save()


Remove dev code

Remove dev code

--- src/smc-webapp/course/students_panel.cjsx
+++ src/smc-webapp/course/students_panel.cjsx
@@ -4,7 +4,6 @@
 {salvus_client} = require('../salvus_client')

 # React libraries and components
-window.Perf = require('react-addons-perf')
 {React, ReactDOM, rclass, rtypes}  = require('../smc-react')
 {Button, ButtonToolbar, ButtonGroup, FormGroup, FormControl, InputGroup, Row, Col, Panel} = require('react-bootstrap')


failtimer duration increased for couldnt connect to backend modal

--- client/landing/app/MainApp/maincontroller/maincontroller.coffee
+++ client/landing/app/MainApp/maincontroller/maincontroller.coffee
@@ -16,7 +16,7 @@

   constructor:(options = {}, data)->

-    options.failWait  = 5000            # duration in miliseconds to show a connection failed modal
+    options.failWait  = 10000            # duration in miliseconds to show a connection failed modal

     super options, data


Adjust test to check upper case X cell content.

--- src/spec/producttypegenerator.spec.coffee
+++ src/spec/producttypegenerator.spec.coffee
@@ -371,7 +371,7 @@
     productTypeDefinition2 =
       name: 'ProductType2'
       description: 'Description2'
-      size: 'x'
+      size: 'X'

     productTypeDefinitions = [productTypeDefinition1, productTypeDefinition2]


pass loop iterator test

pass loop iterator test

--- test/scope.coffee
+++ test/scope.coffee
@@ -71,13 +71,12 @@
       ok not k
     return

-  # FAIL
-  #test 'loop iterators available outside the loop (ew)', ->
-  # fn = ->
-  # for v, k in [1]
-  #   fn()
-  # ok v
-  # ok not k
+  test 'loop iterators available outside the loop (ew)', ->
+    fn = ->
+    for v, k in [1]
+      fn()
+    ok v
+    ok not k

   test '`do` acts as `let`', ->
     outerNonce = nonce = {}


added $localeName contain current locale name

--- tasks/i18n.coffee
+++ tasks/i18n.coffee
@@ -46,6 +46,7 @@
         opts.data = {} unless _.isPlainObject opts.data
         opts.data = _.extend opts.data, readFile filepath
         opts.data[namespace] = readFile filepath
+        opts.data.$localeName = locale

         # translate output destination for each language
         config.files = _.cloneDeep(@files).map (file) ->


Fixes remoteReleasesUrl path (removes /raw)

--- tasks/pack.coffee
+++ tasks/pack.coffee
@@ -337,7 +337,7 @@
         process.env.SIGN_WIN_CERTIFICATE_PASSWORD
       ]

-      remoteReleasesUrl = manifest.updater.urls.win32 + '/raw'
+      remoteReleasesUrl = manifest.updater.urls.win32
       releasesUrl = manifest.updater.urls.win32 + '/RELEASES'

       request {url: releasesUrl}, (err, res, body) ->


hrmmm

hrmmm

--- client/app/Applications/Apps.kdapplication/Views/AppsListItemView.coffee
+++ client/app/Applications/Apps.kdapplication/Views/AppsListItemView.coffee
@@ -73,20 +73,20 @@
       {{> @thumbnail}}

-
{a[href=#]{#(title)}}

+
{a[href="#"]{#(title)}}

-          {{#(counts.installed) or 0}} Installs
+          {{#(counts.installed) || 0}} Installs

-          {{#(counts.followers) or 0}} Followers
+          {{#(counts.followers) || 0}} Followers

-
{a[href=#]{#(title)}}

+
{a[href="#"]{#(title)}}

{{@utils.shortenText #(body)}}


Stil für ein- und ausgehende Wege angepasst.

--- src/main/coffee/styles.coffee
+++ src/main/coffee/styles.coffee
@@ -15,6 +15,8 @@
     # Eingehender Weg
     incomingWay: $.extend({}, defaultWayStyle,
       color: "#ff0000"
+      opacity: 0.8
+      weight: 6
     )
     # Knoten
     node: $.extend({}, defaultStyle,
@@ -23,6 +25,8 @@
     # Ausgehender Weg
     outgoingWay: $.extend({}, defaultWayStyle,
       color: "#00ff00"
+      opacity: 0.8
+      weight: 6
     )
     # Pfad
     path: $.extend({}, defaultWayStyle,


Boyscouting

Boyscouting

--- core/app/backbone/factlink/add_model_to_collection_mixin.coffee
+++ core/app/backbone/factlink/add_model_to_collection_mixin.coffee
@@ -5,10 +5,10 @@
     @options.addToCollection.add(model, options)
     model.save {},
       success: =>
-        @addModelSuccess(model) if @addModelSuccess
+        @addModelSuccess(model) if @addModelSuccess?
       error: =>
         @options.addToCollection.remove(model)
-        @addModelError(model) if @addModelError
+        @addModelError(model) if @addModelError?

   addDefaultModel: (options) -> @addModel @model, options


Add notification for invalid LaTeX root file

--- lib/manager.coffee
+++ lib/manager.coffee
@@ -51,6 +51,17 @@

   findMain: (here) ->
     result = @findMainSequence(here)
+    if !fs.existsSync(@latex.mainFile)
+      @latex.logger.processError(
+        "Invalid LaTeX root file `#{path.basename(@latex.mainFile)}`",
+        "The path #{@latex.mainFile} does not exist!", true,
+        [{
+          text: "Set LaTeX root"
+          onDidClick: =>
+            @latex.manager.refindMain()
+            @latex.logger.clearBuildError()
+        }])
+      return false
     @latex.panel.view.update()
     return result


:bug: Bad value returned in getCharHeight

--- lib/minimap.coffee
+++ lib/minimap.coffee
@@ -56,7 +56,7 @@

   getCharWidth: -> @charWidth

-  getCharHeight: -> @charWidth
+  getCharHeight: -> @charHeight

   getInterline: -> @interline


Exposes methods to retrieve a minimal for an editor view, a pane view or a pane model

--- lib/minimap.coffee
+++ lib/minimap.coffee
@@ -32,6 +32,17 @@
   updateAllViews: ->
     view.onScrollViewResized() for id,view of @minimapViews

+  minimapForEditorView: (editorView) ->
+    @minimapForPaneView(editorView.getPane())
+
+  minimapForPaneView: (paneView) -> @minimapForPane(paneView.model)
+
+  minimapForPane: (pane) ->
+    console.log pane
+    console.log pane.id
+    console.log @minimapViews
+    @minimapViews[pane.id]
+
   open: ->
     # When toggled we'll look for each existing and future pane thanks to
     # the `eachPaneView` method. It returns a subscription object so we'll


:fire: cleanup duplicate constructor.

:fire: cleanup duplicate constructor.

--- lib/motions.coffee
+++ lib/motions.coffee
@@ -20,7 +20,7 @@
   complete: true
   recordable: false

-  constructor: (@vimState) ->
+  constructor: (@vimState, @options={}) ->
     {@editor, @editorElement} = @vimState

   select: (options) ->
@@ -510,10 +510,10 @@
   @extend()
   backwards: false
   offset: 0
-  constructor: (@vimState, options={}) ->
-    super(@vimState)
-
-    if not options.repeated
+  constructor: ->
+    super
+
+    if not @options.repeated
       @viewModel = new ViewModel(this, class: 'find', singleChar: true, hidden: true)
       # @backwards = false # Moved to prototype property `backwards: false`
       @repeated = false
@@ -527,7 +527,7 @@
       @complete = orig.complete
       @input = orig.input

-      @reverse() if options.reverse
+      @reverse() if @options.reverse

   match: (cursor, count) ->
     currentPosition = cursor.getBufferPosition()
@@ -589,13 +589,14 @@
 class MoveToMark extends MotionWithInput
   @extend()
   operatesInclusively: false
-
-  constructor: (@vimState, @linewise=true) ->
-    super(@vimState)
-    @operatesLinewise = @linewise
+  operatesLinewise: true
+
+  constructor: ->
+    super
     @viewModel = new ViewModel(this, class: 'move-to-mark', singleChar: true, hidden: true)

-  isLinewise: -> @linewise
+  isLinewise: ->
+    @operatesLinewise

   moveCursor: (cursor) ->
     markPosition = @vimState.getMark(@input.characters)
@@ -605,26 +606,25 @@
       @vimState.setMark('`', cursor.getBufferPosition())

     cursor.setBufferPosition(markPosition) if markPosition?
-    if @linewise
+    if @operatesLinewise
       cursor.moveToFirstCharacterOfLine()

 # keymap: `
 class MoveToMarkLiteral extends MoveToMark
   @extend()
-
-  constructor: (@vimState) ->
-    super(@vimState, false)
+  operatesLinewise: false

 # Search
 # -------------------------
 class SearchBase extends MotionWithInput
   @extend()
   operatesInclusively: false
-
-  constructor: (@vimState, options={}) ->
-    super(@vimState)
+  dontUpdateCurrentSearch: false
+
+  constructor: ->
+    super
     @reverse = @initiallyReversed = false
-    @updateCurrentSearch() unless options.dontUpdateCurrentSearch
+    @updateCurrentSearch() unless @dontUpdateCurrentSearch

   reversed: =>
     @initiallyReversed = @reverse = true
@@ -706,7 +706,7 @@
   @keywordRegex: null
   complete: true

-  constructor: (@vimState) ->
+  constructor: ->
     super

     # FIXME: This must depend on the current language
@@ -767,9 +767,10 @@
 class RepeatSearch extends SearchBase
   @extend()
   complete: true
-
-  constructor: (@vimState) ->
-    super(@vimState, dontUpdateCurrentSearch: true)
+  dontUpdateCurrentSearch: true
+
+  constructor: ->
+    super
     @input = new Input(@vimState.getSearchHistoryItem(0) ? "")
     @replicateCurrentSearch()


Cleanup

Cleanup

--- lib/project.coffee
+++ lib/project.coffee
@@ -73,7 +73,7 @@
           @props._id = newProject._id

   remove: ->
-    @db = new DB() unless @db
+    @db ?= new DB()
     removed = @db.delete @props._id

   open: ->


Add explicit return to Terminal

Add explicit return to Terminal

--- system/Terminal.coffee
+++ system/Terminal.coffee
@@ -61,3 +61,5 @@
       return null if newlinePresent is false
       keyBuffer = keyBuffer.substr(lineSize + 1)
       return line
+
+  return Terminal


lib: Expose runtime.handleMessage again

lib: Expose runtime.handleMessage again

noflo-runtime still relies on it

--- lib/runtime.coffee
+++ lib/runtime.coffee
@@ -414,3 +414,4 @@
     uploadGraph: uploadGraph
     createFlowhubRuntime: createFlowhubRuntime
     registerFlowhubRuntime: registerFlowhubRuntime
+    handleMessage: handleMessage


替换.-@为下划线

替换.-@为下划线

--- lib/steedos.coffee
+++ lib/steedos.coffee
@@ -143,7 +143,7 @@
                         for topic in req.body.pushTopics
                             eventName = topic
                             if req.param("steedosId")?
-                                eventName = eventName + "|" + req.param("steedosId").replace("@", "_").replace(".", "_")
+                                eventName = eventName + "|" + req.param("steedosId").replace(/[@\-\.]/g, "_")
                             events[eventName] = {}
                         subscriber.addSubscriptions events, (r) ->
                             generateResponse(req, res, subscriber)
@@ -168,7 +168,7 @@
                         for topic in req.body.pushTopics
                             eventName = topic
                             if req.param("steedosId")?
-                                eventName = eventName + "|" + req.param("steedosId").replace("@", "_").replace(".", "_")
+                                eventName = eventName + "|" + req.param("steedosId").replace(/[@\-\.]/g, "_")
                             events[eventName] = {}
                         subscriber.addSubscriptions events, (r) ->
                             generateResponse(req, res, subscriber)
@@ -192,7 +192,7 @@
                 for topic in req.body.pushTopics
                     eventName = topic
                     if req.param("steedosId")?
-                        eventName = eventName + "|" + req.param("steedosId").replace("@", "_").replace(".", "_")
+                        eventName = eventName + "|" + req.param("steedosId").replace(/[@\-\.]/g, "_")
                     events[eventName] = {}
                 req.subscriber.addSubscriptions events, (r) ->
                     generateResponse(req, res, req.subscriber)
@@ -216,7 +216,7 @@
                 for topic in req.body.pushTopics
                     eventName = topic
                     if req.param("steedosId")?
-                        eventName = eventName + "|" + req.param("steedosId").replace("@", "_").replace(".", "_")
+                        eventName = eventName + "|" + req.param("steedosId").replace(/[@\-\.]/g, "_")
                     events[eventName] = {}
                 req.subscriber.removeSubscriptions events, (r) ->
                     generateResponse(req, res, req.subscriber)
@@ -235,7 +235,7 @@
             if req.body.pushTopic?
                 if req.body.toUsers?
                     for user in req.body.toUsers
-                        eventName = req.body.pushTopic + "|" + user.replace("@", "_").replace(".", "_")
+                        eventName = req.body.pushTopic + "|" + user.replace(/[@\-\.]/g, "_")
                         event = getEventFromId(eventName)
                         message = {}
                         if req.body.data?


properties: rename self to exports

properties: rename self to exports

--- lib/properties.coffee
+++ lib/properties.coffee
@@ -5,7 +5,7 @@
 builder = require 'xmlbuilder'
 misc = require 'mecano/lib/misc'

-self = module.exports =
+module.exports = exports =
   ###
   `parse(xml, [property])`
   ----------------------------------
@@ -100,7 +100,7 @@
       property = null
     fs.readFile ssh, path, 'utf8', (err, markup) ->
       return callback err if err
-      callback null, self.parse markup, property
+      callback null, exports.parse markup, property
   ###
   `write([ssh], path, properties, callback)`
   ------------------------------------------
@@ -116,7 +116,7 @@
     path = args[0]
     properties = args[1]
     callback = args[2]
-    markup = self.stringify properties
+    markup = exports.stringify properties
     fs.writeFile ssh, path, markup, (err) ->
       return callback err if err
       callback null, markup


:lipstick: Refactor columns widths stringification

--- lib/table-view.coffee
+++ lib/table-view.coffee
@@ -58,10 +58,11 @@
   #     ######   #######  ########  #######  ##     ## ##    ##  ######

   getColumnsWidths: ->
-    return @columnsWidths if @columnsWidths?
+    return @columnsPercentWidths if @columnsPercentWidths?

     count = @table.getColumnsCount()
-    @columnsWidths = ("#{Math.round 1 / count * 100}%" for n in [0...count])
+    @columnsWidths = (1 / count for n in [0...count])
+    @columnsPercentWidths = @columnsWidths.map @floatToPercent

   setColumnsWidths: (columnsWidths) ->
     restWidth = 1
@@ -89,7 +90,8 @@
     if wholeWidth > 1
       widths = widths.map (w) -> w * (1 / wholeWidth)

-    @columnsWidths = widths.map (w) -> "#{Math.round w * 100}%"
+    @columnsWidths = widths
+    @columnsPercentWidths = widths.map @floatToPercent

     @requestUpdate(true)

@@ -140,3 +142,5 @@
     @hasChanged = false

   asDisposable: (subscription) -> new Disposable -> subscription.off()
+
+  floatToPercent: (w) -> "#{Math.round w * 100}%"


Fix composition bug.

Fix composition bug.

--- src/chaplin/lib/composition.coffee
+++ src/chaplin/lib/composition.coffee
@@ -53,7 +53,7 @@

     # Sets the stale property for every item in the composition that has it.
     @_stale = value
-    for name, item of this when item isnt this and _(item).has 'stale'
+    for name, item of this when item and item isnt this and _(item).has 'stale'
       item.stale = value

     # Return nothing.


GitLabProvider: replace repo from queryString as well

--- workers/social/lib/social/models/gitprovider/gitlabprovider.coffee
+++ workers/social/lib/social/models/gitprovider/gitlabprovider.coffee
@@ -11,10 +11,18 @@

 injectQueryStrings = (templateData) ->

-  { template: { content }, branch } = templateData
+  { template: { content }, user, repo, branch } = templateData
+
+  config = { repo: "#{user}/#{repo}", branch }
+
+  { content } = templateData.template
+
+  Object.keys(config).forEach (key) ->
+    value   = config[key]
+    content = content
+      .replace ///\$\{var\.koding_queryString_#{key}\}///g, value

   templateData.template.content = content
-    .replace /\$\{var\.koding_queryString_branch\}/g, branch

   return templateData


finally got this marriage generator working

--- famgen.coffee
+++ famgen.coffee
@@ -13,7 +13,7 @@
   people = []
   for index in [0..total]
     person = generatePerson()
-    person.ID = globalID += 1
+    person.id = globalID += 1
     people.push(person)
   return people

@@ -26,19 +26,28 @@

 generateMarriages = (singles) ->
   complete = []
-  for person, index in singles
+  index = 0
+  while singles.length > 1
+    console.log "#{index} vs #{singles.length-1}"
     rand = getRandomInt(index + 1, singles.length - 1)
-    console.log rand
+
     complete.push(singles[index])
     complete.push(singles[rand])
-    singles = singles.slice(rand-1, rand)
-    singles = singles.slice(index-1, index)
-  console.log singles
+
+    console.log index + 1, singles.length - 1, rand, singles.length, singles[rand]
+    complete[complete.length-2].spouseId = singles[rand].id
+    complete[complete.length-1].spouseId = singles[index].id
+
+    singles.splice(rand, 1)
+    singles.splice(index, 1)
+  return complete

 getRandomInt = (min, max) ->
   return Math.ceil((Math.random() * (max - min)) + min)

 people = generatePeople(INITIAL_PEOPLE)
-generateMarriages(people)
+complete = generateMarriages(people)
+console.log complete
+

 console.log "Complete!"


[background] removed unused variable

[background] removed unused variable

--- src/coffee/data/interpreter.coffee
+++ src/coffee/data/interpreter.coffee
@@ -8,8 +8,6 @@

     standardManifestKeys = [ 'key', 'lastupdated', 'tag', 'faction', 'refresh' ]
     standardSourceKeys = [ 'oid', 'nickname', 'name', 'level' ]
-
-    anomalies = [ '13magnus', 'recursion', 'interitus' ]

     filterEmpty = (obj) ->
         Object.each obj, (key, value) ->


Support for Meteor 1.5.1.

Support for Meteor 1.5.1.

We cannot rely anymore on the fact that server-to-server Meteor method calls have connection set to null.

Fixes: #5

--- lib.coffee
+++ lib.coffee
@@ -31,6 +31,42 @@

 SUBSCRIPTION_ID_REGEX = /_.+?$/

+subscriptionDataSet = (collection, connectionId, subscriptionDataId, path, value) ->
+  if Meteor.isClient
+    check connectionId, null
+    check subscriptionDataId, Match.DocumentId
+  else
+    check connectionId, Match.DocumentId
+    check subscriptionDataId, Match.Where checkSubscriptionDataId
+  check path, Match.Where checkPath
+  check value, Match.Any
+
+  if _.isString path
+    update = {}
+    if value is undefined
+      update.$unset = {}
+      update.$unset[path] = ''
+    else
+      update.$set = {}
+      update.$set[path] = value
+
+  # We checked that the "path" is an object.
+  else
+    # We are replacing the whole document, so we have to add
+    # "_connectionId", otherwise it will be removed.
+    update = _.extend path,
+      _connectionId: connectionId
+
+  # We make sure (on the server side) that "_connectionId" matches current
+  # connection to prevent malicious requests who guess the "subscriptionDataId"
+  # to modify the state of other subscriptions. This is not strictly needed
+  # though because on the server "subscriptionDataId" contains "connectionId".
+  collection.update
+    _id: subscriptionDataId
+    _connectionId: connectionId
+  ,
+    update
+
 share.handleMethods = (connection, collection, subscriptionDataId) ->
   dataFunction = (path, equalsFunc) ->
     getData = (fields) ->
@@ -63,27 +99,28 @@
         _connectionId: 0

   setDataFunction = (path, value) ->
-    if value is undefined
-      args = [subscriptionDataId, path]
-    else
-      args = [subscriptionDataId, path, value]
-
     oldValue = Tracker.nonreactive =>
       dataFunction path

     return if EJSON.equals value, oldValue

-    connection.apply '_subscriptionDataSet', args, (error) =>
-      console.error "_subscriptionDataSet error", error if error
+    if Meteor.isClient
+      if value is undefined
+        args = [subscriptionDataId, path]
+      else
+        args = [subscriptionDataId, path, value]
+
+      connection.apply '_subscriptionDataSet', args, (error) =>
+        console.error "_subscriptionDataSet error", error if error
+    else
+      connectionId = subscriptionDataId.replace SUBSCRIPTION_ID_REGEX, ''
+      subscriptionDataSet collection, connectionId, subscriptionDataId, path, value

   {data: dataFunction, setData: setDataFunction}

 share.subscriptionDataMethods = (collection) ->
   _subscriptionDataSet: (subscriptionDataId, path, value) ->
-    if Meteor.isClient or @connection?.id
-      check subscriptionDataId, Match.DocumentId
-    else
-      check subscriptionDataId, Match.Where checkSubscriptionDataId
+    check subscriptionDataId, Match.DocumentId
     check path, Match.Where checkPath
     check value, Match.Any

@@ -93,39 +130,10 @@
       # anyway (it is not published), so {_connectionId: null} in fact does
       # exactly the right thing: finds documents without "_connectionId".
       connectionId = null
-    else if @connection?.id
-      # Server-side call from the client. "subscriptionDataId" is only
-      # "subscriptionId" so we reconstruct whole "subscriptionDataId".
-      connectionId = @connection?.id
+    else
+      # On the server, we have to reconstruct the whole "subscriptionDataId"
+      # because  "subscriptionDataId" is given as only "subscriptionId".
+      connectionId = @connection.id
       subscriptionDataId = "#{connectionId}_#{subscriptionDataId}"
-    else
-      # On the server side @connection does not exist when method is called
-      # from the server side (for example, from the publish function) but
-      # we can get "connectionId" from "subscriptionDataId".
-      connectionId = subscriptionDataId.replace SUBSCRIPTION_ID_REGEX, ''

-    if _.isString path
-      update = {}
-      if value is undefined
-        update.$unset = {}
-        update.$unset[path] = ''
-      else
-        update.$set = {}
-        update.$set[path] = value
-
-    # We checked that the "path" is an object.
-    else
-      # We are replacing the whole document, so we have to add
-      # "_connectionId", otherwise it will be removed.
-      update = _.extend path,
-        _connectionId: connectionId
-
-    # We make sure (on the server side) that "_connectionId" matches current
-    # connection to prevent malicious requests who guess the "subscriptionDataId"
-    # to modify the state of other subscriptions. This is not strictly needed
-    # though because on the server "subscriptionDataId" contains "connectionId".
-    collection.update
-      _id: subscriptionDataId
-      _connectionId: connectionId
-    ,
-      update
+    subscriptionDataSet collection, connectionId, subscriptionDataId, path, value


makeScaledFunction: ignore if scale factor is 1

--- Smooth.coffee
+++ Smooth.coffee
@@ -141,7 +141,10 @@

 #Take a function with one parameter and apply a scale factor to its parameter
 makeScaledFunction = (f, scaleFactor) ->
-	(t) -> f(t*scaleFactor)
+	if scaleFactor is 1
+		f #don't wrap the function unecessarily
+	else
+		(t) -> f(t*scaleFactor)

 Smooth = (arr, config = {}) ->
 	config[k] ?= v for own k,v of defaultConfig #fill in defaults
@@ -181,7 +184,6 @@

 	smoothFunc = makeScaledFunction smoothFunc, (arr.length-1)/config.scaleTo if config.scaleTo

-
 	return smoothFunc


Fixed windows tests

Fixed windows tests

--- test/cwebp.coffee
+++ test/cwebp.coffee
@@ -1,4 +1,5 @@
 fs = require 'fs'
+os = require 'os'

 {CWebp} = require '../src'
 data = require './utils/data'
@@ -19,25 +20,17 @@
         buffer.toString('utf8', 0, 4).should.be.equal 'RIFF'
         buffer.toString('utf8', 8, 12).should.be.equal 'WEBP'

-    it 'should report verbose errors', ->
+    it 'should report errors', ->
       webp = new CWebp data.corrupt
-      webp.verbose().toBuffer().then ->
-        throw new Error 'Should not be fulfilled'
-      , (err) ->
-        err.should.be.Error
-        err.message.should.match /Premature end of JPEG file/
-        err.message.should.match /JPEG datastream contains no image/
-
-    it 'should allow default verbose rewriting', ->
-      class Webp3 extends CWebp
-        @verbose: true
-      webp = new Webp3 data.corrupt
       webp.toBuffer().then ->
         throw new Error 'Should not be fulfilled'
       , (err) ->
         err.should.be.Error
-        err.message.should.match /Premature end of JPEG file/
-        err.message.should.match /JPEG datastream contains no image/
+        if os.platform() is 'linux'
+          err.message.should.match /Premature end of JPEG file/
+          err.message.should.match /JPEG datastream contains no image/
+        err.message.should.match /Error! Could not process file/
+        err.message.should.match /Error! Cannot read input picture file/

     it 'should cleanup tmp files on error', ->
       filename = ''


check if req.user is destroyed on all passport logout tests

--- test/index.coffee
+++ test/index.coffee
@@ -207,6 +207,7 @@
       @logoutSpy.called.should.be.true
       @del.args[0][0].should.containEql '/api/v1/access_token'
       @send.args[0][0].should.eql access_token: 'secret'
+      (@req.user?).should.not.be.ok
       @next.called.should.be.true

     it 'still works if there is no access token', ->


[test] RedisModel##progressForJobs, ##stacktraceForJobs, ##delayTimeForJobs

--- test/index.coffee
+++ test/index.coffee
@@ -540,3 +540,63 @@
       qCleaner queue
         .then -> qCleaner queueAndJob2.queue
         .asCallback done
+
+  describe "##progressForJobs", ->
+    it "should get stacktrace for jobs", (done) ->
+      ideally = errify done
+      data    = {name: "testjob", foo: "bar"}
+
+      await fakeJob queuename, data, "active",  ideally defer {queue, job}
+      await fakeJob "test2",   data, "delayed", ideally defer queueAndJob2
+
+      jobs = [
+        {queue: job.queue.name,          id: job.jobId}
+        {queue: queueAndJob2.queue.name, id: queueAndJob2.job.jobId}
+      ]
+      await instance.progressForJobs jobs, ideally defer jobsWithProgress
+      for jobWithProgress in jobsWithProgress
+        expect(jobWithProgress.progress).to.equal 0
+
+      qCleaner queue
+        .then -> qCleaner queueAndJob2.queue
+        .asCallback done
+
+  describe "##stacktraceForJobs", ->
+    it "should get stacktrace for jobs", (done) ->
+      ideally = errify done
+      data    = {name: "testjob", foo: "bar"}
+
+      await fakeJob queuename, data, "active",  ideally defer {queue, job}
+      await fakeJob "test2",   data, "delayed", ideally defer queueAndJob2
+
+      jobs = [
+        {queue: job.queue.name,          id: job.jobId}
+        {queue: queueAndJob2.queue.name, id: queueAndJob2.job.jobId}
+      ]
+      await instance.stacktraceForJobs jobs, ideally defer jobsWithStacktrace
+      for jobWithStacktrace in jobsWithStacktrace
+        expect(jobWithStacktrace.stacktrace).to.be.an "array"
+
+      qCleaner queue
+        .then -> qCleaner queueAndJob2.queue
+        .asCallback done
+
+  describe "##delayTimeForJobs", ->
+    it "should get delay time for jobs", (done) ->
+      ideally = errify done
+      data    = {name: "testjob", foo: "bar"}
+
+      await fakeJob queuename, data, "active",  ideally defer {queue, job}
+      await fakeJob "test2",   data, "delayed", ideally defer queueAndJob2
+
+      jobs = [
+        {queue: job.queue.name,          id: job.jobId}
+        {queue: queueAndJob2.queue.name, id: queueAndJob2.job.jobId}
+      ]
+      await instance.delayTimeForJobs jobs, ideally defer jobsWithDelay
+      for jobWithDelay in jobsWithDelay
+        expect(jobWithDelay.delayUntil).to.be.an.instanceof Date
+
+      qCleaner queue
+        .then -> qCleaner queueAndJob2.queue
+        .asCallback done


Link to CNX webview for student's in CC courses

--- src/components/course-listing.cjsx
+++ src/components/course-listing.cjsx
@@ -11,22 +11,20 @@
 # Called once the store is loaded
 # checks the course and roles and will redirect if there is only a single course and role
 DisplayOrRedirect = (transition, callback) ->
-  courses = CourseListingStore.allValidCourses() or []
+  courses = CourseListingStore.allCourses() or []
   [course] = courses
   if courses.length is 1 and course.roles?.length is 1
     roleType = courses[0].roles[0].type
     conceptCoach = courses[0].is_concept_coach

     if roleType is 'student'
-      type = 'viewStudentDashboard'
-    else if roleType is 'teacher' and not conceptCoach
-      type = 'taskplans'
-    else if roleType is 'teacher' and conceptCoach
-      type = 'cc-dashboard'
+      if conceptCoach then callback() else view = 'viewStudentDashboard'
+    else if roleType is 'teacher'
+      view = if conceptCoach then 'cc-dashboard' else 'taskplans'
     else
       throw new Error("BUG: Unrecognized role type #{roleType}")

-    transition.redirect(type, {courseId: _.first(courses).id})
+    transition.redirect(view, {courseId: _.first(courses).id}) if view
   callback()

@@ -72,10 +70,15 @@
             to={to}
             params={{courseId}}>{course.name}</Router.Link>
       else if isStudent
-        courseLink = <Router.Link
-          className='tutor-course-item'
-          to='viewStudentDashboard'
-          params={{courseId}}>{course.name}</Router.Link>
+        if isConceptCoach
+          courseLink =
+            {course.name}
+
+        else
+          courseLink = <Router.Link
+            className='tutor-course-item'
+            to='viewStudentDashboard'
+            params={{courseId}}>{course.name}</Router.Link>
       else
         console.warn?("BUG: User is not a teacher or a student on course id: #{course.id}")
         return null
@@ -88,7 +91,7 @@
       </BS.Row>

   render: ->
-    courses = CourseListingStore.allValidCourses() or []
+    courses = CourseListingStore.allCourses() or []
     body = if courses.length

{@renderCourses(courses)}

     else


fix(menu): Copy Link => Copy Link Address #2105

--- src/components/evented-iframe.cjsx
+++ src/components/evented-iframe.cjsx
@@ -221,7 +221,7 @@
         menu.append(new MenuItem({ label: "Copy Email Address", click:( -> clipboard.writeText(href.split('mailto:').pop()) )}))
       else
         menu.append(new MenuItem({ label: "Open Link", click:( -> NylasEnv.windowEventHandler.openLink({href}) )}))
-        menu.append(new MenuItem({ label: "Copy Link", click:( -> clipboard.writeText(href) )}))
+        menu.append(new MenuItem({ label: "Copy Link Address", click:( -> clipboard.writeText(href) )}))
       menu.append(new MenuItem({ type: 'separator' }))

     # Menu actions for images


can be passed in

can be passed in

--- src/components/exercise/index.cjsx
+++ src/components/exercise/index.cjsx
@@ -105,7 +105,6 @@
   getTeacherReadOnlyProps: ->
     teacherReadOnlyProps = _.omit(@props, NOT_TEACHER_READ_ONLY_PROPS)
     teacherReadOnlyProps.onContinue = @props.onNextStep
-    teacherReadOnlyProps.isContinueEnabled = true
     teacherReadOnlyProps.controlButtons = false
     teacherReadOnlyProps.type = 'teacher-review'


Removed debugging line :/

Removed debugging line :/

--- src/components/task-step/ends.cjsx
+++ src/components/task-step/ends.cjsx
@@ -173,7 +173,6 @@
   displayName: 'TaskEnd'
   render: ->
     {courseId} = @props
-    console.log(CourseStore.isTeacher(courseId))

       <CardBody className='-reading-completed'>


Add invalid quote test

Add invalid quote test

--- test/quote.coffee
+++ test/quote.coffee
@@ -1,7 +1,6 @@

 fs = require 'fs'
 should = require 'should'
-produce = require 'produce'
 parse = if process.env.CSV_COV then require '../lib-cov' else require '../src'

 describe 'quote', ->
@@ -94,6 +93,19 @@
       err.message.should.eql 'Quoted field not terminated at line 1'
       next()

+  it 'when invalid quotes', (next) ->
+    parse """
+      ""  1974    8.8392926E7 ""t ""
+      ""  1974    8.8392926E7 ""  ""
+    """, quote: '"', escape: '"', delimiter: "\t", (err) ->
+      err.message.should.eql 'Invalid closing quote at line 1; found " " instead of delimiter "\\t"'
+      next()
+
+  it 'when invalid quotes from string', (next) ->
+    parse '"",1974,8.8392926E7,""t,""', quote: '"', escape: '"', (err) ->
+      err.message.should.match /Invalid closing quote/
+      next()
+


Separate tests for begin/commit and begin/rollback transactions.

--- test/integration/transactions-test.coffee
+++ test/integration/transactions-test.coffee
@@ -17,52 +17,110 @@
 else
   config.options.debug = {}

-exports.beginCommitTransaction = (test) ->
-  test.expect(4)
+class Tester
+  constructor: (@test) ->
+    @connection = new Connection(config)

-  connection = new Connection(config)
+    @connection.on('end', (info) =>
+      @test.done()
+    )

-  beginTransaction = (callback) ->
-    connection.beginTransaction((err, transactionDescriptor) ->
-      test.ok(!err)
-      test.ok(transactionDescriptor)
+    @connection.on('errorMessage', (error) =>
+      console.log("#{error.number} : #{error.message}")
+    )
+
+    @connection.on('debug', (message) =>
+      if (debug)
+        console.log(message)
+    )
+
+  createTable: (callback) =>
+    request = new Request('create table #temp (id int)', (err) =>
+      @test.ok(!err)
+      callback(err)
+    )
+
+    @connection.execSqlBatch(request)
+
+  insert: (callback) =>
+    request = new Request('insert into #temp (id) values(1)', (err) =>
+      @test.ok(!err)
+      callback(err)
+    )
+
+    @connection.execSqlBatch(request)
+
+  select: (callback, expectedRows) =>
+    request = new Request('select id from #temp', (err, rowCount) =>
+      @test.ok(!err)
+      @test.strictEqual(rowCount, expectedRows)
+      callback(err)
+    )
+
+    request.on('row', (columns) =>
+        @test.strictEqual(columns[0].value, 1)
+    )
+
+    @connection.execSqlBatch(request)
+
+  selectExpectZeroRows: (callback) =>
+    @select(callback, 0)
+
+  selectExpectOneRow: (callback) =>
+    @select(callback, 1)
+
+  beginTransaction: (callback) =>
+    @connection.beginTransaction((err, transactionDescriptor) =>
+      @test.ok(!err)
+      @test.ok(transactionDescriptor)
+
       callback(err)
     , 'abc')

-  select = (callback) ->
-    request = new Request('select 3', (err) ->
-      test.ok(!err)
+  commitTransaction: (callback) =>
+    @connection.commitTransaction((err) =>
+      @test.ok(!err)
+
       callback(err)
     )

-    connection.execSql(request)
+  rollbackTransaction: (callback) =>
+    @connection.rollbackTransaction((err) =>
+      @test.ok(!err)

-  commitTransaction = (callback) ->
-    connection.commitTransaction((err) ->
-      test.ok(!err)
-      connection.close()
       callback(err)
     )

-  connection.on('connect', (err) ->
-    async.series([
-        beginTransaction
-        select
-        commitTransaction
-        () ->
-          connection.close()
-    ]);
-  )
+  close: (callback) =>
+    @connection.close()

-  connection.on('end', (info) ->
-    test.done()
-  )
+  run: (actions) =>
+    @connection.on('connect', (err) =>
+      async.series(actions)
+    )

-  connection.on('errorMessage', (error) ->
-    console.log("#{error.number} : #{error.message}")
-  )
+exports.beginCommit = (test) ->
+  test.expect(8)

-  connection.on('debug', (message) ->
-    if (debug)
-      console.log(message)
-  )
+  tester = new Tester(test)
+  tester.run([
+    tester.createTable
+    tester.beginTransaction
+    tester.insert
+    tester.commitTransaction
+    tester.selectExpectOneRow
+    tester.close
+  ])
+
+exports.beginRollback = (test) ->
+  test.expect(7)
+
+  tester = new Tester(test)
+  tester.run([
+    tester.createTable
+    tester.beginTransaction
+    tester.insert
+    tester.rollbackTransaction
+    tester.selectExpectZeroRows
+    tester.close
+  ])


Delete view.coffee

Delete view.coffee

更新為js檔案

--- src/devtools/panel/app/view.coffee
+++ src/devtools/panel/app/view.coffee
@@ -1,43 +0,0 @@
-# 基础数据模型
-((exports)->
-  exports.tohken = {} if !exports.tohken
-  exports.tohken.view = {
-    player: {
-      "set": false
-      # 玩家名
-      "name":  null
-      # 等级
-      "level": null
-    }
-    resource: {
-      "set": false
-      # 依頼札
-      "bill":         null
-      # 手伝い札
-      "bonemeal":     null
-      # 木炭
-      "charcoal":     null
-      # 玉鋼
-      "steel":        null
-      # 冷却材
-      "coolant":      null
-      # 砥石
-      "file":         null
-      # 最大资源储量
-      "max_resource": null
-      # 小判
-      "money": null
-    }
-    party: {
-      "set": false
-      "data": {}
-    }
-    # 刀装整理
-    equips: {
-      "set": false
-      # 准备加合计
-      "data": {}
-    }
-  }
-)(window)
-


Insert API users to database in test suite

--- test/suite.coffee
+++ test/suite.coffee
@@ -5,6 +5,7 @@
 redis     = require './../coffee/db/redis'

 data =
+  api: users: require './data/api.users.json'
   steder: require './data/steder.json'
   turer: require './data/turer.json'

@@ -13,6 +14,8 @@
 # > 0. new ObjectID(ObjectID) => new ObjectId()

 if not (data['steder'][0]._id instanceof ObjectID)
+  for val, key in data.api.users
+    data.api.users[key]._id = new ObjectID(val._id['$oid'])
   data.steder[key]._id = new ObjectID(val._id['$oid']) for val, key in data.steder
   data.turer[key]._id = new ObjectID(val._id['$oid']) for val, key in data.turer

@@ -21,7 +24,12 @@

 # Wait for the MongoDB connection to become ready before spinning of any tests.

-before (done) -> mongo.once 'ready', done
+before (done) ->
+  mongo.once 'ready', ->
+    mongo.db.collection('api.users').drop()
+    mongo.db.collection('api.users').insert data.api.users, (err) ->
+      throw err if err
+      done()

 # Flush cache- and persistand data from Redis and MongoDB.


Tidied the translate regular expression with non-matching groups so msg.match only returns the terms we're interested in.

--- src/hubot/scripts/translate.coffee
+++ src/hubot/scripts/translate.coffee
@@ -65,10 +65,10 @@
       return code if lang.toLowerCase() is language.toLowerCase()

 module.exports = (robot) ->
-  robot.respond /(translate)( me)?(( from) ([a-z]*))?(( (in)?to) ([a-z]*))? (.*)/i, (msg) ->
-    term   = "\"#{msg.match[10]}\""
-    origin = if msg.match[5] isnt undefined then getCode(msg.match[5], languages) else 'auto'
-    target = if msg.match[9] isnt undefined then getCode(msg.match[9], languages) else 'en'
+  robot.respond /(?:translate)(?: me)?(?:(?: from) ([a-z]*))?(?:(?: (?:in)?to) ([a-z]*))? (.*)/i, (msg) ->
+    term   = "\"#{msg.match[3]}\""
+    origin = if msg.match[1] isnt undefined then getCode(msg.match[1], languages) else 'auto'
+    target = if msg.match[2] isnt undefined then getCode(msg.match[2], languages) else 'en'

     msg.http("http://translate.google.com/translate_a/t")
       .query({
@@ -90,7 +90,7 @@
           language =languages[parsed[2]]
           parsed = parsed[0] && parsed[0][0] && parsed[0][0][0]
           if parsed
-            if msg.match[9] is undefined
+            if msg.match[2] is undefined
               msg.send "#{term} is #{language} for #{parsed}"
             else
               msg.send "The #{language} #{term} translates as #{parsed} in #{languages[target]}"


ok, we're ready to go....

ok, we're ready to go....

--- test/gen/gen_spec.iced
+++ test/gen/gen_spec.iced
@@ -7,15 +7,23 @@
 pkg = require '../../package.json'
 input = require './input.json'

+##=====================================================================

 class Runner
-  constructor : ({@scrypt, @bu}) ->
+
+  #-------------------
+
+  constructor : ({@input, @scrypt, @bu}) ->
+
+  #-------------------

   make_vectors : (cb) ->
     out = []
-    for v,i in input[0...1]
+    for v,i in @input
       await @make_vector v, defer out[i]
     cb out
+
+  #-------------------

   run : (cb) ->
     out = {
@@ -25,6 +33,8 @@
     }
     await @make_vectors defer out.vectors
     cb out
+
+  #-------------------

   run_scrypt : (input, cb) ->
     args = [
@@ -48,11 +58,35 @@
     ret = if (m = out[0].match x)? then m[1] else null
     cb ret

+  #-------------------
+
   run_bu : (seed, cb) ->
+    args = [ seed ]
+    opts = {
+      quiet : true
+      interp : @bu
+    }
+    child = new Child args, opts
+    out = []
+    child.filter (l, which) -> out.push l
+    await child.run().wait defer status
+
+    bu_out = {}
+    primary_key = null
+    for line in out.join("\n").split(/\n+/) when line.length
+      [key,val] = line.split(/:\s+/)
+      if key[0] is ' '
+        bu_out[last_key][key.replace(/\s+/, '')] = val
+      else
+        last_key = key
+        bu_out[key] = { _ : val}
+
     cb {
-      "private"  : 1,
-      "public" : 2
+      "private"  : bu_out.WIF.uncompressed
+      "public" : bu_out['Bitcoin address'].uncompressed
     }
+
+  #-------------------

   make_vector : (input, cb) ->
     await @run_scrypt input, defer seed
@@ -63,7 +97,9 @@
     out.keys = keys
     cb out

-r = new Runner { scrypt, bu }
+##=====================================================================
+
+r = new Runner { input, scrypt, bu }
 await r.run defer out
 console.log JSON.stringify out, null, 4


add tests for @b-attr

add tests for @b-attr

--- test/index-test.coffee
+++ test/index-test.coffee
@@ -192,6 +192,42 @@
           children: [
             '|line3'
           ]
+        ]
+        template = bHtml source
+        assert.deepEqual template(context), expected
+
+  context '@b-attr', ->
+    context 'simple', ->
+      it 'works', ->
+        source = '''
+          </img
+            @b-attr src: src
+        '''
+        context =
+          src: '/images/1.png'
+        expected = [
+          tag: 'img'
+          attrs:
+            src: '/images/1.png'
+        ]
+        template = bHtml source
+        assert.deepEqual template(context), expected
+
+    context 'complex', ->
+      it 'works', ->
+        source = '''
+          </img
+            @b-attr alt: image.alt, src: image.src
+        '''
+        context =
+          image:
+            alt: 'sample'
+            src: '/images/2.png'
+        expected = [
+          tag: 'img'
+          attrs:
+            alt: 'sample'
+            src: '/images/2.png'
         ]
         template = bHtml source
         assert.deepEqual template(context), expected


Debug output in downloadContests

Debug output in downloadContests

--- server/cron/downloadContests.coffee
+++ server/cron/downloadContests.coffee
@@ -43,6 +43,8 @@
         text = await download(href, @jar)
         re = new RegExp 'Задача ([^.]+)\\. ([^<]+)'
         secondProbRes = re.exec text
+        if not secondProbRes
+            logger.warn("Second problem not found in contest ", href)
         secondProbHref = secondProbRes[1].replace('&','&')
         secondProb = @makeProblem(secondProbRes[0], secondProbRes[1], secondProbRes[2], secondProbRes[3], secondProbRes[4])


Fix logout

Fix logout

Fixes https://github.com/cozy-labs/konnectors/issues/97

--- server/konnectors/freemobile.coffee
+++ server/konnectors/freemobile.coffee
@@ -101,7 +101,7 @@
     options =
         method: 'GET'
         url:  logOutUrl
-        jar: false
+        jar: true
     request options, (err, res, body) ->
         if err?
             log.error "Couldn't logout of Free Mobile website"


Update indent for tips

Update indent for tips


[Jax.Mesh.Icosahedron] texes

[Jax.Mesh.Icosahedron] texes


ComputeProvider: ignore credential check for only "koding" provider

--- workers/social/lib/social/models/computeproviders/computeprovider.coffee
+++ workers/social/lib/social/models/computeproviders/computeprovider.coffee
@@ -70,16 +70,23 @@

       {provider, credential} = options

-      if not provider or not provider = PROVIDERS[provider]
+      if not provider or not provider_ = PROVIDERS[provider]
         return callback new KodingError "No such provider.", "ProviderNotFound"
       else
-        arguments[1].provider = provider
+        provider_.slug        = provider
+        arguments[1].provider = provider_
+
+      args = [ arguments... ]
+
+      # This is Koding only which doesn't need a valid credential
+      # since the user session is enough for koding provider for now.
+      if provider is 'koding'
+        fn.apply @, args
+        return

       if not credential?
         return callback new KodingError \
           "Credential is required.", "MissingCredential"
-
-      args = [ arguments... ]

       checkCredential client, credential, (err, cred)=>


Fix a few specs

Fix a few specs

--- spec/javascripts/slider_spec.coffee
+++ spec/javascripts/slider_spec.coffee
@@ -55,9 +55,9 @@
     (expect ($ '#slider ul.slider_tray').css 'display').toEqual 'block'
     (expect ($ '#slider ul.slider_tray').css 'position').toEqual 'relative'
     (expect ($ '#slider ul.slider_tray').css 'overflow').toEqual 'hidden'
-    (expect ($ '#slider ul.slider_tray').css 'list-style').toEqual 'none outside none'
-    (expect ($ '#slider ul.slider_tray').css 'margin').toEqual '0px'
-    (expect ($ '#slider ul.slider_tray').css 'padding').toEqual '0px'
+    (expect ($ '#slider ul.slider_tray').css 'list-style').toEqual ''
+    (expect ($ '#slider ul.slider_tray').css 'margin').toEqual ''
+    (expect ($ '#slider ul.slider_tray').css 'padding').toEqual ''

     # li
     (expect ($ '#slider ul.slider_tray > li').css 'position').toEqual 'relative'
@@ -102,16 +102,16 @@

       (expect @slider.handle_arrow_event).toHaveBeenCalledWith 'right'

-    it 'should move everything to the left', ->
-      ($ '#slider .left_arrow').removeClass 'disabled'
-      ($ '#slider .left_arrow').click()
-
-      (expect ($ '#slider .slider_tray').css 'left').toEqual '426px'
-
     it 'should move everything to the right', ->
       ($ '#slider > .right_arrow').click()

       (expect ($ '#slider .slider_tray').css 'left').toEqual '-426px'
+
+    it 'should move everything to the left', ->
+      ($ '#slider .left_arrow').click()
+
+      (expect ($ '#slider .slider_tray').css 'left').toEqual '426px'
+

     it 'should not do anything if the left button is disabled', ->
       spyOn @slider, 'handle_arrow_event'


Formatting.

Formatting.

--- lib/client/special_event_handler.coffee
+++ lib/client/special_event_handler.coffee
@@ -11,6 +11,31 @@
     click : (remoteEvent, clientEvent) ->
         clientEvent.preventDefault()
         @socket.emit('processEvent', remoteEvent)
+    # Valid targets:
+    #   input, select, textarea
+    #
+    change : (remoteEvent, clientEvent) ->
+        target = clientEvent.target
+        # TODO: use batch mechanism once it exists...this is inefficient.
+        if target.tagName.toLowerCase() == 'select'
+            if target.multiple == true
+                for option in target.options
+                    @socket.emit 'setAttribute',
+                        target : option.__nodeID
+                        attribute : 'selected'
+                        value : option.selected
+            else
+                @socket.emit 'setAttribute',
+                    target : clientEvent.target.__nodeID
+                    attribute : 'selectedIndex'
+                    value : clientEvent.target.selectedIndex
+        else # input or textarea
+            @socket.emit 'setAttribute',
+                target : clientEvent.target.__nodeID
+                attribute : 'value'
+                value : clientEvent.target.value
+        @socket.emit('processEvent', remoteEvent)
+

     _keyupListener : (event) =>
         @_pendingKeyup = false
@@ -54,28 +79,4 @@
             @monitor.document.addEventListener('keyup', @keyupListener.bind(this), true)
         @_queuedKeyEvents.push(remoteEvent)

-    # Valid targets:
-    #   input, select, textarea
-    change : (remoteEvent, clientEvent) ->
-        target = clientEvent.target
-        # TODO: use batch mechanism once it exists...this is inefficient.
-        if target.tagName.toLowerCase() == 'select'
-            if target.multiple == true
-                for option in target.options
-                    @socket.emit 'setAttribute',
-                        target : option.__nodeID
-                        attribute : 'selected'
-                        value : option.selected
-            else
-                @socket.emit 'setAttribute',
-                    target : clientEvent.target.__nodeID
-                    attribute : 'selectedIndex'
-                    value : clientEvent.target.selectedIndex
-        else # input or textarea
-            @socket.emit 'setAttribute',
-                target : clientEvent.target.__nodeID
-                attribute : 'value'
-                value : clientEvent.target.value
-        @socket.emit('processEvent', remoteEvent)
-
 module.exports = SpecialEventHandler


update selection change listeners

update selection change listeners

--- src/selection.coffee
+++ src/selection.coffee
@@ -1,7 +1,4 @@
 class TandemSelection
-  @POLL_INTERVAL: 500
-
-
   constructor: (@editor) ->
     @destructors = []
     @range = null
@@ -14,19 +11,16 @@
     @destructors = null

   initListeners: ->
-    debouncedUpdate = _.debounce( =>
+    checkUpdate = =>
       return if !@destructors?
       this.update()
-    , 100)
     keyUpdate = (event) =>
-      debouncedUpdate() if Tandem.Keyboard.KEYS.LEFT <= event.which and event.which <= Tandem.Keyboard.KEYS.DOWN
+      checkUpdate() if Tandem.Keyboard.KEYS.LEFT <= event.which and event.which <= Tandem.Keyboard.KEYS.DOWN
     @editor.doc.root.addEventListener('keyup', keyUpdate)
-    @editor.doc.root.addEventListener('mouseup', debouncedUpdate)
-    @editor.doc.root.addEventListener('mousedown', debouncedUpdate)
+    @editor.doc.root.addEventListener('mouseup', checkUpdate)
     @destructors.push( =>
       @editor.doc.root.removeEventListener('keyup', keyUpdate)
-      @editor.doc.root.removeEventListener('mouseup', debouncedUpdate)
-      @editor.doc.root.removeEventListener('mousedown', debouncedUpdate)
+      @editor.doc.root.removeEventListener('mouseup', checkUpdate)
     )

   deleteRange: ->


changed default memcached host

changed default memcached host

--- src/seoserver.coffee
+++ src/seoserver.coffee
@@ -12,7 +12,7 @@
     defaultPort: 10300
     memcached:
       enabled: true
-      defaultHost: 'localhost'
+      defaultHost: 'seo-memcache-production'
       defaultPort: 11211
       maxValue: 2097152
       connectRetries: 5


These apply only in command mode and don 't actually do anything

--- lib/motions/general-motions.coffee
+++ lib/motions/general-motions.coffee
@@ -39,7 +39,6 @@
 class MoveLeft extends Motion

   execute: (count=1) ->
-    @vimState.resetInputTransactions()
     _.times count, =>
       {row, column} = @editor.getCursorScreenPosition()
       @editor.moveCursorLeft() if column > 0
@@ -56,7 +55,6 @@

 class MoveRight extends Motion
   execute: (count=1) ->
-    @vimState.resetInputTransactions()
     _.times count, =>
       {row, column} = @editor.getCursorScreenPosition()
       lastCharIndex = @editor.getBuffer().lineForRow(row).length - 1
@@ -76,7 +74,6 @@

 class MoveUp extends Motion
   execute: (count=1) ->
-    @vimState.resetInputTransactions()
     _.times count, =>
       {row, column} = @editor.getCursorScreenPosition()
       @editor.moveCursorUp() if row > 0
@@ -88,7 +85,6 @@

 class MoveDown extends Motion
   execute: (count=1) ->
-    @vimState.resetInputTransactions()
     _.times count, =>
       {row, column} = @editor.getCursorScreenPosition()
       @editor.moveCursorDown() if row < (@editor.getBuffer().getLineCount() - 1)


Fixed bug with ignoring existing models in collections.observe.

--- Collections.coffee
+++ Collections.coffee
@@ -102,7 +102,7 @@
 # items in the collection.
   observe: (collection, args) ->
     args ?= {}
-    isObserving = !args.ignoreExisting
+    isObserving = args.ignoreExisting == false
     wrapHandler = (handler) -> -> handler.apply(@, arguments) if isObserving
     observeArgs = {}
     _.each ['added', 'changed', 'removed'], (methodName) ->


Fix where we look for error information

Fix where we look for error information

--- lib/firehose/long_poll_transport.coffee
+++ lib/firehose/long_poll_transport.coffee
@@ -100,8 +100,8 @@
   # We need this custom handler to have the connection status
   # properly displayed
   _error: (jqXhr, status, error) =>
-    if status == 500
-      error = JSON.parse error
+    if jqXhr.status == 500
+      error = JSON.parse jqXhr.responseText
       if error.error == 'Subscription failed'
         @config.subscriptionFailed(error)


:lipstick: Break if to multiple lines

:lipstick: Break if to multiple lines

--- src/space-pen.coffee
+++ src/space-pen.coffee
@@ -198,7 +198,8 @@
   onDom = element.parents?('html').length > 0

   elementsWithHooks = []
-  elementsWithHooks.push(element[0]) if element[0].getAttribute('callAttachHooks')
+  if element[0].getAttribute('callAttachHooks')
+    elementsWithHooks.push(element[0])
   if onDom
     for child in element[0].querySelectorAll('[callAttachHooks]')
       elementsWithHooks.push(child)


sks-128 - after adding kudo - form is not cleared

--- app/assets/javascripts/controllers/application_controller.js.coffee
+++ app/assets/javascripts/controllers/application_controller.js.coffee
@@ -38,11 +38,17 @@

   addManyKudos: (user) ->
     $visibleContent = $('#users-list').find '.form-visible'
-    value = $visibleContent.find('.stars').raty('score') || 1
+    $ratyContainer = $visibleContent.find('.stars')
+    value = $ratyContainer.raty('score') || 1
     $kudoComment = $visibleContent.find('.kudos-comment')
     comment = $kudoComment.val()

     @addKudo user, value, comment

+    # reset to defaults
+    $kudoComment.val('')
+    $ratyContainer.raty('score', 1)

+
+


:memo: Add documentation for new method

:memo: Add documentation for new method

--- lib/mixins/decoration-management.coffee
+++ lib/mixins/decoration-management.coffee
@@ -54,6 +54,31 @@

     decorationsByMarkerId

+  # Returns the decorations that intersects the passed-in row range
+  # in a structured way.
+  #
+  # The returned object look like:
+  #
+  # ```coffee
+  # {
+  #   'line':
+  #     '1': [...]
+  #     '2': [...]
+  #   'highlight-over':
+  #     '10': [...]
+  #     '11': [...]
+  # }
+  # ```
+  #
+  # At the first level, the keys are the available decoration types.
+  # At the second level, the keys are the row index for which there
+  # are decorations available. The value is an array containing the
+  # decorations that intersects with the corresponding row.
+  #
+  # startScreenRow - The starting row index.
+  # endScreenRow - The ending row index.
+  #
+  # Returns an {Object}.
   decorationsForScreenRowRangeByTypeThenRows: (startScreenRow, endScreenRow) ->
     decorationsByMarkerType = {}
     for marker in @findMarkers(intersectsScreenRowRange: [startScreenRow, endScreenRow])


watch out for double //

watch out for double //

--- app/assets/javascripts/angular_blog/angular_app/services/social.js.coffee
+++ app/assets/javascripts/angular_blog/angular_app/services/social.js.coffee
@@ -11,7 +11,7 @@
       this.load()

   tags: (link,title) ->
-    '

+    '


make project load its own settings

make project load its own settings

--- js/app.coffee
+++ js/app.coffee
@@ -268,14 +268,13 @@
     project_name = "#{username}/#{project}"

     # if we're already on this page, dont reload
-    if (not @project() or
-    (@project().vcs_url() isnt "https://github.com/#{project_name}"))
-      $.getJSON "/api/v1/project/#{project_name}/settings", (data) =>
-        @project(new CI.inner.Project data)
-        @project().get_users()
-        VM.loadExtraEditPageData subpage
-    else
-        VM.loadExtraEditPageData subpage
+    if !@project() or (@project().project_name() isnt project_name)
+      if @project() then @project().clean()
+      @project new CI.inner.Project
+        vcs_url: "https://github.com/#{project_name}"
+
+    @project().maybe_load_settings()
+    VM.loadExtraEditPageData subpage

     display "edit", {project: project_name}, subpage


Update Atom config

Update Atom config

--- atom.cson
+++ atom.cson
@@ -1,16 +1,8 @@
 "*":
   "atom-material-ui":
     colors:
-      abaseColor:
-        red: 236
-        green: 64
-        blue: 122
-        alpha: 1
-      accentColor:
-        red: 70
-        green: 255
-        blue: 193
-        alpha: 1
+      abaseColor: "#ec407a"
+      accentColor: "#46ffc1"
       paintCursor: true
       predefinedColor: "Pink"
     fonts: {}
@@ -65,3 +57,6 @@
   "tree-view": {}
   welcome:
     showOnStartup: false
+".pug.source":
+  editor:
+    nonWordCharacters: "^*\"`'/|\\?!;:,.%#@(){}[]<>=+-~_"


Add eventEmitter's methods to Cursor

Add eventEmitter's methods to Cursor

--- drivers/javascript/cursor.coffee
+++ drivers/javascript/cursor.coffee
@@ -220,26 +220,6 @@
         else
             throw new err.RqlDriverError "First argument to `toArray` must be a function or undefined."

-class Cursor extends IterableResult
-    constructor: ->
-        @_type = protoResponseType.SUCCESS_PARTIAL
-        super
-
-    toString: ar () -> "[object Cursor]"
-
-class Feed extends IterableResult
-    constructor: ->
-        @_type = protoResponseType.SUCCESS_FEED
-        super
-
-
-    hasNext: ->
-        throw new err.RqlDriverError "`hasNext` is not available for feeds."
-    toArray: ->
-        throw new err.RqlDriverError "`toArray` is not available for feeds."
-
-    toString: ar () -> "[object Feed]"
-
     _makeEmitter: ->
         @emitter = new EventEmitter
         @each = ->
@@ -302,6 +282,27 @@
             @emitter.emit('error', err)
         else
             @emitter.emit('data', data)
+
+
+
+class Cursor extends IterableResult
+    constructor: ->
+        @_type = protoResponseType.SUCCESS_PARTIAL
+        super
+
+    toString: ar () -> "[object Cursor]"
+
+class Feed extends IterableResult
+    constructor: ->
+        @_type = protoResponseType.SUCCESS_FEED
+        super
+
+    hasNext: ->
+        throw new err.RqlDriverError "`hasNext` is not available for feeds."
+    toArray: ->
+        throw new err.RqlDriverError "`toArray` is not available for feeds."
+
+    toString: ar () -> "[object Feed]"

 # Used to wrap array results so they support the same iterable result


Editor: Emit `FileContentChanged` event unconditionally

--- client/Ace/ace.coffee
+++ client/Ace/ace.coffee
@@ -28,10 +28,8 @@
             @lastSavedContents = contents

           @editor.on 'change', =>
-            if @isCurrentContentChanged()
-              @emit 'FileContentChanged'  unless @suppressListeners
-            else
-              @emit 'FileContentSynced'
+            @emit 'FileContentChanged'  unless @suppressListeners
+            @emit 'FileContentSynced'  if @isCurrentContentChanged()

           @editor.gotoLine 0
           @focus()


use args for repl

use args for repl

--- lib/connection/terminal.coffee
+++ lib/connection/terminal.coffee
@@ -23,7 +23,7 @@
   jlpath: () -> atom.config.get("julia-client.juliaPath")
   jlargs: () -> atom.config.get("julia-client.juliaArguments")

-  repl: -> @term @escpath @jlpath()
+  repl: -> @term "#{@escpath @jlpath()} #{@jlargs()}"

   client: (port) ->
     comm.booting()


MainNav: on tab change select the nav item

--- client/landing/app/MainApp/maincontroller/mainviewcontroller.coffee
+++ client/landing/app/MainApp/maincontroller/mainviewcontroller.coffee
@@ -39,10 +39,9 @@
     cdController    = KD.getSingleton("contentDisplayController")
     appManager      = KD.getSingleton('appManager')
     app             = appManager.getFrontApp()
-    {navController} = KD.getSingleton('mainController').sidebarController.getView()
+    {mainTabView, navController} = mainView
+
     cdController.emit "ContentDisplaysShouldBeHidden"
-    {mainTabView}   = mainView
-
     # temp fix
     # until fixing the original issue w/ the dnd this should be kept here
     if pane


Don't require unused modules

Don't require unused modules

--- lib/data/commandos2/pck.coffee
+++ lib/data/commandos2/pck.coffee
@@ -1,6 +1,5 @@
 {allowUnsafeNewFunction} = require 'loophole'
 {Parser} = require 'binary-parser'
-{FourCC} = require '../../common/fourcc'

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