more work with the UI

more work with the UI

--- lib/minjs.coffee
+++ lib/minjs.coffee
@@ -1,45 +1,45 @@
 minjs = require 'uglify-js'
 fs = require 'fs'

-compile = () ->
-	editor = atom.workspace.getActiveEditor()
-	path = editor.getPath()
+module.exports =
+	compile = () ->
+		editor = atom.workspace.getActiveEditor()
+		path = editor.getPath()

-	if !path or path.match(/\.min\.(js|css)$/gi) or !path.match(/\.(js|css)$/gi)
-		@status "File not minifiable."
-		return
-
-	@status "Working..."
-
-	if path.indexOf('.js') == path.length - 3 and path.indexOf('.min.js') < 0
-		result = minjs.minify(editor.getText(), {fromString: true});
-		new_name = path.replace('.js', '.min.js')
-		fs.writeFile(new_name, result.code, (err) ->
-			if err
-				@status "Couldn't minify .js file!"
-			else
-				@status "Minification succeeded!"
-		)
-
-module.exports =
-  activate: ->
-			atom.workspaceView.command "minjs:minify", => compile()
-			atom.workspaceView.command "core:save", =>
-				if atom.config.get('minjs.minifyOnSave')
-					compile()
+		if !path or path.match(/\.min\.(js|css)$/gi) or !path.match(/\.(js|css)$/gi)
+			@status "File not minifiable."
 			return

-	statusTimeout: null
+		@status "Working..."

-	status: (text) ->
-		clearTimeout @statusTimeout
-		if atom.workspaceView.statusBar.find('.minjs-status').length
-			atom.workspaceView.statusBar.find('.minjs-status').text text
-		else
-			atom.workspaceView.statusBar.appendRight('' + text + '')
-		@statusTimeout = setTimeout ->
-				atom.workspaceView.statusBar.find('.minjs-status').remove()
-			, 3000
+		if path.indexOf('.js') == path.length - 3 and path.indexOf('.min.js') < 0
+			result = minjs.minify(editor.getText(), {fromString: true});
+			new_name = path.replace('.js', '.min.js')
+			fs.writeFile(new_name, result.code, (err) ->
+				if err
+					@status "Couldn't minify .js file!"
+				else
+					@status "Minification succeeded!"
+			)

-	configDefaults:
-		minifyOnSave: false
+	  activate: ->
+				atom.workspaceView.command "minjs:minify", => compile()
+				atom.workspaceView.command "core:save", =>
+					if atom.config.get('minjs.minifyOnSave')
+						compile()
+				return
+
+		statusTimeout: null
+
+		status: (text) ->
+			clearTimeout @statusTimeout
+			if atom.workspaceView.statusBar.find('.minjs-status').length
+				atom.workspaceView.statusBar.find('.minjs-status').text text
+			else
+				atom.workspaceView.statusBar.appendRight('' + text + '')
+			@statusTimeout = setTimeout ->
+					atom.workspaceView.statusBar.find('.minjs-status').remove()
+				, 3000
+
+		configDefaults:
+			minifyOnSave: false


Only turn on guest track-changes if available

--- services/web/public/coffee/ide/review-panel/controllers/ReviewPanelController.coffee
+++ services/web/public/coffee/ide/review-panel/controllers/ReviewPanelController.coffee
@@ -629,14 +629,15 @@
 			_setUserTCState(project.owner._id, newValue, isLocal)

 		_setGuestsTCState = (newValue, isLocal = false) ->
-			$scope.reviewPanel.trackChangesOnForGuests = newValue
-			if (
-				ide.$scope.project.publicAccesLevel == 'tokenBased' &&
-				ide.$scope.isTokenMember &&
-				ide.$scope?.user?.id?
-			)
-				$scope.trackChangesOnForThisGuestClient = newValue
-				_setUserTCState(ide.$scope.user.id, newValue, isLocal)
+			if $scope.reviewPanel.trackChangesForGuestsAvailable
+				$scope.reviewPanel.trackChangesOnForGuests = newValue
+				if (
+					ide.$scope.project.publicAccesLevel == 'tokenBased' &&
+					ide.$scope.isTokenMember &&
+					ide.$scope?.user?.id?
+				)
+					$scope.trackChangesOnForThisGuestClient = newValue
+					_setUserTCState(ide.$scope.user.id, newValue, isLocal)

 		applyClientTrackChangesStateToServer = () ->
 			data = {}


Use the same code path for fold creation and tokenized buffer changes

--- src/app/display-buffer.coffee
+++ src/app/display-buffer.coffee
@@ -103,24 +103,11 @@
   #
   # Returns the new {Fold}.
   createFold: (startRow, endRow) ->
-    return fold if fold = @foldFor(startRow, endRow)
+    return fold if fold = @foldFor(startRow, endRow, 0, refreshMarkers: true)
     fold = new Fold(this, startRow, endRow)
     @registerFold(fold)
-
     unless @isFoldContainedByActiveFold(fold)
-      bufferRange = new Range([startRow, 0], [endRow, @buffer.lineLengthForRow(endRow)])
-      oldScreenRange = @screenLineRangeForBufferRange(bufferRange)
-
-      lines = @buildLineForBufferRow(startRow)
-      @lineMap.replaceScreenRows(oldScreenRange.start.row, oldScreenRange.end.row, lines)
-      newScreenRange = @screenLineRangeForBufferRange(bufferRange)
-
-      start = oldScreenRange.start.row
-      end = oldScreenRange.end.row
-      screenDelta = newScreenRange.end.row - oldScreenRange.end.row
-      bufferDelta = 0
-      @triggerChanged({ start, end, screenDelta, bufferDelta })
-
+      @updateScreenLines(startRow, endRow, 0, refreshMarkers: true)
     fold

   # Public: Given a {Fold}, determines if it is contained within another fold.
@@ -371,26 +358,30 @@
     fold.handleBufferChange(e) for fold in allFolds

   handleTokenizedBufferChange: (tokenizedBufferChange) =>
-    if bufferChange = tokenizedBufferChange.bufferChange
-      @handleBufferChange(bufferChange)
-      bufferDelta = bufferChange.newRange.end.row - bufferChange.oldRange.end.row
-
-    tokenizedBufferStart = @bufferRowForScreenRow(@screenRowForBufferRow(tokenizedBufferChange.start))
-    tokenizedBufferEnd = tokenizedBufferChange.end
-    tokenizedBufferDelta = tokenizedBufferChange.delta
-
-    start = @screenRowForBufferRow(tokenizedBufferStart)
-    end = @lastScreenRowForBufferRow(tokenizedBufferEnd)
-    newScreenLines = @buildLinesForBufferRows(tokenizedBufferStart, tokenizedBufferEnd + tokenizedBufferDelta)
-    @lineMap.replaceScreenRows(start, end, newScreenLines)
-    screenDelta = @lastScreenRowForBufferRow(tokenizedBufferEnd + tokenizedBufferDelta) - end
-
-    changeEvent = { start, end, screenDelta, bufferDelta }
-    if bufferChange
+    {start, end, delta, bufferChange} = tokenizedBufferChange
+    @handleBufferChange(bufferChange) if bufferChange
+    @updateScreenLines(start, end, delta, delayChangeEvent: bufferChange?)
+
+  updateScreenLines: (startBufferRow, endBufferRow, bufferDelta, options={}) ->
+    startBufferRow = @bufferRowForScreenRow(@screenRowForBufferRow(startBufferRow))
+    newScreenLines = @buildLinesForBufferRows(startBufferRow, endBufferRow + bufferDelta)
+
+    startScreenRow = @screenRowForBufferRow(startBufferRow)
+    endScreenRow = @lastScreenRowForBufferRow(endBufferRow)
+
+    @lineMap.replaceScreenRows(startScreenRow, endScreenRow, newScreenLines)
+
+    changeEvent =
+      start: startScreenRow
+      end: endScreenRow
+      screenDelta: @lastScreenRowForBufferRow(endBufferRow + bufferDelta) - endScreenRow
+      bufferDelta: bufferDelta
+
+    if options.delayChangeEvent
       @pauseMarkerObservers()
       @pendingChangeEvent = changeEvent
     else
-      @triggerChanged(changeEvent, false)
+      @triggerChanged(changeEvent, options.refreshMarkers)

   handleMarkersUpdated: =>
     event = @pendingChangeEvent


FIX: Switch from using underscore's .where to lodash's .filter

--- src/app/projects/partials/directives/project-portfolio.coffee
+++ src/app/projects/partials/directives/project-portfolio.coffee
@@ -93,7 +93,7 @@
           d.include_in_portfolio and _.find($scope.project.task_outcome_alignments, { task_id: d.id })?
         selectedTasks.length is 0
       else
-        selectedTasks = _.where $scope.project.tasks, { include_in_portfolio: true }
+        selectedTasks = _.filter $scope.project.tasks, (d) -> d.include_in_portfolio
         selectedTasks.length is 0
 )


Added a clickable cool feature

Added a clickable cool feature

- Added cool feature that you can simply click in the devtools to enable/disable debug
- Moved list() to renderer

--- lib/debug.coffee
+++ lib/debug.coffee
@@ -14,10 +14,6 @@
       Object.assign new Debug, o
     else
       o
-
-# Another wrapper
-class Handler
-  constructor: (@enabled, @type) ->

 # Globals
 console.assert process, "process doesn't exist"
@@ -102,12 +98,6 @@
         toString:
           value: -> "[#{tag}: #{if @isEnabled() then 'enabled' else 'disabled'}]"
     @ex[tag]
-  list: ->
-    output = Debug.wrap {debug: new Handler(@isEnabled(), 'main')}
-    for opt of @ex
-      output[opt] = new Handler(@ex[opt].isEnabled(), 'extra')
-    console.table output
-    output

   Object.defineProperty @prototype, 'ex',
     value: new ExtraDebugOptions
@@ -124,6 +114,28 @@
     process.env.DEBUG_EXTRA = Array.from(extraOpts).join(',') if extraOpts.size > 0
     super()

+# Helper classes to make life easier with DevTools
+class DevToolsBooster
+
+class Booster
+  constructor: (dbgr, type, relistFunc) ->
+    @Enabled = dbgr.isEnabled()
+    @Type = type
+    enable = dbgr.enable.bind dbgr
+    disable = dbgr.disable.bind dbgr
+    if @Enabled
+      Object.defineProperty @, 'ClickToDisable -->',
+        get: ->
+          disable()
+          relistFunc()
+          'Disabled'
+    else
+      Object.defineProperty @, 'ClickToEnable -->',
+        get: ->
+          enable()
+          relistFunc()
+          'Enabled'
+
 # For the Renderer Processes
 class DebugRenderer extends DebugBase
   style = 'background: linear-gradient(30deg, cyan, white 3ex)'
@@ -136,6 +148,14 @@
     process.env.DEBUG_EXTRA?.split(',').forEach @enableExtra.bind @
     super()

+  list: ->
+    relist = @list.bind @
+    output = new DevToolsBooster
+    output['DEBUG'] = new Booster(@, 'main', relist)
+    for opt of @ex
+      output[opt] = new Booster(@ex[opt], 'extra', relist)
+    console.table output
+
 dbg = if isRenderer then new DebugRenderer else new DebugBrowser

 module.exports = dbg


Small fix so that the `!router:route` can be invoked with 2 params.

--- src/chaplin/lib/router.coffee
+++ src/chaplin/lib/router.coffee
@@ -74,9 +74,11 @@

     # Handler for the global !router:route event
     routeHandler: (path, options, callback) ->
-      # Assume only path and callback were passed if we only got 2 arguments;
-      # so as to mimic existing chaplin behavior
-      [callback, options] = [options, {}] if arguments.length is 2
+      # Assume only path and callback were passed if we only got 2 arguments
+      # and the second argument is a function; so as to mimic existing chaplin
+      # behavior
+      if arguments.length is 2 and _(options).isFunction()
+        [callback, options] = [options, {}]

       # Continue on to handle the route; pass in options hash
       routed = @route path, options


used force brackets

used force brackets

--- lib/minimap-indicator.coffee
+++ lib/minimap-indicator.coffee
@@ -96,7 +96,8 @@
     @calBoundaryY y

   computeFromCenterX: (cx) ->
-    @setCenterY cx - @scroller.x
+    @setCenterY(cx) - @scroller.x

   computeFromCenterY: (cy) ->
-    @setCenterY cy - @scroller.y
+    @setCenterY(cy) - @scroller.y
+


only when a commit msg is added

only when a commit msg is added

--- lib/models/git-commit.coffee
+++ lib/models/git-commit.coffee
@@ -93,6 +93,8 @@
         cwd: @dir()
       stdout: (data) =>
         new StatusView(type: 'success', message: data)
+        if @andPush
+          new GitPush()
         # Set @isAmending to false since it succeeded.
         @isAmending = false
         # Destroying the active EditorView will trigger our cleanup method.
@@ -108,9 +110,6 @@
       stderr: (err) =>
         # Destroying the active EditorView will trigger our cleanup method.
         @destroyActiveEditorView()
-      exit: =>
-        if @andPush
-          new GitPush()

   # Public: Destroys the active EditorView to trigger our cleanup method.
   destroyActiveEditorView: ->


QUALITY: Remove unit tutorials when stream deleted

--- src/app/common/services/unit-service.coffee
+++ src/app/common/services/unit-service.coffee
@@ -173,7 +173,7 @@
     # Delete a unit's stream
     unit.deleteStream = (stream) ->
       successCallback = () ->
-        # Add the new stream to the unit
+        _.remove unit.tutorials, (tutorial) -> tutorial.tutorial_stream == stream
         _.pull unit.tutorial_streams, stream
       failureCallback = (response) ->
         # Deal with the failure


Add ability to just do a path scan from the cli

--- lib/dscan.coffee
+++ lib/dscan.coffee
@@ -45,23 +45,55 @@
   scanner.on 'finished-scanning', onFinishedScanning
   scanner.scan()

-singleProcessMain = (options) ->
+singleProcessScanFirstSearch = (regex, scanner, searcher, doneCallback) ->
+  runSearch = ->
+    scanner.removeListener 'finished-scanning', runSearch
+    searcher.searchPaths regex, scanner.paths, ->
+      doneCallback()
+
+  scanner.on 'finished-scanning', runSearch
+  scanner.scan()
+
+singleProcessSearchMain = (options) ->
   searcher = new PathSearcher()
-  scanner = new PathScanner(options.pathToSearch, options)
+  scanner = new PathScanner(options.pathToScan, options)
   console.time 'Single Process Search'

   count = 0
+  resultCount = 0
+  pathCount = 0

-  if options.verbose
-    searcher.on 'results-found', (results) ->
-      console.log results.path
-      count++
-      #for result in results.results
-      #  console.log '  ', result.lineNumber + ":", result.matchText, 'at', result.range
+  scanner.on 'path-found', (path) ->
+    pathCount++

-  singleProcessSearch buildRegex(options.regex), scanner, searcher, ->
+  searcher.on 'results-found', (results) ->
+    count++
+    console.log results.path if options.verbose
+
+    for result in results.results
+      resultCount++
+      if options.verbose
+        console.log '  ', result.lineNumber + ":", result.matchText, 'at', result.range
+
+  singleProcessSearch buildRegex(options.search), scanner, searcher, ->
+  # singleProcessScanFirstSearch buildRegex(options.regex), scanner, searcher, ->
     console.timeEnd 'Single Process Search'
-    console.log 'Searched', scanner.paths.length, '; found in', count
+    console.log "#{resultCount} matches in #{count} files. Searched #{pathCount} files"
+
+singleProcessScanMain = (options) ->
+  scanner = new PathScanner(options.pathToScan, options)
+  console.time 'Single Process Scan'
+
+  count = 0
+  scanner.on 'path-found', (path) ->
+    count++
+    console.log path if options.verbose
+
+  scanner.on 'finished-scanning', ->
+    console.timeEnd 'Single Process Scan'
+    console.log "Found #{count} paths"
+
+  scanner.scan()

 buildRegex = (pattern) ->
   new RegExp(pattern, 'gi')
@@ -75,11 +107,14 @@
   argParser.addArgument([ '-m', '--multiprocess' ], action: 'storeTrue')
   argParser.addArgument([ '-e', '--excludeVcsIgnores' ], action: 'storeTrue')
   argParser.addArgument([ '-o', '--verbose' ], action: 'storeTrue')
-  argParser.addArgument(['regex'])
-  argParser.addArgument(['pathToSearch'])
+  argParser.addArgument([ '-s', '--search' ])
+  argParser.addArgument(['pathToScan'])

   options = argParser.parseArgs()

-  singleProcessMain(options)
+  if options.search
+    singleProcessSearchMain(options)
+  else
+    singleProcessScanMain(options)

 module.exports = main


config: add contly as webserver process

config: add contly as webserver process

--- config/workers.coffee
+++ config/workers.coffee
@@ -75,6 +75,17 @@
         ]
       healthCheckURLs   : [ "http://localhost:#{KONFIG.kontrol.port}/healthCheck" ]
       versionURL        : "http://localhost:#{KONFIG.kontrol.port}/version"
+
+    countly             :
+      group             : "webserver"
+      nginx             :
+        websocket       : yes
+        locations       : [
+          {
+            location    : '/countly/'
+            proxyPass   : "#{credentials.countly.host}"
+          }
+        ]

     kloud               :
       group             : 'environment'


config: add kloud secret key as flag

config: add kloud secret key as flag

--- config/workers.coffee
+++ config/workers.coffee
@@ -44,7 +44,7 @@
       ports             :
         incoming        : "#{KONFIG.kloud.port}"
       supervisord       :
-        command         : "#{GOBIN}/kloud -networkusageendpoint http://localhost:#{KONFIG.vmwatcher.port} -planendpoint #{KONFIG.socialapi.proxyUrl}/payments/subscriptions -hostedzone #{options.userSitesDomain} -region #{options.region} -environment #{options.environment} -port #{KONFIG.kloud.port}  -userprivatekey #{KONFIG.kloud.userPrivateKeyFile} -userpublickey #{KONFIG.kloud.userPublicKeyfile}  -publickey #{KONFIG.kontrol.publicKeyFile} -privatekey #{KONFIG.kontrol.privateKeyFile} -kontrolurl #{KONFIG.kontrol.url}  -registerurl #{KONFIG.kloud.registerUrl} -mongourl #{KONFIG.mongo} -prodmode=#{options.configName is "prod"} -awsaccesskeyid=#{credentials.awsKeys.vm_kloud.accessKeyId} -awssecretaccesskey=#{credentials.awsKeys.vm_kloud.secretAccessKey} -slusername=#{credentials.slKeys.vm_kloud.username} -slapikey=#{credentials.slKeys.vm_kloud.apiKey} -janitorsecretkey=#{KONFIG.socialapi.janitor.secretKey} -vmwatchersecretkey=#{KONFIG.vmwatcher.secretKey} -paymentwebhooksecretkey=#{KONFIG.paymentwebhook.secretKey} -tunnelurl #{KONFIG.kloud.tunnelUrl}"
+        command         : "#{GOBIN}/kloud -networkusageendpoint http://localhost:#{KONFIG.vmwatcher.port} -planendpoint #{KONFIG.socialapi.proxyUrl}/payments/subscriptions -hostedzone #{options.userSitesDomain} -region #{options.region} -environment #{options.environment} -port #{KONFIG.kloud.port}  -userprivatekey #{KONFIG.kloud.userPrivateKeyFile} -userpublickey #{KONFIG.kloud.userPublicKeyfile}  -publickey #{KONFIG.kontrol.publicKeyFile} -privatekey #{KONFIG.kontrol.privateKeyFile} -kontrolurl #{KONFIG.kontrol.url}  -registerurl #{KONFIG.kloud.registerUrl} -mongourl #{KONFIG.mongo} -prodmode=#{options.configName is "prod"} -awsaccesskeyid=#{credentials.awsKeys.vm_kloud.accessKeyId} -awssecretaccesskey=#{credentials.awsKeys.vm_kloud.secretAccessKey} -slusername=#{credentials.slKeys.vm_kloud.username} -slapikey=#{credentials.slKeys.vm_kloud.apiKey} -janitorsecretkey=#{KONFIG.socialapi.janitor.secretKey} -vmwatchersecretkey=#{KONFIG.vmwatcher.secretKey} -paymentwebhooksecretkey=#{KONFIG.paymentwebhook.secretKey} -kloudsecretkey=#{credentials.kloud.secretKey} -tunnelurl #{KONFIG.kloud.tunnelUrl}"
       nginx             :
         websocket       : yes
         locations       : [


Remove comment

Remove comment

--- lib/project-find-view.coffee
+++ lib/project-find-view.coffee
@@ -91,7 +91,6 @@
   handleEventsForReplace: ->
     @replacementsMade = 0
     @model.on 'replace', (promise) =>
-      # if @model.getPathCount()
       @replacementsMade = 0
       @replacmentInfoBlock.show()
       @replacementProgress.removeAttr('value')


Fixup some coffeescript-linter problems.

--- lib/pub/pub_component.coffee
+++ lib/pub/pub_component.coffee
@@ -63,7 +63,7 @@
           @emitter.emit 'pub-start',
             title: 'Pub Get'
           @run pubspecRoot, 'get'
-        () => 1
+        => 1
       )
   upgrade: =>
     @whenPubspecPresent =>
@@ -72,7 +72,7 @@
           @emitter.emit 'pub-start',
             title: 'Pub Upgrade'
           @run pubspecRoot, 'upgrade'
-        () => 1
+        => 1
       )

   observePubspec: (pubspecRoot) =>
@@ -93,10 +93,10 @@
   # Select a pubspecRoot to operate on
   # Returns Promise.
   getPubspecRoot: =>
-    if Utils.getDartProjectPaths().length == 0
+    if Utils.getDartProjectPaths().length is 0
       return Promise.reject('No valid Dart project paths')

-    if Utils.getDartProjectPaths().length == 1
+    if Utils.getDartProjectPaths().length is 1
       return Promise.resolve(Utils.getDartProjectPaths()[0])

     picker = new ProjectPicker()


Update stats.coffee

Update stats.coffee

--- resources/assets/coffee/react/beatmapset-page/stats.coffee
+++ resources/assets/coffee/react/beatmapset-page/stats.coffee
@@ -79,12 +79,7 @@
       div className: 'beatmapset-stats__row beatmapset-stats__row--advanced',
         table className: 'beatmap-stats-table',
           tbody null,
-            stats =
-              if @props.beatmap.mode == 'taiko'
-                ['drain', 'accuracy', 'stars']
-              else
-                ['cs', 'drain', 'accuracy', 'ar', 'stars']
-            for stat in stats
+            for stat in (if @props.beatmap.mode == 'taiko' then ['drain', 'accuracy', 'stars'] else ['cs', 'drain', 'accuracy', 'ar', 'stars'])
               value =
                 if stat == 'stars'
                   @props.beatmap.difficulty_rating


make PackManager parameters configurable

--- app/coffee/PackManager.coffee
+++ app/coffee/PackManager.coffee
@@ -252,15 +252,16 @@
 		newResults.slice(0, limit) if limit?
 		return newResults

+	MAX_SIZE:  1024*1024 # make these configurable parameters
+	MAX_COUNT: 1024
+	MIN_COUNT: 100
+	KEEP_OPS:  100
+
 	convertDocsToPacks: (docs, callback) ->
-		MAX_SIZE = 1024*1024 # make these configurable parameters
-		MAX_COUNT = 1024
-		MIN_COUNT = 100
-		KEEP_OPS = 100
 		packs = []
 		top = null
 		# keep the last KEEP_OPS as individual ops
-		docs = docs.slice(0,-KEEP_OPS)
+		docs = docs.slice(0,-PackManager.KEEP_OPS)

 		docs.forEach (d,i) ->
 			# skip existing packs
@@ -272,13 +273,13 @@
 				top = null
 				return
 			sz = BSON.calculateObjectSize(d)
-			if top?	&& top.pack.length < MAX_COUNT && top.sz + sz < MAX_SIZE
+			if top?	&& top.pack.length < PackManager.MAX_COUNT && top.sz + sz < PackManager.MAX_SIZE
 				top.pack = top.pack.concat {v: d.v, meta: d.meta,  op: d.op, _id: d._id}
 				top.sz += sz
 				top.v_end = d.v
 				top.meta.end_ts = d.meta.end_ts
 				return
-			else if sz < MAX_SIZE
+			else if sz < PackManager.MAX_SIZE
 				# create a new pack
 				top = _.clone(d)
 				top.pack = [ {v: d.v, meta: d.meta,  op: d.op, _id: d._id} ]
@@ -293,7 +294,7 @@

 		# only store packs with a sufficient number of ops, discard others
 		packs = packs.filter (packObj) ->
-			packObj.pack.length > MIN_COUNT
+			packObj.pack.length > PackManager.MIN_COUNT
 		callback(null, packs)

 	checkHistory: (docs, callback) ->


ceil not round

ceil not round

--- app/coffee/PackManager.coffee
+++ app/coffee/PackManager.coffee
@@ -534,5 +534,5 @@

 	_getOneDayInFutureWithRandomDelay: ->
 		thirtyMins = 1000 * 60 * 30
-		randomThirtyMinMax = Math.round(Math.random() * thirtyMins)
+		randomThirtyMinMax = Math.ceil(Math.random() * thirtyMins)
 		return new Date(Date.now() + randomThirtyMinMax + 1*DAYS)


don't require/load all compilers

don't require/load all compilers

(when searching for the right file extension)

--- lib/index.coffee
+++ lib/index.coffee
@@ -58,12 +58,11 @@
  * Given a file extension, finds the adapter's name in accord, or
  * returns undefined.
  * @param  {String} ext - file extension, no dot
- * @return {?} string adapter name or undefined
+ * @return {String|undefined} string adapter name or undefined
 ###
 lookupAdapter = (ext) ->
   for name, Adapter of accord.all()
-    a = new Adapter
-    if _.contains(a.extensions, ext) then return a.name
+    if _.contains(Adapter::extensions, ext) then return name
   return

 ###*


Update interface

Update interface

--- lib/index.coffee
+++ lib/index.coffee
@@ -1,24 +1,25 @@
 'use strict'

-path         = require 'path'
-existsFile   = require 'exists-file'
-defaults     = require 'lodash.defaults'
-spawn        = require('child_process').spawn
+spawn      = require('child_process').spawn
+defaults   = require 'lodash.defaults'
+existsFile = require 'exists-file'
+path       = require 'path'

-defaultOptions =
+conventionalChangelog = 'node_modules/.bin/conventional-changelog'
+
+DEFAULT =
   filename: 'CHANGELOG.md'

 parseOptions = (opts) ->
   Object.keys(opts).map (opt) ->
     value = opts[opt]
     if value?
-      console.log
       flagValue = if typeof value is 'boolean' then '' else "=#{opts[opt]}"
       "--#{opt}#{flagValue}"

 module.exports = (bumped, plugin, cb) ->
-  changelog = path.resolve plugin.path, 'node_modules/.bin/conventional-changelog'
-  opts = defaults {}, plugin.options, defaultOptions
+  changelog = path.resolve plugin.path, conventionalChangelog
+  opts = defaults {}, plugin.opts, DEFAULT
   isFirstTime = !existsFile.sync opts.filename

   opts.infile = opts.filename


リファクタリング

リファクタリング

--- lib/index.coffee
+++ lib/index.coffee
@@ -47,7 +47,6 @@

     gulp.task "deploy-to-aws-lambda", (callback)->
       config = require(path.join(process.cwd(), "lambda-config.js"))
-      # console.log(JSON.stringify({config: config}, null, 2))
       lambda = new LambdaWrapper(region: config.Region)

       console.log "Loading zip file..."
@@ -64,7 +63,6 @@
             Timeout:      config.Timeout,
             Code:         {ZipFile: zipBody},
           }
-          # console.log(JSON.stringify({createFunctionParam: createFunctionParam}, null, 2))
           updateFunctionConfigurationParam = {
             FunctionName: config.FunctionName,
             Description:  config.Description,
@@ -73,20 +71,17 @@
             MemorySize:   config.MemorySize,
             Timeout:      config.Timeout,
           }
-          # console.log(JSON.stringify({updateFunctionConfigurationParam: updateFunctionConfigurationParam}, null, 2))
           updateFunctionCodeParam = {
             FunctionName: config.FunctionName,
             ZipFile:      zipBody,
           }
-          # console.log(JSON.stringify({updateFunctionCodeParam: updateFunctionCodeParam}, null, 2))
-
           console.log "Creating function..."
           return lambda.createFunction(createFunctionParam)
             .then (result)->
               console.log "Created function."
               return Promise.resolve(result)
             .catch (result)->
-              if result?.error?.statusCode == 409 #
+              if result?.error?.statusCode == 409
                 console.log "Function already exist"
                 console.log "Updating function configuration..."
                 return lambda.updateFunctionConfiguration(updateFunctionConfigurationParam)
@@ -99,11 +94,9 @@
               else
                 return Promise.reject(result)
         .then (result)->
-          # console.log(JSON.stringify({then: result}, null, 2))
           console.log("Successful deploy function.")
           # callback()
         .catch (result)->
-          # console.log(JSON.stringify({catch: result}, null, 2))
           console.log("Failed deploy function.")
           console.log(result)
           console.log(result.stack) if result?.stack?


deploy-to-aws-lambdaタスクを追加

deploy-to-aws-lambdaタスクを追加

--- lib/index.coffee
+++ lib/index.coffee
@@ -1,3 +1,5 @@
+
+path = require("path")

 coffee      = require "gulp-coffee"
 gutil       = require "gulp-util"
@@ -8,6 +10,9 @@
 install = require("gulp-install")
 zip = require("gulp-zip")
 runSequence = require("run-sequence")
+
+FsWrapper     = require("./fs_wrapper")
+LambdaWrapper = require("./lambda_wrapper")

 module.exports = class Lamjet
   @setup: (gulp)->
@@ -43,6 +48,68 @@
         ["archive-to-zip"],
         callback)

+    gulp.task "deploy-to-aws-lambda", (callback)->
+      config = require(path.join(process.cwd(), "lambda-config.js"))
+      # config = require("./lambda-config.js")
+      console.log config
+
+      # lambda = new aws.Lambda(
+      #   apiVersion: "2015-03-31",
+      #   region: config.Region)
+      # console.log lambda
+      lambda = new LambdaWrapper(region: config.Region)
+
+      FsWrapper.readFile("./out.zip")
+        .then (result)->
+          zipBody = result.body
+          param = {
+            FunctionName: config.FunctionName,
+            Description: config.Description,
+            Handler: config.Handler,
+            Role: config.Role,
+            Runtime: config.Runtime,
+            MemorySize: config.MemorySize,
+            Timeout: config.Timeout,
+            Code: {ZipFile: zipBody},
+          }
+          console.log param
+          return lambda.createFunction(param)
+            .then (result)->
+              console.log "created"
+              return Promise.resolve(result)
+            .catch (result)->
+              if result.error.statusCode == 409 # Function already exist
+                console.log result.error.statusCode
+                param = {
+                  FunctionName: config.FunctionName,
+                  Description: config.Description,
+                  Handler: config.Handler,
+                  Role: config.Role,
+                  MemorySize: config.MemorySize,
+                  Timeout: config.Timeout,
+                }
+                console.log param
+                return lambda.updateFunctionConfiguration(param)
+                  .then (result)->
+                    param = {
+                      FunctionName: config.FunctionName,
+                      ZipFile: zipBody,
+                    }
+                    console.log param
+                    return lambda.updateFunctionCode(param)
+              else
+                return Promise.reject(result)
+        .then (result)->
+          # console.log(JSON.stringify({then: result}, null, 2))
+          console.log({then: result})
+          # callback()
+        .catch (result)->
+          # console.log(JSON.stringify({catch: result}, null, 2))
+          console.log({catch: result})
+          console.log(result.stack) if result?.stack?
+          # callback(result)
+
+
     # TODO: 「lambduh-gulp」に依存しないように修正する。
     lambduhGulp(gulp)


Add description to cache.#getCol()

Add description to cache.#getCol()

--- coffee/Cache.class.coffee
+++ coffee/Cache.class.coffee
@@ -84,6 +84,9 @@
 #
 # Get document from database for type and id
 #
+# This method will automaticly filter object keys according to type in order
+# to prevent fetching of uncesserary data.
+#
 # @param type - {@code string) data type
 # @param id - {@code string} item id
 # @param cb - {@code function} callback function (err, data)


fixed inheritance bug with default properties

--- lib/model.coffee
+++ lib/model.coffee
@@ -1,3 +1,5 @@
+_ = require('underscore')
+
 class Model
   constructor: (@props = {}) ->
     @setupProps()
@@ -15,14 +17,16 @@

       if options.default
         @defaults ||= {}
+        @defaults = _.clone @defaults
+
         attributes.forEach (attribute) =>
           @defaults[attribute] = options.default

-    @attributes = @attributes.concat(attributes)
+    @attributes = _.uniq @attributes.concat(attributes)

   @type = (type = false) ->
-    @type = type if type
-    @type
+    @_type = type if type
+    @_type

   setupProps: ->
     @_props = {}


Extend Yandex Map bounds with markers

Extend Yandex Map bounds with markers

--- vendor/assets/javascripts/gmaps4rails/yandex/objects/map.coffee
+++ vendor/assets/javascripts/gmaps4rails/yandex/objects/map.coffee
@@ -27,8 +27,8 @@

     @serviceObject = new ymaps.Map(@options.id, mergedYandexOptions)

-  extendBoundsWithMarker : (marker)->
-    @boundsObject.extend(@createLatLng(marker.lat,marker.lng))
+  extendBoundsWithMarkers : (marker)->
+    @controller.getMapObject().setBounds(@controller.getMapObject().geoObjects.getBounds());

   extendBoundsWithPolyline: (polyline)->


Sort hosts alphabetically

Sort hosts alphabetically

--- app/routes/hosts/index.coffee
+++ app/routes/hosts/index.coffee
@@ -2,6 +2,7 @@

 HostsIndexRoute = Ember.Route.extend
   model: ->
-    @store.find 'host'
+    @store.find('host').then (hosts) ->
+      hosts.sortBy('name', 'instanceId')

 `export default HostsIndexRoute`


Now fixed appending dice on goal screen

Now fixed appending dice on goal screen

--- client/src/Screen/GoalScreen.coffee
+++ client/src/Screen/GoalScreen.coffee
@@ -35,7 +35,7 @@
     thisReference = this
     resourceList = $('#notadded-goal li.dice')
     resourceList.bind 'click', (event) ->
-      thisReference.addToGoal($(this).data('index'));
+      thisReference.addDiceToGoal($(this).data('index'));
     $('#sendgoal').bind 'click', (event) ->
       Network.sendGoal(thisReference.createGoalArray())

@@ -89,11 +89,14 @@

+
+
+
   ###*
    * Move a dice from resources to the goal.
    * @param {Number} index The (zero based) index of the resources array to move.
   ###
-  addToGoal: (index) ->
+  addDiceToGoal: (index) ->
     # Add the diceface to the dom and add a click listener that removes it when its clicked
     if(@numberInGoal < 6) # There is a maximum of six dice allowed
       thisReference = this
@@ -104,14 +107,22 @@
         html = "

"
         $(html).appendTo("#added-goal").bind 'click', (event) ->
           thisReference.dotListener(this)
-
-      # Now add a dot to the right of the newly added dice
+
       @numberInGoal++
       @numberDots++
       diceFace = DiceFace.toHtml(@resources[index])
       html = "
#{diceFace}
"
       html2 = "

"
       $('#notadded-goal li.dice[data-index='+index+']').remove()
+      @cleanUpBrackets()
+
+
+      if($('li.dot:nth-last-child(2)').attr('data-bracket') is 'right')
+        @numberDots--
+        $('li.dot:last-child').remove()
+
+
+
       $(html).appendTo("#added-goal").bind 'click', (event) ->
         thisReference.removeFromGoal($(this).data('index'));
       $(html2).appendTo("#added-goal").bind 'click', (event) ->
@@ -130,7 +141,7 @@
     $('#added-goal li.dice[data-index='+index+']').remove()
     @cleanUpBrackets()
     $(html).appendTo("#notadded-goal").bind 'click', (event) ->
-      thisReference.addToGoal($(this).data('index'));
+      thisReference.addDiceToGoal($(this).data('index'));

   cleanUpBrackets: () ->


KodingProvider: s/amazon/aws/

KodingProvider: s/amazon/aws/

--- workers/social/lib/social/models/computeproviders/koding.coffee
+++ workers/social/lib/social/models/computeproviders/koding.coffee
@@ -59,7 +59,7 @@
           region ?= (Regions.findRegion userIp, SUPPORTED_REGIONS).regions[0]

           meta =
-            type          : 'amazon' # Do we need this field? ~ GG
+            type          : 'aws'
             region        : region ? SUPPORTED_REGIONS[0]
             source_ami    : '' # Kloud is updating this field after a successfull build
             instance_type : 't2.micro'


updating select topics has changed logic

--- src/components/task-plan/select-topics.cjsx
+++ src/components/task-plan/select-topics.cjsx
@@ -121,15 +121,21 @@
     hide: React.PropTypes.func.isRequired
     selected: React.PropTypes.array

+  getInitialState: -> {initialSelected: @props.selected}
+
   renderChapterPanels: (chapter, i) ->
     expanded = not @props.selected?.length and i is 0
     <ChapterAccordion {...@props} expanded={expanded} chapter={chapter}/>
+
+  hasChanged: ->
+    @props.selected and not _.isEqual(@props.selected, @state.initialSelected)

   renderDialog: ->
     {courseId, planId, selected, hide, header, primary, cancel} = @props

     selected = TaskPlanStore.getTopics(planId)
     chapters = _.map(TocStore.get(@props.ecosystemId), @renderChapterPanels)
+    changed = @hasChanged()

     <Dialog
       className='select-reading-dialog'
@@ -137,7 +143,7 @@
       primary={primary}
       confirmMsg='You will lose unsaved changes if you continue.'
       cancel='Cancel'
-      isChanged={-> true}
+      isChanged={-> changed}
       onCancel={cancel}>

       <div className='select-reading-chapters'>


Fix issue picking up configured JVM options

--- fmc/fmc-webui/src/main/webapp/app/controllers/add_agent_wizard.coffee
+++ fmc/fmc-webui/src/main/webapp/app/controllers/add_agent_wizard.coffee
@@ -826,7 +826,7 @@
       proxy = null
       jvmopts = null
       proxy = @proxy.val() if @use_proxy.is ":checked"
-      jvmopts = @jvm_opts if @use_jvm_opts is ":checked"
+      jvmopts = @jvm_opts.val() if @use_jvm_opts.is ":checked"
       ensemble_server = @ensemble_server.is ":checked"

       @state.set {


add comment about upsert and locking

add comment about upsert and locking

--- services/web/app/coffee/Features/Project/ProjectEntityUpdateHandler.coffee
+++ services/web/app/coffee/Features/Project/ProjectEntityUpdateHandler.coffee
@@ -261,6 +261,11 @@
 					return callback(err) if err?
 					callback null, doc, !existingDoc?

+	# FIXME: this method needs to be changed, currently it needs a lock around an upload to S3 because
+	# there is no way to know in advance if the file is a replace or an insert (at least you have to
+	# take the lock to find that out and do any operation in that lock).  In the new scheme any upsert
+	# should always create the new file (outside the lock) in S3 first and then make the changes to the
+	# project in a lock, marking the old file as deleted if it exists.
 	upsertFile: wrapWithLock (project_id, folder_id, fileName, fsPath, linkedFileData, userId, callback = (err, file, isNewFile)->)->
 		ProjectLocator.findElement project_id: project_id, element_id: folder_id, type: "folder", (error, folder) ->
 			return callback(error) if error?


Move formatQuestionType helper to correct template

--- app/packages/results/controllers/types/basic_results_info.coffee
+++ app/packages/results/controllers/types/basic_results_info.coffee
@@ -3,8 +3,6 @@
 Template.basic_results_info.helpers
   hasRange: ->
     @type in ['number', 'scale']
-
-  formatQuestionType: -> formatQuestionType(@type)

 Template.type_icon.helpers
   icon: ->
@@ -26,3 +24,5 @@
         'sliders'
       when 'shortAnswer'
         'minus'
+
+  formatQuestionType: -> formatQuestionType(@type)


Version bump 0.3.1

Version bump 0.3.1

--- src/jquery.superslides.coffee
+++ src/jquery.superslides.coffee
@@ -1,5 +1,5 @@
 ###
-  Superslides 0.3.0
+  Superslides 0.3.1
   Fullscreen slideshow plugin for jQuery
   by Nic Aitch @nicinabox
   http://nicinabox.github.com/superslides/


Fixed all sorts of bugs discovered from the new test. All tests currently pass.

--- lib/suite.coffee
+++ lib/suite.coffee
@@ -5,6 +5,7 @@
 # MIT Licensed
 #
 {Runner} = require './runner'
+{Test} = require './test'

@@ -41,7 +42,7 @@
     item = @_tests_and_suites[index]

     if not item?
-      @_run_runners @_afters callback
+      @_run_runners @_afters, callback
       return

     befores_callback = (reports) ->
@@ -49,7 +50,7 @@
       item.run test_callback

     test_callback = (report) =>
-      @_run_runners after_eachs
+      @_run_runners after_eachs, after_eachs_callback

     after_eachs_callback = (report) =>
       @_run callback, befores, before_eachs, after_eachs, ++index
@@ -74,7 +75,7 @@

     runner.run (report) ->
       reports.push report
-      @_run_runner runners, callback, ++index, reports
+      @_run_runners runners, callback, ++index, reports

   # (runner) -> undefined
   #
@@ -151,7 +152,9 @@
   #
   # Desc:
   #   Run all the tests found in this suite, and any suites added to this.
-  run: (callback) ->
+  run: (callback=->) ->
+    @_run (reports) ->
+      callback()


Don't list items twice/

Don't list items twice/

--- client/landing/app/Applications/Groups.kdapplication/Views/paymentmodalview.coffee
+++ client/landing/app/Applications/Groups.kdapplication/Views/paymentmodalview.coffee
@@ -50,11 +50,6 @@
     @group = options.group
     super

-  loadView:->
-
-    super
-    @loadItems()
-
   loadItems:(callback)->
     @removeAllItems()
     @customItem?.destroy()


Revert "Report unsaved changes after 60 seconds"

This reverts commit 44a7e598f2fdbd91d18cc340de477ca3d33a1338.

--- services/web/public/coffee/ide/editor/controllers/SavingNotificationController.coffee
+++ services/web/public/coffee/ide/editor/controllers/SavingNotificationController.coffee
@@ -24,8 +24,6 @@
 					if oldStatus[doc_id]?
 						newStatus[doc_id] = oldStatus[doc_id]
 						newStatus[doc_id].unsavedSeconds += 1
-						if newStatus[doc_id].unsavedSeconds == 60
-							reportUnsavedChanges(doc)
 					else
 						newStatus[doc_id] = {
 							unsavedSeconds: 0
@@ -41,12 +39,6 @@
 				$scope.docSavingStatusCount = newUnsavedCount
 				$scope.$apply()

-		reportUnsavedChanges = (doc) ->
-			ide.reportError new Error("unsaved changes"), {
-				inflightOp: doc?.getInflightOp(),
-				pendingOp: doc?.getPendingOp()
-			}
-
 		warnAboutUnsavedChanges = () ->
 			if Document.hasUnsavedChanges()
 				return "You have unsaved changes. If you leave now they will not be saved."


fix(lint): remove unnecessary double quotes

--- test/acceptance/crud.coffee
+++ test/acceptance/crud.coffee
@@ -11,7 +11,7 @@
 delete doc.checksum

 beforeEach ->
-  req.post "/turer?api_key=dnt"
+  req.post '/turer?api_key=dnt'
     .send doc
     .expect 201
     .expect (res) ->


Fix bug in order cycle select dropdown

Fix bug in order cycle select dropdown

The date filters were being filled with the string: "Invalid date" because momentjs was not able to parse the input

--- app/assets/javascripts/admin/line_items/controllers/line_items_controller.js.coffee
+++ app/assets/javascripts/admin/line_items/controllers/line_items_controller.js.coffee
@@ -23,8 +23,11 @@

   $scope.refreshData = ->
     unless !$scope.orderCycleFilter? || $scope.orderCycleFilter == 0
-      $scope.startDate = moment(OrderCycles.byID[$scope.orderCycleFilter].orders_open_at).format('YYYY-MM-DD')
-      $scope.endDate = moment(OrderCycles.byID[$scope.orderCycleFilter].orders_close_at).startOf('day').format('YYYY-MM-DD')
+      start_date = OrderCycles.byID[$scope.orderCycleFilter].orders_open_at
+      end_date = OrderCycles.byID[$scope.orderCycleFilter].orders_close_at
+      format = "YYYY-MM-DD HH:mm:ss Z"
+      $scope.startDate = moment(start_date, format).format('YYYY-MM-DD')
+      $scope.endDate = moment(end_date, format).startOf('day').format('YYYY-MM-DD')

     formatted_start_date = moment($scope.startDate).format()
     formatted_end_date = moment($scope.endDate).add(1,'day').format()


Make the iframe with the player higher, to avoid scrolling even when the selection stats are displayed

--- app/assets/javascripts/rglossa/speech/components/centre/results/wfplayer.jsx.coffee
+++ app/assets/javascripts/rglossa/speech/components/centre/results/wfplayer.jsx.coffee
@@ -19,4 +19,4 @@
     $node.find("#waveframe").attr('src', "wfplayer-#{corpus_id}-#{line_key}-#{start}-#{stop}")

   render: ->
-    `<div><iframe height="370" width="100%" id="waveframe" target="_blank" className="wfplayer"></iframe></div>`
+    `<div><iframe height="385" width="100%" id="waveframe" target="_blank" className="wfplayer"></iframe></div>`


Proper engrish

Proper engrish

--- client/landing/app/Applications/Home.kdapplication/ContentDisplays/AboutView.coffee
+++ client/landing/app/Applications/Home.kdapplication/ContentDisplays/AboutView.coffee
@@ -49,7 +49,7 @@

-            We're located at SOMA district in San Francisco, California.
+            We're located in the SOMA district of San Francisco, California.

           <address>


Commented prettyRender

Commented prettyRender

--- coffeequate/src/prettyRender.coffee
+++ coffeequate/src/prettyRender.coffee
@@ -121,87 +121,185 @@
     node.terms = terms
     return node

+  # Drawing node representing addition.
   class Add extends DrawingNode
+
+    # Make a new Add drawing node.
+    #
+    # @param terms... [Array<DrawingNode>] Drawing nodes to add together.
+    # @return [Add] A new addition drawing node.
     constructor: (@terms...) ->

+    # How strongly bound the node is.
+    #
+    # @return [Number] Binding strength.
     bindingStrength: ->
       4

+    # Draw the node as a LaTeX string.
+    #
+    # @return [String] This node drawn as LaTeX.
     renderLaTeX: ->
       return @terms.map((x) -> x.renderLaTeX()).join(" + ")

+    # Draw the node as a string.
+    #
+    # @return [String] This node drawn as a string.
     renderString: ->
       return @terms.map((x) -> x.renderString()).join(" + ")

+    # Draw the node as a MathML string.
+    #
+    # @return [String] This node drawn as MathML.
     renderMathML: ->
       return @terms.map((x) -> x.renderMathML())
                    .join("<mo>+</mo>")

+  # Drawing node representing multiplication.
   class Mul extends DrawingNode
+
+    # Make a new multiplication drawing node.
+    #
+    # @param terms... [Array<DrawingNode>] Drawing nodes to multiply together.
+    # @return [Mul] A new multiplication drawing mode.
     constructor: (@terms...) ->

+    # How strongly this node is bound.
+    #
+    # @return [Number] Binding strength.
     bindingStrength: ->
       6

+    # Draw the node as a LaTeX string.
+    #
+    # @return [String] This node drawn as LaTeX.
     renderLaTeX: ->
       return @terms.map((x) -> x.renderLaTeX()).join(" \\cdot ")

+    # Draw the node as a string.
+    #
+    # @return [String] This node drawn as a string.
     renderString: ->
       return @terms.map((x) -> x.renderString()).join("*")

+    # Draw this node as a MathML string.
     renderMathML: ->
       return @terms.map((x) -> x.renderMathML()).join("<mo>·</mo>")

+  # Drawing node representing exponentiation.
   class Pow extends DrawingNode
+
+    # Make a new exponentiation drawing node.
+    #
+    # @param left [DrawingNode] The base of the power node.
+    # @param right [DrawingNode] The exponent of the power node.
+    # @return [Pow] A new exponentiation drawing node.
     constructor: (@left, @right) ->

+    # Draw the node as a LaTeX string.
+    #
+    # @return [String] This node drawn as LaTeX.
     renderLaTeX: ->
       "#{@left.renderLaTeX()}^{#{@right.renderLaTeX()}}"

+    # Draw the node as a string.
+    #
+    # @return [String] This node drawn as a string.
     renderString: ->
       "#{@left.renderString()}**#{@bracketIfNeeded(@right).renderString()}"

+    # Draw the node as a MathML string.
+    #
+    # @return [String] This node drawn as MathML.
     renderMathML: ->
       "<msup>#{@left.renderMathML()}#{@right.renderMathML()}</msup>"

-
+  # Drawing node representing bracketing.
   class Bracket extends DrawingNode
+
+    # Make a new bracket drawing node.
+    #
+    # @param contents [Array<DrawingNode>] Drawing nodes inside the brackets.
+    # @return [Bracket] A new bracket node.
     constructor: (@contents) ->

+    # How strongly bound this node is.
+    #
+    # @return [Number] Binding strength.
     bindingStrength: ->
       9

+    # Draw the node as a LaTeX string.
+    #
+    # @return [String] This node drawn as LaTeX.
     renderLaTeX: ->
       return "\\left(#{@contents.renderLaTeX()}\\right)"

+    # Draw the node as a string.
+    #
+    # @return [String] This node drawn as a string.
     renderString: ->
       return "(#{@contents.renderString()})"

-    renderMathML: ->
-      return "<mfenced><mrow>#{@contents.renderMathML()}" +
-                                                                "</mrow></mfenced>"
-
+    # Draw the node as a MathML string.
+    #
+    # @return [String] This node drawn as MathML.
+    renderMathML: ->
+      return "<mfenced><mrow>#{@contents.renderMathML()}</mrow></mfenced>"
+
+  # Drawing node representing a number.
   class Number extends DrawingNode
-    constructor: (@value) ->
-
+
+    # Make a new number drawing node.
+    #
+    # @param value [Number] The value of the number.
+    # @param classname [String] Optional. The name that should be set as the class for this node if drawn as MathML or similar.
+    # @return [Number] A new drawing node representing this number.
+    constructor: (@value, @classname="constant") ->
+
+    # How strongly this node is bound.
+    #
+    # @return [Number] Binding strength.
     bindingStrength: ->
       10

+    # Draw the node as a LaTeX string.
+    #
+    # @return [String] This node drawn as LaTeX.
     renderLaTeX: ->
       return @value+""

+    # Draw the node as a string.
+    #
+    # @return [String] This node drawn as a string.
     renderString: ->
       return @value+""

-    renderMathML: ->
-      return "<mn class=\"constant\">#{@value}</mn>"
-
+    # Draw the node as MathML.
+    #
+    # @return [String] This node drawn as MathML.
+    renderMathML: ->
+      return "<mn class=\"#{@classname}\">#{@value}</mn>"
+
+  # Drawing node representing a variable.
   class Variable extends DrawingNode
+
+    # Make a new variable drawing node.
+    #
+    # @param label [String] The label of this variable.
+    # @param classname [String] Optional. The name that should be set as the class for this node if drawn as MathML or similar.
+    # @return [Variable] A new variable drawing node.
     constructor: (@label, @classname="variable") ->

+    # How strongly this node is bound.
+    #
+    # @return [Number] Binding strength.
     bindingStrength: ->
       10

+    # Draw the node as a LaTeX string.
+    #
+    # @return [String] This node drawn as LaTeX.
     renderLaTeX: ->
       # Check for Greek characters.
       mlabel = ""
@@ -212,9 +310,15 @@
           mlabel += char
       return mlabel

+    # Draw the node as a string.
+    #
+    # @return [String] This node drawn as a string.
     renderString: ->
       return @label

+    # Draw the node as MathML.
+    #
+    # @return [String] This node drawn as MathML.
     renderMathML: ->
       labelArray = @label.split("-")
       label = labelArray[0]
@@ -232,19 +336,37 @@
       else
         return '<mi class="' + @classname + '">' + label + '</mi>'

-
+  # Drawing node representing a fraction.
   class Fraction extends DrawingNode
+
+    # Make a new fraction drawing node.
+    #
+    # @param top [DrawingNode] The node to be drawn on top of the fraction.
+    # @param bottom [DrawingNode] The node to be drawn on the bottom of the fraction.
+    # @return [Fraction] A new fraction drawing node.
     constructor: (@top, @bottom) ->

+    # How strongly this node is bound.
+    #
+    # @return [Number] Binding strength.
     bindingStrength: ->
       8

+    # Draw the node as a LaTeX string.
+    #
+    # @return [String] This node drawn as LaTeX.
     renderLaTeX: ->
       return "\\frac{#{@top.renderLaTeX()}}{#{@bottom.renderLaTeX()}}"

+    # Draw the node as a string.
+    #
+    # @return [String] This node drawn as a string.
     renderString: ->
       return "#{@bracketIfNeeded(@top).renderString()}/#{@bracketIfNeeded(@bottom).renderString()}"

+    # Draw the node as MathML.
+    #
+    # @return [String] This node drawn as MathML.
     renderMathML: (x,y) ->
       "<mfrac>
       <mrow>#{@top.renderMathML(x,y)}</mrow>
@@ -252,22 +374,36 @@
       </mfrac>"

-
+  # Drawing node representing a surd/root.
   class Surd extends DrawingNode
+
+    # Make a new surd drawing node.
+    #
+    # @param contents [DrawingNode] The node to draw inside the root.
+    # @param power [Number] Optional. The number of this root. For example, 2 for a sqrt and 3 for a cbrt.
     constructor: (@contents, @power = null) ->

+    # Draw the node as a LaTeX string.
+    #
+    # @return [String] This node drawn as LaTeX.
     renderLaTeX: ->
       if @power and @power != 2
         return "\\sqrt[#{@power}]{#{@contents.renderLaTeX()}}"
       else
         return "\\sqrt{#{@contents.renderLaTeX()}}"

+      # Draw the node as a string.
+      #
+      # @return [String] This node drawn as a string.
     renderString: ->
       if @power and @power != 2
         return "#{@bracketIfNeeded(@contents).renderString()} ** (1/#{@power})"
       else
         return "sqrt(#{@contents.renderString()})"

+      # Draw the node as MathML.
+      #
+      # @return [String] This node drawn as MathML.
     renderMathML: (x...) ->
       if @power and @power != 2
         return "<mroot>
@@ -283,18 +419,36 @@
                   #{@contents.renderMathML(x...)}
                 </msqrt>"

+  # Drawing node representing an uncertainty.
   class Uncertainty extends DrawingNode
+
+    # Make a new uncertainty drawing node.
+    #
+    # @param label [String] The label of the variable this uncertainty represents.
+    # @param class [String] Optional. The name that should be set as the class for this node if drawn as MathML or similar.
     constructor: (@label, @class="default") ->

+    # How strongly this node is bound.
+    #
+    # @return [Number] Binding strength.
     bindingStrength: ->
       9

+    # Draw the node as a LaTeX string.
+    #
+    # @return [String] This node drawn as LaTeX.
     renderLaTeX: ->
       return "\\sigma_{#{@label}}"

+    # Draw the node as a string.
+    #
+    # @return [String] This node drawn as a string.
     renderString: ->
       return "σ(#{@label})"

+    # Draw the node as MathML.
+    #
+    # @return [String] This node drawn as MathML.
     renderMathML: (x...)->
       dummy = new Variable(@label)
       return "<msub><mo>σ</mo>#{dummy.renderMathML(x...)}</msub>"


Fixed  new entry from hiding

Fixed  new entry from hiding

--- public/dreamcatcher/controllers/application_controller.coffee
+++ public/dreamcatcher/controllers/application_controller.coffee
@@ -9,7 +9,7 @@
     @comment = new Dreamcatcher.Controllers.Comments $('#entryField') if $('#entryField').exists()
     @imageBank = new Dreamcatcher.Controllers.ImageBank $("#frame.browser") if $("#frame.browser").exists()
     @comments = new Dreamcatcher.Controllers.Comments $('#entryField') if $('#entryField').exists()
-    @entries = new Dreamcatcher.Controllers.Entries $("#entryField") if $("#entryField").exists()
+    @entries = new Dreamcatcher.Controllers.Entries $("#entryField .matrix") if $("#entryField .matrix").exists()
     @stream = new Dreamcatcher.Controllers.Stream $("#streamContextPanel") if $("#streamContextPanel").exists()
     @admin = new Dreamcatcher.Controllers.Admin $('#adminPage') if $('#adminPage').exists()


optmize wizard view

optmize wizard view

--- lib/utils/wizard-view.coffee
+++ lib/utils/wizard-view.coffee
@@ -14,6 +14,7 @@
   @content: ->
     @div class: 'butterfly overlay from-top', =>

+      # content view of each step, insert here
       @div outlet: 'contentView', class: 'content'

       @div class: 'actions', =>
@@ -28,7 +29,7 @@
   initialize: ->
     throw new Error('@flow must be specified.') unless @constructor.flow

-    #multi inheritance...
+    # mixin
     _.extend this, EventEmitter.prototype

     @order = 0 #current flow order
@@ -54,7 +55,7 @@

   onClickNext: ->
     #collect result into @result object
-    _.extend @result, @currentView.getResult()
+    _.extend @result, @currentView.getResult() if @currentView.getResult

     if @order < @constructor.flow.length - 1
       @order++
@@ -69,3 +70,9 @@

   destroy: ->
     @detach()
+
+  enableNext: ->
+    @next.prop 'disabled', false
+
+  disableNext: ->
+    @next.prop 'disabled', true


hide if no docs

hide if no docs

--- lib/atom-ternjs-autocomplete.coffee
+++ lib/atom-ternjs-autocomplete.coffee
@@ -82,10 +82,14 @@

     setDocumentationContent: ->
         return unless @suggestionsArr.length
+        currentSuggestion = @suggestionsArr[@currentSuggestionIndex]
+        if !currentSuggestion._ternDocs
+            @documentation.hide()
+            return
         @documentation.set({
-            word: @suggestionsArr[@currentSuggestionIndex].word,
-            label: @suggestionsArr[@currentSuggestionIndex].label,
-            docs: @suggestionsArr[@currentSuggestionIndex]._ternDocs
+            word: currentSuggestion.word,
+            label: currentSuggestion.label,
+            docs: currentSuggestion._ternDocs
         })

     forceCompletion: ->


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/engine_selector.coffee
+++ test/engine_selector.coffee
@@ -22,8 +22,7 @@
   indexSum = 0

   engine.each (obj, index) ->
-    counter += 1
-    indexSum +=
+

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


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/engine_selector.coffee
+++ test/engine_selector.coffee
@@ -17,7 +17,7 @@
     x: 0
     y: 15

-  equals engine.closest(".enemy", player.position())
+  equals engine.closest(".enemy", player.position()), enemy1

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


Refactored number of classes

Refactored number of classes

--- core/app/backbone/views/fact_relations/argument_vote_view.coffee
+++ core/app/backbone/views/fact_relations/argument_vote_view.coffee
@@ -31,12 +31,6 @@

     @model.getFactWheel().undoOpinion()

-class window.FactVoteUpLineView extends FactVoteLineView
-  template: 'facts/vote_up_line'
-
-class window.FactVoteDownLineView extends FactVoteLineView
-  template: 'facts/vote_down_line'
-
 class FactRelationVoteLineView extends Backbone.Marionette.ItemView

   className: 'vote-up-down-line'
@@ -66,12 +60,6 @@

     @model.undoOpinion()

-class window.FactRelationVoteUpLineView extends FactRelationVoteLineView
-  template: 'fact_relations/vote_up_line'
-
-class window.FactRelationVoteDownLineView extends FactRelationVoteLineView
-  template: 'fact_relations/vote_down_line'
-
 class ArgumentVoteView extends Backbone.Marionette.Layout
   className: 'vote-up-down'
   template: 'arguments/vote_popover'
@@ -81,17 +69,23 @@
     factLineRegion: '.js-fact-line-region'

 class window.ArgumentVoteUpView extends ArgumentVoteView
-
   onRender: ->
-    @factRelationLineRegion.show new FactRelationVoteUpLineView(model: @model)
+    @factRelationLineRegion.show new FactRelationVoteLineView
+      template: 'fact_relations/vote_up_line'
+      model: @model

     if @model instanceof FactRelation
-      @factLineRegion.show new FactVoteUpLineView(model: @model.getFact())
+      @factLineRegion.show new FactVoteLineView
+        template: 'facts/vote_up_line'
+        model: @model.getFact()

 class window.ArgumentVoteDownView extends ArgumentVoteView
-
   onRender: ->
-    @factRelationLineRegion.show new FactRelationVoteDownLineView(model: @model)
+    @factRelationLineRegion.show new FactRelationVoteLineView
+      template: 'fact_relations/vote_down_line'
+      model: @model

     if @model instanceof FactRelation
-      @factLineRegion.show new FactVoteDownLineView(model: @model.getFact())
+      @factLineRegion.show new FactVoteLineView
+        template: 'facts/vote_down_line'
+        model: @model.getFact()


Autoexpand columns if resultset has 1 row 1 col

--- lib/bottom-dock/results-pane.coffee
+++ lib/bottom-dock/results-pane.coffee
@@ -104,6 +104,8 @@
         table = new TableView options, resultset.rows, resultset.columns , height
         @tables.push {table:table, queryid:resultset['queryid'], nrrows: resultset.rowcount, pinned:false, querynumber: @querynumber}
         @append table
+        if resultset.onlyOne and resultset.rowcount == 1 and resultset.columns.length == 1
+            @expandColumns(resultset.queryid)

     initialize: ->
         super()


test paths

test paths

--- client/landing/app/Applications/Activity.kdapplication/widgets/statuswidget.coffee
+++ client/landing/app/Applications/Activity.kdapplication/widgets/statuswidget.coffee
@@ -33,6 +33,7 @@
       placeholder   : "What's new #{name}?"
       name          : 'body'
       style         : 'input-with-extras'
+      testPath      : 'status-update-input'
       autogrow      : yes
       validate      :
         rules       :


Added couple of helper functions for function goto

--- lib/services/php-file-parser.coffee
+++ lib/services/php-file-parser.coffee
@@ -388,17 +388,18 @@
     return null

   ###*
-   * Gets the class and namespace (if there is one) from the buffer position given.
+   * Gets the full words from the buffer position given.
+   * E.g. Getting a class with its namespace.
    * @param  {TextEditor}     editor   TextEditor to search.
    * @param  {BufferPosition} position BufferPosition to start searching from.
-   * @return {string}  Returns a string of the class.
-  ###
-  getClassFromBufferPosition: (editor, position) ->
+   * @return {string}  Returns a string of the class.
+  ###
+  getFullWordFromBufferPosition: (editor, position) ->
     foundStart = false
     foundEnd = false
     startBufferPosition = []
     endBufferPosition = []
-    regex = /\(|\s|\)|;|'|,|"|:|\|/
+    regex = /\(|\s|\)|;|'|,|"|\|/
     index = -1
     previousText = ''

@@ -425,3 +426,35 @@
     startBufferPosition[1] += 1
     endBufferPosition[1] -= 1
     return editor.getTextInBufferRange([startBufferPosition, endBufferPosition])
+
+  getParentClass: (editor) ->
+    text = editor.getText()
+
+    lines = text.split('\n')
+    for line in lines
+      line = line.trim()
+
+      # If we found extends keyword, return the class
+      if line.indexOf('extends ') != -1
+        words = line.split(' ')
+        extendsIndex = words.indexOf('extends')
+        return @findUseForClass(editor, words[extendsIndex + 1])
+
+  findBufferPositionOfFunction: (editor, term) ->
+    text = editor.getText()
+    row = 0
+    lines = text.split('\n')
+    for line in lines
+      regex = ///function\ +#{term}(\ +|\()///i
+      if regex.test(line)
+        words = line.split(' ')
+        functionIndex = 0
+        for element in words
+            if element.indexOf(term) != -1
+                break
+            functionIndex++;
+
+        reducedWords = words.slice(0, functionIndex).join(' ')
+        return [row, reducedWords.length + 1]
+      row += 1
+    return null


打开前关闭其他属于变色龙的panel

打开前关闭其他属于变色龙的panel

--- lib/utils/chameleon-box-view.coffee
+++ lib/utils/chameleon-box-view.coffee
@@ -157,10 +157,23 @@
       @hide()
       @destroy()

+  closeOtherView: ->
+    tempArr = []
+    for panel in atom.workspace.getModalPanels()
+      el = panel.item
+      if el isnt @ && el.hasClass 'chameleon'
+        tempArr.push panel
+    for panel in tempArr
+      panel.item.remove();
+      panel.hide()
+      panel.destroy()
+    tempArr = null
+
   openView: ->
     if @enable isnt yes
       return
     @findModalPanel()
+    @closeOtherView()
     if @modalPanel?.isVisible() is no
       @modalPanel.show()
       return @modalPanel.isVisible()


Make options default for all targets (less, handlebars, jst, uglify)

--- config/application.coffee
+++ config/application.coffee
@@ -25,29 +25,26 @@

   #style
   less:
-    compile:
-      options:
-        paths: ["app/css", "vendor/css"]
-
+    options:
+      paths: ["app/css", "vendor/css"]
+    compile:
       files:
         "generated/css/app.less.css": "<%= files.less.app %>"

   #templates
   handlebars:
-    compile:
-      options:
-        namespace: "JST"
-        wrapped: true
-
+    options:
+      namespace: "JST"
+      wrapped: true
+    compile:
       files:
         "generated/template/handlebars.js": "<%= files.template.handlebars %>"

   jst:
-    compile:
-      options:
-        namespace: "JST"
-
+    options:
+      namespace: "JST"
+    compile:
       files:
         "generated/template/underscore.js": "<%= files.template.underscore %>"

@@ -130,9 +127,9 @@

   #optimizing
   uglify:
-    js:
-      options:
-        banner: "<%= meta.banner %>"
+    options:
+      banner: "<%= meta.banner %>"
+    js:
       files:
         "dist/js/app.min.js": "<%= files.glob.js.concatenated %>"


Fix generation of thread id

Fix generation of thread id

--- services/web/public/coffee/ide/review-panel/controllers/ReviewPanelController.coffee
+++ services/web/public/coffee/ide/review-panel/controllers/ReviewPanelController.coffee
@@ -99,17 +99,22 @@
 				$scope.$broadcast "review-panel:toggle"
 				$scope.$broadcast "review-panel:layout"

-		regenerateTrackChangesId = (doc) ->
-			old_id = getChangeTracker(doc.doc_id).getIdSeed()
+		generatePartialMongoId = () ->
 			# Generate a the first 18 characters of Mongo ObjectId, leaving 6 for the increment part
 			# Reference: https://github.com/dreampulse/ObjectId.js/blob/master/src/main/javascript/Objectid.js
 			pid = Math.floor(Math.random() * (32767)).toString(16)
 			machine = Math.floor(Math.random() * (16777216)).toString(16)
 			timestamp = Math.floor(new Date().valueOf() / 1000).toString(16)
-			new_id = '00000000'.substr(0, 8 - timestamp.length) + timestamp +
+			return '00000000'.substr(0, 8 - timestamp.length) + timestamp +
 				'000000'.substr(0, 6 - machine.length) + machine +
 				'0000'.substr(0, 4 - pid.length) + pid
-
+
+		generateFullMongoId = () ->
+			return generatePartialMongoId() + "000000"
+
+		regenerateTrackChangesId = (doc) ->
+			old_id = getChangeTracker(doc.doc_id).getIdSeed()
+			new_id = generatePartialMongoId()
 			getChangeTracker(doc.doc_id).setIdSeed(new_id)
 			doc.setTrackChangesIdSeeds({pending: new_id, inflight: old_id})

@@ -214,7 +219,7 @@
 				$scope.$broadcast "review-panel:layout"

 		$scope.submitNewComment = (content) ->
-			thread_id = RangesTracker.newId()
+			thread_id = generateFullMongoId()
 			$scope.$broadcast "comment:add", thread_id
 			$http.post("/project/#{$scope.project_id}/thread/#{thread_id}/messages", {content, _csrf: window.csrfToken})
 				.error (error) ->


[atom] add tree-view-git-modified

[atom] add tree-view-git-modified

--- .atom/packages.cson
+++ .atom/packages.cson
@@ -13,4 +13,5 @@
   "package-sync"
   "project-plus"
   "sort-lines"
+  "tree-view-git-modified"
 ]


allow initial value in the Stack ctor

allow initial value in the Stack ctor

--- lib/stack.coffee
+++ lib/stack.coffee
@@ -1,7 +1,9 @@

 exports.Stack = class Stack
-        constructor: ->
+        constructor: (initial)->
                 @stack = []
+                @stack.unshift initial if initial?
+

         push: (o) ->
                 @stack.unshift o


First draft of a field guide Text examples taken from Trish's tutorial.

--- examples.coffee
+++ examples.coffee
@@ -1 +1,65 @@
-module.exports = []
+module.exports = [{
+    label: 'Type'
+    figures: [{
+      label: 'Drawing/painting/diagram'
+      image: ""
+      alt: "An example of a drawing"
+    },{
+      label: 'Chart/table'
+      image: ""
+      alt: "An example of a chart"
+    },{
+      label: "Photograph"
+      image: ""
+      alt: "An example of a photograph"
+    },{
+      label: "Map"
+      image: ""
+      alt: "An example of a map"
+    }]
+  },{
+    label: "Keywords"
+    content: '''
+
Add general keywords or phrases about the primary species or subjects depicted in the  illustration Separate terms by semi-colons e.g. bird; landscape; crab; forest; man; woman; apple; pottery; cemetery; skull; fossil; microscopic view; meteor, meteorological observations.

+
If it is a chart or table, indicate the topic that the data represents e.g. Montana Wheat; Trout length; Livestock inventory; mirror

+
If is it a map, add any current or historic geographic locations indicated by the map or caption e.g. Three Lakes; Southern China; Canada; Uriconium; Yorkshire

+                 '''
+    figures: []
+  },{
+    label: "Content"
+    content: '''
+
Click on species, inscriptions and contributors in the illustration to record each one.

+                 '''
+    figures: [{
+      image: ""
+      alt: "Species example"
+      label: '''
+
Species

+
Common Name=Ostrich Scientific Name=Struthio camelus

+                   '''
+
+      },{
+        image: ""
+        alt: "Inscription example"
+        label: '''
+
Inscriptions

+

+
Near Alata Sidaillo

+
Dec 15- 1926-

+
Bycanistes cristatus

+

+                       '''
+
+      },{
+        image: ""
+        alt: "Contributors example"
+        label: '''
+
Contributors

+

+
Name=Werner Klinkhardt   Role=Printer

+
Name=Sharp & Son    Role=Illustrator

+

+                       '''
+
+      }]
+  }]


Some comments.

Some comments.

--- start.coffee
+++ start.coffee
@@ -158,17 +158,18 @@
 			res.json (doc.value for doc in docs)

 	app.get "/pca/basic", ( req, res ) ->
-		# This returns a json list of objects that include the title, artist, and pca_x and pca_y.
-
-		# Setup attributes to pca.. if we don't get anything error out.
+		# This returns a list of objects.
+		# The objects contain track information, such as title, artist, as well
+		# as x and y which are computed using PCA on the features that are specified.
+
+		# The 'pca' keyword is used to specify what attributes we want to perform the PCA on.
 		attrs = req.query.pca

+		# Force at least a single attribute to be specified.
 		if not attrs
 			return _error_out res, "No pca specified."
-
-		if typeof attrs is "string"
-			return _error_out res, "Multiple pca values need to be specified."

+		# This just gets a list of documents from the CouchDB server. The view isn't important at this point.
 		runtime['db'].view "songs/by-artist-and-title", ( err, docs ) ->
 			if err
 				return _error_out res, err
@@ -232,8 +233,12 @@

 			_return = [ ]
 			for doc in valid_docs
-				doc.x = k.Z.elements[i][0]
-				doc.y = k.Z.elements[i][1]
+				if k.Z.elements[i]?
+					doc.x = k.Z.elements[i][0]
+					doc.y = k.Z.elements[i][1]
+				else
+					doc.x = 0
+					doc.y = 0

 				# Note that we don't shove the entire doc back..
 				_return.push { "artist": doc.artist, "title": doc.title, "x": doc.x, "y": doc.y, "_id": doc._id }


Reorganised functions

Reorganised functions

--- steam.coffee
+++ steam.coffee
@@ -182,22 +182,22 @@

         communityID

-    getHero = (heroID) ->
-        return hero for hero in heroes when hero.id is heroID
-
-    getTowers = (dec) ->
-        for status, tower in "00000000000#{(+dec).toString(2)}".slice(-11).split('')
-            if parseInt(status) then towers[tower] else continue
-
-    steam_request = (msg, endpoint, params = {}, handler, version = 1) ->
-        params.key = STEAM_API_KEY
-
-        msg.http("http://api.steampowered.com#{endpoint}/v#{version}/")
-            .query(params)
-            .get() (err, res, body) ->
-                if err or res.statusCode isnt 200
-                    err = "Bad request (invalid Steam web API key)" if res.statusCode is 400
-                    msg.reply "An error occurred while attempting to process your request."
-                    return robot.logger.error err
-
-                handler JSON.parse(body)+getHero = (heroID) ->
+    return hero for hero in heroes when hero.id is heroID
+
+getTowers = (dec) ->
+    for status, tower in "00000000000#{(+dec).toString(2)}".slice(-11).split('')
+        if parseInt(status) then towers[tower] else continue
+
+steam_request = (msg, endpoint, params = {}, handler, version = 1) ->
+    params.key = STEAM_API_KEY
+
+    msg.http("http://api.steampowered.com#{endpoint}/v#{version}/")
+        .query(params)
+        .get() (err, res, body) ->
+            if err or res.statusCode isnt 200
+                err = "Bad request (invalid Steam web API key)" if res.statusCode is 400
+                msg.reply "An error occurred while attempting to process your request."
+                return robot.logger.error err
+
+            handler JSON.parse(body)


:bug: Fix issue if tablr.supportedCsvExtensions gets null

Fixes #64

--- lib/tablr.coffee
+++ lib/tablr.coffee
@@ -19,7 +19,9 @@
       'tablr:clear-csv-layout': => @csvConfig.clearOption('layout')

     @subscriptions.add atom.workspace.addOpener (uriToOpen) =>
-      return unless ///\.(#{atom.config.get('tablr.supportedCsvExtensions').join('|')})$///.test uriToOpen
+      extensions = atom.config.get('tablr.supportedCsvExtensions') ? ['csv', 'tsv', 'CSV', 'TSV']
+
+      return unless ///\.(#{extensions.join('|')})$///.test uriToOpen

       _ ?= require 'underscore-plus'
       CSVEditor ?= require './csv-editor'


make select2 set data attributes on generated options

--- app/assets/javascripts/folio/console/simple_form_inputs/_collection_select_input.coffee
+++ app/assets/javascripts/folio/console/simple_form_inputs/_collection_select_input.coffee
@@ -17,6 +17,12 @@
           minimumInputLength: 0
           cache: false
           data: (params) -> { q: params.term }
+        templateSelection: (data, container) ->
+          $el = $(data.element)
+          Object.keys(data).forEach (key) ->
+            if key.indexOf('data-') is 0
+              $el.attr(key, data[key])
+          return data.text

 window.folioConsoleUnbindCollectionSelectInput = ($elements) ->
   $elements.each -> $(this).select2('destroy')


Use model for saving

Use model for saving

--- backend/app/assets/javascripts/spree/backend/stock_management/index_update_forms.coffee
+++ backend/app/assets/javascripts/spree/backend/stock_management/index_update_forms.coffee
@@ -44,15 +44,13 @@
     backorderable = $("#backorderable-#{stockItemId}").prop("checked")
     countOnHand = parseInt($("#number-update-#{stockItemId} input[type='number']").val(), 10)

-    stockItem = new Spree.StockItem
-      id: stockItemId
+    @model.set
       count_on_hand: countOnHand
       backorderable: backorderable
-      stock_location_id: stockLocationId
     options =
       success: successHandler
       error: errorHandler
-    stockItem.save(force: true, options)
+    @model.save(force: true, options)

 $ ->
   $('.js-edit-stock-item').each ->


fix inconsistent indentation

fix inconsistent indentation


Improve cache.set's success logic.

Improve cache.set's success logic.

--- src/cache.coffee
+++ src/cache.coffee
@@ -106,13 +106,8 @@
             # Unset the lock process; the value has been updated.
             client.del "lock-process:#{key}", done
     ], (err, results) ->
-      # If we catch a `CacheError`, the update sequence bailed;
-      # set the result to `false`.
-      if err and err instanceof CacheError
-        return fn err, false
-
-      # Otherwise, the update was successful if there was no error.
-      fn err, !!err
+      # The update was successful if there was no error.
+      fn err, results and not err

 # Expose `Cache`.


improved test def

improved test def

--- test/tests/ColorTest.coffee
+++ test/tests/ColorTest.coffee
@@ -26,7 +26,7 @@
 		color = new Color hexColor
 		color.toHexString().should.eql hexColor

-	it "should constraint constructor options", ->
+	it "should clamp constructor options", ->

 		color = new Color
 			r: -10


Add tests for Backdrop properties

Add tests for Backdrop properties


Add billing data

Add billing data

--- coffee/stripe.service.coffee
+++ coffee/stripe.service.coffee
@@ -66,7 +66,7 @@
                 key: key,
                 image: image,
                 locale: 'auto',
-                billingAddress: false,
+                billingAddress: true,
                 panelLabel: 'Change data', # LOCALIZE
                 token: (data) =>
                     params = {


Make options argument optional in define function

--- collection-behaviours.coffee
+++ collection-behaviours.coffee
@@ -46,7 +46,7 @@
     optionsPattern = Match.ObjectIncluding
       replace: Boolean

-    check options, optionsPattern
+    check options, Match.Optional optionsPattern

     if name of behaviours and not options?.replace
       console.warn 'Behaviour already defined, use {replace: true} to override'


fix cloned save button

fix cloned save button

--- BackofficeBundle/Resources/public/coffee/backboneRouter.coffee
+++ BackofficeBundle/Resources/public/coffee/backboneRouter.coffee
@@ -10,6 +10,7 @@
     jQuery ->
       ribbonFormButtonViewClass = appConfigurationView.getConfiguration('ribbon-form-button', 'createRibbonFormButton')
       OpenOrchestra.RibbonButton.ribbonFormButtonView = new ribbonFormButtonViewClass()
+      OpenOrchestra.RibbonButton.ribbonFormButtonModalView = new ribbonFormButtonViewClass()
     return

   showHome: ->


Remove debugging statements from JS client.

--- lib/assets/javascripts/websocket_rails/websocket_rails.js.coffee
+++ lib/assets/javascripts/websocket_rails/websocket_rails.js.coffee
@@ -35,9 +35,7 @@
       event = new WebSocketRails.Event( socket_message )
       console.log event
       if event.is_result()
-        console.log "is a result"
         @queue[event.id]?.run_callbacks(event.success, event.data)
-        console.log @queue[event.id]
         @queue[event.id] = null
       else if event.is_channel()
         @dispatch_channel event
@@ -60,9 +58,6 @@
   trigger: (event_name, data, success_callback, failure_callback) =>
     event = new WebSocketRails.Event( [event_name, data, @connection_id], success_callback, failure_callback )
     @queue[event.id] = event
-    console.log "stored event"
-    console.log @queue[event.id]
-    console.log "event id #{event.id}"
     @_conn.trigger event

   trigger_event: (event) =>


prevent exiting if options.catch is false

--- lib/utils.coffee
+++ lib/utils.coffee
@@ -74,11 +74,14 @@
         else
           resolve()

-  _fileExistsAtPath: (pathToCypress) ->
+  _fileExistsAtPath: (pathToCypress, options = {}) ->
     fs.statAsync(pathToCypress)
       .bind(@)
       .return(pathToCypress)
       .catch (err) =>
+        ## allow us to bubble up the error if catch is false
+        return throw(err) if options.catch is false
+
         console.log("")
         console.log(chalk.bgRed.white(" -Error- "))
         console.log(chalk.red.underline("The Cypress App could not be found."))
@@ -92,13 +95,16 @@
         console.log("")
         process.exit(1)

-  verifyCypress: (pathToCypress) ->
+  verifyCypress: (pathToCypress, options = {}) ->
+    _.defaults options,
+      catch: true
+
     ## this needs to change to become async and
     ## to do a lookup for the cached cypress path
     pathToCypress ?= @getPathToExecutable()

     ## verify that there is a file at this path
-    @_fileExistsAtPath(pathToCypress)
+    @_fileExistsAtPath(pathToCypress, options)

       ## now verify that we can spawn cypress successfully
       .then(@_cypressSmokeTest)


Fix current proposal scrolling

Fix current proposal scrolling

--- lineman/app/components/thread_page/thread_page_controller.coffee
+++ lineman/app/components/thread_page/thread_page_controller.coffee
@@ -18,7 +18,7 @@
     AbilityService.canVoteOn(@discussion.activeProposal())

   @elementToFocus = ->
-    if @proposalToFocus
+    if @proposalToFocus or (@discussion.hasActiveProposal() and $location.search().proposal == @discussion.activeProposal().key)
       "#proposal-#{@proposalToFocus.key}"
     else if @commentToFocus
       "#comment-#{@commentToFocus.id}"
@@ -35,7 +35,8 @@
       @discussion = discussion
       @group      = @discussion.group()
       @comment    = Records.comments.build(discussion_id: @discussion.id)
-      @openVoteModal()
+      if @discussion.hasActiveProposal() and $location.search().proposal == @discussion.activeProposal().key
+        @proposalToFocus = @discussion.activeProposal()

       @sequenceIdToFocus = @discussion.reader().lastReadSequenceId # or location hash when we put it back in.


Revert: Auto fill path and name attributes for components

--- src/index.coffee
+++ src/index.coffee
@@ -93,10 +93,7 @@

     for name in options.components or []
-        comp = require name
-        comp::name ?= name
-        comp::view ?= require.resolve name, paths: globalPaths
-        app.component comp
+        app.component require name

     for moduleInfo in options.modules
         if _.isString moduleInfo


Fixes S3 test

Fixes S3 test

--- test/services/s3.spec.coffee
+++ test/services/s3.spec.coffee
@@ -1183,7 +1183,7 @@
               tr.push(new Buffer('test'))
           tr

-        s3 = new AWS.S3(signatureVersion: 'v4')
+        s3 = new AWS.S3(signatureVersion: 'v4', s3DisableBodySigning: false)
         stream = fs.createReadStream('path/to/file', {start:0, end:5})
         req = s3.putObject(Bucket: 'example', Key: 'key', Body: stream)
         req.send (err) ->


add require statements to tests that depend on coffee-script modules

--- test/test_compilation.coffee
+++ test/test_compilation.coffee
@@ -1,4 +1,6 @@
 # Ensure that carriage returns don't break compilation on Windows.
+CoffeeScript: require('coffee-script')
+Lexer: require('coffee-script/lexer')

 js: CoffeeScript.compile("one\r\ntwo", {no_wrap: on})


Add support for image, video and audio filter

--- src/links.coffee
+++ src/links.coffee
@@ -18,16 +18,26 @@
 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # THE SOFTWARE.

+filters = {
+						all: ".*",
+						image: "\.(jpg|jepg|png|gif|svg)$",
+						video: "\.(mov|qt|swf|flv|mpg|mpe|mpeg|mp2v|m2v|m2s|avi|asf|asx|wmv|wma|wmx|rm|ra|ram|rmvb|mp4|3g2|3gp|ogm|mkv)$",
+						audio: "\.(mp3|m4a|mpa|ra|wav|wma|aif|iff|mid)$"
+					}
+
 onClickHandler = (info, tab) ->
+	filter = filters[info.menuItemId]
 	chrome.tabs.sendMessage(tab.id, "getSelectedLinks", (response) ->
-		for link in response.links.reverse()
+		for link in response.links.reverse() when link.match(new RegExp(filter, "i"))
 			chrome.tabs.create({url:link,index:tab.index+1})
 	)

 onInstalledHandler = () ->
-	title = "Open all selected links"
 	contexts = ["page","selection","link","editable","image","video","audio"]
-	chrome.contextMenus.create({"title": title, "contexts": contexts, "id": "selection"})
+	chrome.contextMenus.create({"title": "All", "contexts": contexts, "id": "all"})
+	chrome.contextMenus.create({"title": "Images only", "contexts": contexts, "id": "image"})
+	chrome.contextMenus.create({"title": "Videos only", "contexts": contexts, "id": "video"})
+	chrome.contextMenus.create({"title": "Audio only", "contexts": contexts, "id": "audio"})

 chrome.contextMenus.onClicked.addListener(onClickHandler)
 chrome.runtime.onInstalled.addListener(onInstalledHandler)


Added test for #191

Added test for #191

--- test/validations_test.coffee
+++ test/validations_test.coffee
@@ -88,3 +88,27 @@

     test.done()

+it 'should validate uniqueness', (test) ->
+
+  Airport = schema.define 'Airport', code: String, city: String
+  Airport.validatesUniquenessOf 'code'
+
+  bkk = new Airport code: 'BKK', city: 'Bangkok'
+  bkk.isValid (valid) ->
+    test.ok valid
+    bkk.save ->
+      dmk = new Airport code: 'DMK', city: 'Bangkok'
+      dmk.isValid (valid) ->
+        test.ok valid
+        dmk.save ->
+        dmk.city = 'Bangkok, Don Muang'
+        dmk.isValid (valid) ->
+          test.ok valid
+          dmk.save ->
+            dmk.code = 'BKK'
+            dmk.isValid (valid) ->
+              test.ok !valid
+              dmk.code = 'DMK'
+              dmk.isValid (valid) ->
+                test.ok valid
+                test.done()


second try: fixing cannot revive. took over Arvid's fix from newkoding. added same fix on cache worker. and re-added logging to roll bar if anchors not found from my previous fix attempt

--- client/landing/app/Applications/Activity.kdapplication/activitylistcontroller.coffee
+++ client/landing/app/Applications/Activity.kdapplication/activitylistcontroller.coffee
@@ -92,9 +92,16 @@

     for overviewItem in cache.overview when overviewItem
       if overviewItem.ids.length > 1 and overviewItem.type is "CNewMemberBucketActivity"
+        anchors = []
+        for id in overviewItem.ids
+          if cache.activities[id].teaser?
+            anchors.push cache.activities[id].teaser.anchor
+          else
+            KD.logToExternal msg:'no teaser for activity', activityId:id
+
         @addItem new NewMemberBucketData
           type                : "CNewMemberBucketActivity"
-          anchors             : (cache.activities[id].teaser.anchor for id in overviewItem.ids)
+          anchors             : anchors
           count               : overviewItem.count
           createdAtTimestamps : overviewItem.createdAt
       else


Need to check it here

Need to check it here

--- client/landing/app/Applications/Topics.kdapplication/Views/TopicsListItemView.coffee
+++ client/landing/app/Applications/Topics.kdapplication/Views/TopicsListItemView.coffee
@@ -11,7 +11,7 @@
       pistachio   : '{{#(title)}}'
       click       : (pubInst, event) =>
         @titleReceivedClick()
-        event.stopPropagation()
+        event?.stopPropagation()
         no
     , data


payment: refactor GroupProductSettingsView

make it easy to reuse the product creation form

--- client/app/Applications/Dashboard.kdapplication/views/groupproductsettingsview.coffee
+++ client/app/Applications/Dashboard.kdapplication/views/groupproductsettingsview.coffee
@@ -3,36 +3,53 @@
   constructor: (options = {}, data) ->
     super options, data

-    group = @getData()
+    @setClass 'group-product-section'

-    @setClass "payment-settings-view"
+    @productsView = new GroupProductsView

-    @productCreateForm = new GroupProductCreateForm
+    @forwardEvent @productsView, 'DeleteRequested', 'Product'

-    @forwardEvent @productCreateForm, 'ProductCreateRequested'
+    @productsView.on 'CreateRequested', =>
+      @showCreateModal
+        productType       : 'product'
+        isOverageEnabled  : yes

-    @reloadButton = new KDButtonView
-      cssClass   : "product-button"
-      title      : "Reload"
-      callback   : =>
-        @emit 'ProductReloadRequested'
+    @plansView = new GroupPlansView

-    @productListController = new GroupProductListController
-      group     : group
-      itemClass : GroupProductListItem
-    # @controller.loadItems()
+    @plansView.on 'CreateRequested', =>
+      @showCreateModal
+        productType         : 'plan'
+        isRecurringOptional : no
+        isOverageEnabled    : no
+        placeholders        :
+          title             : 'e.g. "Gold Plan"'
+          description       : 'e.g. "2 VMs, and a tee shirt"'

-    @list = @productListController.getListView()
-    @list.on "DeleteItem", (code)=>
-      group.deleteProduct {code}, =>
-        @emit 'ProductReloadRequested'
+  showCreateModal: (options) ->
+
+    productType = options.productType ? 'product'
+
+    modal = new KDModalView
+      overlay       : yes
+      title         : "Create #{ productType }"
+
+    createForm = new GroupProductCreateForm options
+
+    modal.addSubView createForm
+
+    createForm.on 'CancelRequested', ->
+      modal.destroy()
+
+    createForm.on 'CreateRequested', (productData) =>
+      createEventName = "#{ productType.capitalize() }CreateRequested"
+      @emit createEventName, productData
+      modal.destroy()

   setProducts: (products) ->
-    @productListController.instantiateListItems products
+    @productsView.setProducts products

   pistachio: ->
     """
-    {{> @productCreateForm}}
-    {{> @reloadButton}}
-    {{> @productListController.getView()}}
+    {{> @productsView}}
+    {{> @plansView}}
     """


Forgot to reactivate some tests.

Forgot to reactivate some tests.

--- tests/LinkedList.spec.coffee
+++ tests/LinkedList.spec.coffee
@@ -50,7 +50,7 @@
     it "should create a list prepopulated with items of the passed array", ->
         validate linkedList3, 1, 2, 3, 4

-describe "Add node", ->
+describe "Add node", ->
     describe "at the end", ->
         linkedList = new LinkedList()
         it "should return the value added", ->
@@ -67,7 +67,7 @@
         it "should add items in order", ->
             fill linkedList2
             validate linkedList2, "item0", "item1", 5, 2, 9, 0, 12
-
+
     describe "using offset", ->
         linkedList = new LinkedList()
         it "should return the value added", ->
@@ -169,8 +169,8 @@
         expect(linkedList.get(4).value).toBe 12
         expect(linkedList.get(-1).value).toBe 12

-describe "indexOf", ->
-    xdescribe "starting at the beginning", ->
+describe "Find index of node", ->
+    describe "starting at the beginning", ->
         linkedList = new LinkedList()
         array = [1, 2, 3]
         it "returns -1 if the item isn't found", ->
@@ -203,20 +203,22 @@
             expect(linkedList3.indexOf null).toBe 1
     describe "starting at an arbitrary index", ->
         linkedList = new LinkedList()
-        xit "should return -1 for invalid positive index", ->
+        it "should return -1 for invalid positive index", ->
             expect(linkedList.indexOf 2, 0).toBe -1
             expect(linkedList.indexOf 2, 10).toBe -1
             fill linkedList
             expect(linkedList.indexOf 2, 99).toBe -1
-        xit "should return the correct value for a negative index", ->
+        it "should return the correct value for a negative index", ->
             expect(linkedList.indexOf 2, -99).toBe 1
             expect(linkedList.indexOf 0, -2).toBe 3
             linkedList.add 9
             expect(linkedList.indexOf 9, -3).toBe 5
-        xit "returns -1 if the item isn't found starting at the indicated index", ->
+            expect(linkedList.indexOf 9, -1).toBe 5
+            expect(linkedList.indexOf 9, 0).toBe 2
+        it "returns -1 if the item isn't found starting at the indicated index", ->
             expect(linkedList.indexOf 2, 2).toBe -1
             expect(linkedList.indexOf 5, 1).toBe -1
-        xit "returns the index of the item found", ->
+        it "returns the index of the item found", ->
             expect(linkedList.indexOf 9, 2).toBe 2
             expect(linkedList.indexOf 5, 0).toBe 0
             expect(linkedList.indexOf 12, 4).toBe 4
@@ -228,7 +230,3 @@
             expect(linkedList2.indexOf 5, -5).toBe 0
             expect(linkedList2.indexOf 12, -1).toBe 4
             expect(linkedList2.indexOf 0, -3).toBe 3
-
-
-
-


test for loading amd modules

test for loading amd modules

--- tests/test_loader_wd.coffee
+++ tests/test_loader_wd.coffee
@@ -1506,4 +1506,73 @@
             .sleep(DELAY)
             .title().should.eventually.become("fixed_64")
             .safeExecute("localforage.clear()")
-            .nodeify(done)+            .nodeify(done)
+
+    it 'loads modules of various AMD types', (done) ->
+        return @browser
+            .then ->
+                system = yaml.safeLoad("""
+                    index.html: |
+
+
+                                <title></title>
+
+
+
Testing

+
+
+                    app:
+                        a.js: |
+                            // amd/nodeps
+                            define({
+                                a: "a"
+                                });
+                        b.js: |
+                            // amd/factory
+                            define(function(require) {
+                                return "b" + require("./a").a
+                                });
+                        c.js: |
+                            // amd/rem
+                            define(function(require, exports, module) {
+                                module.exports = "c" + require("./b");
+                            });
+                        d.js: |
+                            // amd/deps
+                            define(["./c"], function(c) {
+                                return "d" + c;
+                                });
+                        e.js: |
+                            // amd/named
+                            define("e", ["./d"], function(d) {
+                                return "e" + d;
+                                });
+                        start.js: |
+                            // commonjs
+                            var loader = require("loader");
+                            var e = require("./e");
+                            loader.onApplicationReady = function() {
+                                document.title = e;
+                                };
+                        spa.yaml: |
+                            root: "./"
+                            index: "./index.html"
+                            manifest: "./manifest.json"
+                            hosting:
+                                "./(*.js)": "/app/$1"
+                    """)
+                try
+                    utils.mount(system, path.resolve(__dirname, "../lib/assets"))
+                    mock(system)
+                    spa.Builder.from_config("/app/spa.yaml").build()
+                catch e
+                    console.log e
+
+            .get('http://127.0.0.1:3332/')
+            .sleep(DELAY)
+            .clearLocalStorage()
+            .get('http://127.0.0.1:3332/app/')
+            .sleep(3*DELAY)
+            .title().should.eventually.become("edcba")
+            .safeExecute("localforage.clear()")
+            .nodeify(done)


Use correct resources path

Use correct resources path

--- build/tasks/build-task.coffee
+++ build/tasks/build-task.coffee
@@ -151,8 +151,8 @@
           grunt.file.copy(sourcePath, path.resolve(appDir, '..', subDirectory, filename))

     if process.platform is 'win32'
-      cp path.join('win', 'resources', 'atom.cmd'), path.join(shellAppDir, 'cli', 'atom.cmd')
-      cp path.join('win', 'resources', 'atom.js'), path.join(shellAppDir, 'cli', 'atom.js')
+      cp path.join('resources', 'win', 'atom.cmd'), path.join(shellAppDir, 'cli', 'atom.cmd')
+      cp path.join('resources', 'win', 'atom.js'), path.join(shellAppDir, 'cli', 'atom.js')

     dependencies = ['compile', 'generate-license:save', 'generate-module-cache', 'compile-packages-slug']
     dependencies.push('copy-info-plist') if process.platform is 'darwin'


Don't copy bootstrap docs during build

Don't copy bootstrap docs during build

--- build/tasks/build-task.coffee
+++ build/tasks/build-task.coffee
@@ -44,6 +44,7 @@
       path.join('oniguruma', 'deps')
       path.join('less', 'dist')
       path.join('less', 'test')
+      path.join('bootstrap', 'docs')
       path.join('vendor', 'apm')
       path.join('resources', 'mac')
       path.join('resources', 'win')


fix wrong bonus moves calculation

fix wrong bonus moves calculation

--- frontend/src/game.coffee
+++ frontend/src/game.coffee
@@ -157,8 +157,12 @@
         @board.drawHit()

     startMove: (field, event) =>
+        # we have to save multiplier before sending move to api server because
+        # it will be overwritten as soon as server will respond
+        @multiplier = @game.match.state['bonus-multiplier']
+        @game.match.postMove(field.row, field.col)
+
         # deactivate listening until animation is finished
-        @game.match.postMove(field.row, field.col)
         @listening(false)
         @game.moves -= 1
         @game.scoreDiff = 0
@@ -253,9 +257,9 @@
             @movePreviewToEmptyFields()

     movePreviewToEmptyFields: () ->
+        @game.match.beforeSync()
+
         # move preview field to empty places
-        @game.match.beforeSync()
-
         tweens = []
         previewIndex = 0
         for row in [0..@board.size-1]
@@ -355,10 +359,7 @@
         @game.score += @movePoints
         @game.scoreDiff = @movePoints

-        # multiplier depends on current score, more points you have then
-        # multiplier is smaller so longer path you have to create to get moves bonus
-        multiplier = @game.match.state['bonus-multiplier']
-        @game.movesDiff = Math.floor(@moveLength * multiplier)
+        @game.movesDiff = Math.floor(@moveLength * @multiplier)
         @game.moves += @game.movesDiff
         @topBarWidget.update()


[fix #87481536] changed to be not able to remove character when enabled disabled_new_character.

--- app/assets/javascripts/views/character_selector_view.js.coffee
+++ app/assets/javascripts/views/character_selector_view.js.coffee
@@ -46,7 +46,7 @@
       removeButton.click (e) =>
         e.preventDefault()
         @removeCharacter_(character)
-      if character.get('using')
+      if Smalruby.isEnabled('disabled_new_character') || character.get('using')
         removeButton.hide()

       img = html.find('img')
@@ -105,7 +105,7 @@
     @prevXY = newBlock.getRelativeToSurfaceXY()

   removeCharacter_: (character) ->
-    unless character.get('using')
+    if !Smalruby.isEnabled('disabled_new_character') && !character.get('using')
       Smalruby.Collections.CharacterSet.remove(character)

 }, {


Add `text.md` scope

Add `text.md` scope

--- lib/linter.coffee
+++ lib/linter.coffee
@@ -26,7 +26,7 @@

 module.exports = new class # This only needs to be a class to bind lint()

-  grammarScopes: ['source.gfm', 'source.pfm']
+  grammarScopes: ['source.gfm', 'source.pfm', 'text.md']
   scope: "file"
   lintOnFly: true

@@ -61,7 +61,7 @@
         fin = new Configuration {detectRC: true}
         conf = fin.getConfiguration filePath, (err, conf) ->
           if err
-            errorLoadingConfig(e, filePath).then(resolve, reject);
+            errorLoadingConfig(e, filePath).then(resolve, reject)
             return

           # Load processor for current path


don't use the reserved work 'return' as method name

--- spec/Mock.coffee
+++ spec/Mock.coffee
@@ -13,7 +13,7 @@
         returner[name] = (args...) =>
           {
             thenReturn: (returnValue) =>
-              this[name].return(returnValue).when(args...)
+              this[name].doReturn(returnValue).when(args...)
           }
       returner

@@ -33,7 +33,7 @@
     actualCall = calls[0]
     calls.splice(0,1)
     expect(actualCall).toEqual(args)
-  method.return = (returnValue) ->
+  method.doReturn = (returnValue) ->
     {
       when: (args...) ->
         #console.log("#{name}(#{args}) => #{returnValue}")


Updating hint.

Updating hint.

--- app/client.coffee
+++ app/client.coffee
@@ -302,7 +302,7 @@
 # draw default sized field
 drawField(default_geometry_field)

-#socket = io.connect('http://ssl-webclient.roboime.com:80/')
+#socket = io.connect('http://ssl-webclient.roboime.com:8888/')
 socket = io.connect()

 socket.on "ssl_packet", (packet) ->