Some sensible defaults

Some sensible defaults

--- src/builder.coffee
+++ src/builder.coffee
@@ -128,9 +128,8 @@
 		isArrayOf @elements, Expression

 class ArrayPattern extends Pattern
-	constructor: (elts, loc = null) ->
+	constructor: (@elements, loc = null) ->
 		super 'ArrayPattern', loc
-		@elements = elts
 		isArrayOf @elements, Pattern

 class ArrowExpression extends Expression
@@ -146,17 +145,15 @@
 		isA @expression, 'boolean'

 class AssignmentExpression extends Expression
-	constructor: (op, @left, @right, loc = null) ->
+	constructor: (@operator, @left, @right, loc = null) ->
 		super 'AssignmentExpression', loc
-		@operator = op
 		isLiterally @operator, AssignmentOperator
 		isA @left, Expression
 		isA @right, Expression

 class BinaryExpression extends Expression
-	constructor: (op, @left, @right, loc = null) ->
+	constructor: (@operator, @left, @right, loc = null) ->
 		super 'BinaryExpression', loc
-		@operator = op
 		isLiterally @operator, BinaryOperator
 		isA @left, Expression
 		isA @right, Expression
@@ -172,9 +169,8 @@
 		isNullOr @label, Identifier

 class CallExpression extends Expression
-	constructor: (@callee, args, loc = null) ->
+	constructor: (@callee, @arguments = [], loc = null) ->
 		super 'CallExpression', loc
-		@arguments = args
 		isA @callee, Expression
 		isArrayOf @arguments, Expression

@@ -202,10 +198,8 @@
 		isNullOr @filter, Expression

 class ConditionalExpression extends Expression
-	constructor: (@test, cons, alt, loc = null) ->
+	constructor: (@test, @consequent, @alternate, loc = null) ->
 		super 'ConditionalExpression', loc
-		@consequent = cons
-		@alternate = alt
 		isA @test, Expression
 		isA @consequent, Expression
 		isA @alternate, Expression
@@ -230,9 +224,8 @@
 		super 'EmptyStatement', loc

 class ExpressionStatement extends Statement
-	constructor: (expr, loc = null) ->
+	constructor: (@expression, loc = null) ->
 		super 'ExpressionStatement', loc
-		@expression = expr
 		isA @expression, Expression

 class ForStatement extends Statement
@@ -260,7 +253,7 @@
 		isA @body, Statement

 class FunctionDeclaration extends Declaration #, Function
-	constructor: (@id, @params, @defaults, @rest, @body, isGenerator = false, isExpression = false, loc = null) ->
+	constructor: (@id, @params = [], @defaults = [], @rest = null, @body, isGenerator = false, isExpression = false, loc = null) ->
 		super 'FunctionDeclaration', loc
 		@generator = isGenerator
 		@expression = isExpression
@@ -273,7 +266,7 @@
 		isA @expression, 'boolean'

 class FunctionExpression extends Expression #, Function
-	constructor: (@id, @params, @defaults, @rest, @body, isGenerator = false, isExpression = false, loc = null) ->
+	constructor: (@id = null, @params = [], @defaults = [], @rest = null, @body, isGenerator = false, isExpression = false, loc = null) ->
 		super 'FunctionExpression', loc
 		@generator = isGenerator
 		@expression = isExpression
@@ -298,10 +291,8 @@
 		isA @name, 'string'

 class IfStatement extends Statement
-	constructor: (@test, cons, alt, loc = null) ->
+	constructor: (@test, @consequent, @alternate = null, loc = null) ->
 		super 'IfStatement', loc
-		@consequent = cons
-		@alternate = alt
 		isA @test, Expression
 		isA @consequent, Statement
 		isNullOr @alternate, Statement
@@ -336,91 +327,78 @@
 		isNullOr @value, [ 'string', 'boolean', 'number', RegExp ]

 class LogicalExpression extends Expression
-	constructor: (op, @left, @right, loc = null) ->
+	constructor: (@operator, @left, @right, loc = null) ->
 		super 'LogicalExpression', loc
-		@operator = op
 		isLiterally @operator, LogicalOperator
 		isA @left, Expression
 		isA @right, Expression

 class MemberExpression extends Expression
-	constructor: (obj, prop, isComputed, loc = null) ->
+	constructor: (@object, @property, isComputed = false, loc = null) ->
 		super 'MemberExpression', loc
-		@object = obj
-		@property = prop
 		@computed = isComputed
 		isA @object, Expression
 		isOneOf @property, [ Identifier, Expression ]
 		isA @computed, 'boolean'

 class NewExpression extends Expression
-	constructor: (@callee, args, loc = null) ->
+	constructor: (@callee, @arguments = [], loc = null) ->
 		super 'NewExpression', loc
-		@arguments = args
 		isA @callee, Expression
 		isArrayOf @arguments, Expression

 class ObjectExpression extends Expression
-	constructor: (props, loc = null) ->
+	constructor: (@properties = [], loc = null) ->
 		super 'ObjectExpression', loc
-		@properties = props
 		isArrayOf @properties, Property

 class ObjectPattern extends Pattern
-	constructor: (props, loc = null) ->
+	constructor: (@properties = [], loc = null) ->
 		super 'ObjectPattern', loc
-		@properties = props
 		isArrayOf @properties, PropertyPattern

 class Program extends Node
-	constructor: (@body, loc = null) ->
+	constructor: (@body = [], loc = null) ->
 		super 'Program', loc
 		isArrayOf @body, Statement

 class Property extends Node
-	constructor: (@key, val, @kind, loc = null) ->
+	constructor: (@key, @value, @kind, loc = null) ->
 		super 'Property', loc
-		@value = val
 		isOneOf @key, [ Literal, Identifier ]
 		isA @value, Expression
 		isLiterally @kind, [ 'init', 'get', 'set' ]

 class PropertyPattern extends Node
-	constructor: (@key, patt, loc = null) ->
+	constructor: (@key, @value, loc = null) ->
 		super 'PropertyPattern', loc
-		@value = patt
 		isOneOf @key, [ Literal, Identifier ]
 		isA @value, Pattern

 class ReturnStatement extends Statement
-	constructor: (arg, loc = null) ->
+	constructor: (@argument, loc = null) ->
 		super 'ReturnStatement', loc
-		@argument = arg
 		isNullOr @argument, Expression

 class SequenceExpression extends Expression
-	constructor: (exprs, loc = null) ->
+	constructor: (@expressions, loc = null) ->
 		super 'SequenceExpression', loc
-		@expressions = exprs
 		isArrayOf @expressions, Expression

 class SpreadExpression extends Expression
-	constructor: (argument, loc = null) ->
+	constructor: (@argument, loc = null) ->
 		super 'SpreadExpression', loc
-		@argument = argument
 		isA @argument, Expression

 class SwitchCase extends Node
-	constructor: (@test, cons, loc = null) ->
+	constructor: (@test, @consequent = [], loc = null) ->
 		super 'SwitchCase', loc
-		@consequent = cons
 		isNullOr @test, Expression
 		isArrayOf @consequent, Statement

 class SwitchStatement extends Statement
-	constructor: (disc, @cases, isLexical, loc = null) ->
+	constructor: (@discriminant, @cases, isLexical, loc = null) ->
 		super 'SwitchStatement', loc
-		@discriminant = disc
 		@lexical = isLexical
 		isA @discriminant, Expression
 		isArrayOf @cases, SwitchCase
@@ -431,50 +409,42 @@
 		super 'ThisExpression', loc

 class ThrowStatement extends Statement
-	constructor: (arg, loc = null) ->
+	constructor: (@argument, loc = null) ->
 		super 'ThrowStatement', loc
-		@argument = arg
 		isA @argument, Expression

 class TryStatement extends Statement
-	constructor: (@body, @handler, fin, loc = null) ->
+	constructor: (@body, @handler, @finalizer, loc = null) ->
 		super 'TryStatement', loc
-		@finalizer = fin
 		isA @body, Statement
 		isNullOr @handler, CatchClause
 		isNullOr @finalizer, Statement

 class UnaryExpression extends Expression
-	constructor: (op, arg, isPrefix, loc = null) ->
+	constructor: (@operator, @argument, isPrefix, loc = null) ->
 		super 'UnaryExpression', loc
-		@operator = op
-		@argument = arg
 		@prefix = isPrefix
 		isLiterally @operator, UnaryOperator
 		isA @argument, Expression
 		isA @prefix, 'boolean'

 class UpdateExpression extends Expression
-	constructor: (op, arg, isPrefix, loc = null) ->
+	constructor: (@operator, @argument, isPrefix, loc = null) ->
 		super 'UpdateExpression', loc
-		@operator = op
-		@argument = arg
 		@prefix = isPrefix
 		isLiterally @operator, UpdateOperator
 		isA @argument, Expression
 		isA @prefix, 'boolean'

 class VariableDeclaration extends Declaration
-	constructor: (@kind, dtors, loc = null) ->
+	constructor: (@kind, @declarations, loc = null) ->
 		super 'VariableDeclaration', loc
-		@declarations = dtors
 		isA @kind, 'string'
 		isArrayOf @declarations, VariableDeclarator

 class VariableDeclarator extends Node
-	constructor: (patt, @init = null, loc = null) ->
+	constructor: (@id, @init = null, loc = null) ->
 		super 'VariableDeclarator', loc
-		@id = patt
 		isA @id, Pattern
 		isNullOr @init, Expression

@@ -492,9 +462,8 @@
 		isA @body, Statement

 class YieldExpression extends Expression
-	constructor: (arg, loc = null) ->
+	constructor: (@argument, loc = null) ->
 		super 'YieldExpression', loc
-		@argument = arg
 		isNullOr @argument, Expression

 Properties =


Remove comments

Remove comments

--- code/type-null-true-false.coffee
+++ code/type-null-true-false.coffee
@@ -41,10 +41,10 @@
 length_value(values)

 # "if value":
-# 0 - false <---!
+# 0 - false
 # 5 - true
 # 'string' - true
-# '' - false <---!
+# '' - false
 # [1, 2, 3] - true
 # [] - true
 # true - true
@@ -60,7 +60,7 @@
 # [1, 2, 3] - true
 # [] - true
 # true - true
-# false - true <---!
+# false - true
 # null - false
 # undefined - false
 #


Add in change to actually render <script> tag contents

--- coffee/components/preview.coffee
+++ coffee/components/preview.coffee
@@ -1,4 +1,5 @@
-
+_ = require "underscore"
+$ = require "jquery"
 React = require "react"
 {div, span} = React.DOM
 marked = require "marked"
@@ -18,16 +19,22 @@
     content: "Loading…"

   componentDidMount: ->
-    console.log "Card.componentDidMount fired"
+    @rerender = no
     @props.card.on "change", =>
-      console.log "change fired"
       @renderCard()
     @renderCard()
+
+  componentDidUpdate: ->
+    _.each @getDOMNode().getElementsByTagName("script"), (script) =>
+      if @rerender
+        eval script.innerHTML
+        @rerender = no
+

   renderCard: ->
     @props.card.render()
       .then (content) =>
-        console.log "got rendered content back: #{content}"
+        @rerender = true
         @setState content: content

   render: ->


Use Adler-32-style hash

Use Adler-32-style hash

--- src/cli/zog.coffee
+++ src/cli/zog.coffee
@@ -2,16 +2,18 @@
 Running copy of myself in background
 ###

-hash = (s)->
-  n = 0
+adler32 = (s)->
+  a = 1
+  b = 0
   i = s.length
   while i--
-    n = ~(n + (i & 0xFF ^ s.charCodeAt i))
-  n & 0xFFFF
+    a = (a + s.charCodeAt i) % 65521
+    b = (b + a) % 65521
+  b << 16 + a

 # Magic cookie
 magic =
-  "<#{hash do argv0.load}>"
+  "<#{adler32 do argv0.load}>"

 find = (cmd)->
   require('./cmdz')[cmd]?.z


Clean up string replacement

Clean up string replacement

--- services/web/public/coffee/ide/editor/directives/aceEditor/spell-check/SpellCheckManager.coffee
+++ services/web/public/coffee/ide/editor/directives/aceEditor/spell-check/SpellCheckManager.coffee
@@ -253,7 +253,10 @@

 		blankOutBlacklistedCommands: (line) ->
 			line.replace /\\(label|ref|usepackage|begin|end)(\[[^\]]*\])?{[^}]*}/g, (command) ->
-				command = command.replace /{.*}/, (args) ->
-					'{' + args.slice(1, args.length-1).split('').map((_char)-> '.').join('') + '}'
-				command.replace /\[.*\]/, (args) ->
-					'[' + args.slice(1, args.length-1).split('').map((_char)-> '.').join('') + ']'
+				command.replace(
+					/{.*}/, (args) ->
+						'{' + args.slice(1, args.length-1).split('').map((_char)-> '.').join('') + '}'
+				).replace(
+					/\[.*\]/, (args) ->
+						'[' + args.slice(1, args.length-1).split('').map((_char)-> '.').join('') + ']'
+				)


Chart update

Chart update

--- site/app.coffee
+++ site/app.coffee
@@ -558,7 +558,7 @@
     # x-ticks (only for weeks 20 and 40)
     for i in (i for i in [0...numWeeks - 10]).concat([numWeeks - 1])
       wk = (@chartData[i].epiweek % 100)
-      if wk == 20 or wk == 40
+      if wk == 20 or wk == 40 or i == (numWeeks - 1)
         x = i2x(i)
         trace([x, x], [h - padding.bottom, h - (padding.bottom - 6)])
         yr = (Math.round(@chartData[i].epiweek / 100) % 100)
@@ -619,7 +619,7 @@
       ctx.stroke()
     ctx.font = 24 * Math.min(1, w / 500) + 'px sans-serif'
     name = NAMES[@chartData[0].location]
-    write("Historial Nowcasts for #{name}", w / 2, padding.top / 2, 0)
+    write("Historical Nowcasts(out-of-sample) for #{name}", w / 2, padding.top / 2, 0)

   hitTest: (u, v) ->
     for loc in @locations
@@ -667,7 +667,7 @@
       ili = ili.slice(0, idx + 3)
     else
       ili += '.00'
-    epiweek = current.epiweek
+    epiweek = Math.round(current.epiweek/100) + "w" + (current.epiweek%100)
     @chartData = epidata
     $('#nowcast_label').text("ILI nowcast for #{loc} as of #{epiweek}:")
     $('#nowcast_value').text("#{ili}%")


Remove useless semicolon

Remove useless semicolon

--- siteshot.coffee
+++ siteshot.coffee
@@ -54,7 +54,7 @@
                       if (typeof config.pageModifier is 'function')
                         config.pageModifier(page, ->
                           generateHTML()
-                        );
+                        )
                       else
                         generateHTML()
                     ), config.delay or 0


clear the canvas before redrawing

clear the canvas before redrawing

--- dramagrama.coffee
+++ dramagrama.coffee
@@ -17,6 +17,8 @@
 				allTheBlockPairs[blockPair.first] = [blockPair]

 		@drawer = new Drawer
+		paper.clear()
+
 		startPoint = new Point 50, 10;

 		# keep track of all the blocks that we've drawn


Make audio/aac to request aac instead of ogg

--- frontend/script.coffee
+++ frontend/script.coffee
@@ -1092,7 +1092,7 @@
   audio = new Audio();
   playbackType = null
   if (audio.canPlayType("audio/aac"))
-    playbackType = new PlaybackType "ogg", "audio/aac"
+    playbackType = new PlaybackType "aac", "audio/aac"
   else if (audio.canPlayType("audio/ogg"))
     playbackType = new PlaybackType "ogg", "audio/ogg"
   else if (audio.canPlayType("audio/mpeg"))


на карте отображается маркер у каждого места из базы

--- app/assets/javascripts/map.coffee
+++ app/assets/javascripts/map.coffee
@@ -14,14 +14,20 @@
       navigator.geolocation.getCurrentPosition (position) ->
         initialLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude)
         map_object.setCenter initialLocation
-        marker = new google.maps.Marker({
+        new google.maps.Marker
           position: initialLocation
-          map: map_object,
-          title: 'Click to zoom'
-        })
+          map: map_object
+

   init: ->
     #запуск карты
     map_object = new google.maps.Map(@.map_dom, @.map_options)
     @.nav_geolocation(map_object)
-    console.log gon.places
+
+    outputItem = (item) ->
+      console.log item.lat
+      new google.maps.Marker
+        position: new google.maps.LatLng(item.lat, item.lng)
+        map: map_object
+
+    gon.places.forEach outputItem


bugfix: display do-you-see-a-transit after next lightcurve loads

--- app/controllers/classifier.coffee
+++ app/controllers/classifier.coffee
@@ -138,7 +138,7 @@
       @el.find(".noUi-handle").hide()

     @insertMetadata()
-    @el.find('.do-you-see-a-transit')
+    @el.find('.do-you-see-a-transit').fadeIn()
     @el.find('#no-transits').fadeIn() #prop('disabled',false)
     @el.find('#finished-marking').fadeIn() #prop('disabled',false)
     @el.find('#finished-feedback').fadeIn() #prop('disabled',false)


Propagate nestingDepth in MakeObject

Propagate nestingDepth in MakeObject

--- drivers/javascript/ast.coffee
+++ drivers/javascript/ast.coffee
@@ -447,13 +447,13 @@
     tt: protoTermType.MAKE_OBJECT
     st: '{...}' # This is only used by the `undefined` argument checker

-    constructor: (obj) ->
+    constructor: (obj, nestingDepth=20) ->
         self = super({})
         self.optargs = {}
         for own key,val of obj
             if typeof val is 'undefined'
                 throw new err.RqlDriverError "Object field '#{key}' may not be undefined"
-            self.optargs[key] = rethinkdb.expr val
+            self.optargs[key] = rethinkdb.expr val, nestingDepth-1
         return self

     compose: (args, optargs) -> kved(optargs)
@@ -1031,7 +1031,7 @@
     else if typeof(val) is 'number'
         new DatumTerm val
     else if Object::toString.call(val) is '[object Object]'
-        new MakeObject val
+        new MakeObject val, nestingDepth
     else
         new DatumTerm val


Reuse `timeout` and `authKey` when reconnecting JS.

--- drivers/javascript/net.coffee
+++ drivers/javascript/net.coffee
@@ -233,7 +233,8 @@
             closeCb = (err) =>
                 @rawSocket.removeAllListeners()
                 @rawSocket = null # The rawSocket has been closed
-                @constructor.call @, {host:@host, port:@port}, (err, conn) ->
+                @constructor.call @, {host:@host, port:@port
+                                      timeout:@timeout, authKey:@authKey}, (err, conn) ->
                     if err?
                         reject err
                     else


fixing herecomment/indentation bugaboo ... issue #474

--- rewriter.coffee
+++ rewriter.coffee
@@ -63,13 +63,11 @@
           @tokens.splice i, 0, after
       else if prev and prev[0] not in ['TERMINATOR', 'INDENT', 'OUTDENT']
         if post and post[0] is 'TERMINATOR' and after and after[0] is 'OUTDENT'
-          @tokens.splice(i, 0, @tokens.splice(i + 2, 2)...)
+          @tokens.splice(i + 3, 0, @tokens.splice(i, 2)...)
+          @tokens.splice(i + 3, 0, ['TERMINATOR', "\n", prev[2]])
         else
           @tokens.splice i, 0, ['TERMINATOR', "\n", prev[2]]
         return 2
-      else if before and before[0] is 'OUTDENT' and prev and prev[0] is 'TERMINATOR' and
-              post and post[0] is 'TERMINATOR' and after and after[0] is 'ELSE'
-          @tokens.splice i + 1, 0, @tokens.splice(i - 2, 1)[0]
       return 1

   # Leading newlines would introduce an ambiguity in the grammar, so we


in console, add space after selecting command by Enter

--- app/js/controllers/console.coffee
+++ app/js/controllers/console.coffee
@@ -7,7 +7,7 @@
             for s in response.result
                 # filter bitcoin apis
                 if !((s[0].indexOf "bitcoin") == 0)
-                    ConsoleState.states.push s[0]
+                    ConsoleState.states.push s[0] + " "

     if ConsoleState.outputs.length == 0
         RpcService.request('execute_command_line', ['help']).then (response) =>


Removed debug info

Removed debug info

--- app/js/publisher_poc/nu.nl.coffee
+++ app/js/publisher_poc/nu.nl.coffee
@@ -16,7 +16,6 @@
   factlink_publisher.addFactlinkButtons()

   FACTLINK.on 'factlink.factsLoaded', (facts) ->
-    console.info "FACTS: ", facts
     ui = new UI
     ui.updateFactsCount facts.length
     ui.bindActions()


Fixed bobbing.

Fixed bobbing.

--- app/lib/surface/CocoSprite.coffee
+++ app/lib/surface/CocoSprite.coffee
@@ -234,7 +234,7 @@
     return unless @thang?.pos and @options.camera?
     wop = @getWorldPosition()
     [p0, p1] = [@lastPos, @thang.pos]
-    return if p0 and p0.x is p1.x and p0.y is p1.y and p0.z is p1.z and not @options.camera.tweeningZoomTo
+    return if p0 and p0.x is p1.x and p0.y is p1.y and p0.z is p1.z and not @options.camera.tweeningZoomTo and not @thang.bobHeight
     sup = @options.camera.worldToSurface wop
     [@displayObject.x, @displayObject.y] = [sup.x, sup.y]
     @lastPos = p1.copy?() or _.clone(p1)


Get rid of updateAssociations method

Get rid of updateAssociations method

It seems that with current version of ember-data it's not longer needed
- associations are updated automatically now.

--- assets/scripts/app/store.coffee
+++ assets/scripts/app/store.coffee
@@ -140,8 +140,6 @@
     result = @merge(type, hash, true)
     if result && result.clientId
       @addLoadedData(type, result.clientId, hash)
-    # TODO: it will be probably needed to uncomment and fix this
-    #@_updateAssociations(type, type.singularName(), hash)

     result

@@ -159,14 +157,3 @@
     root = type.pluralName()
     @adapter.sideload(store, type, json, root)
     @loadMany(type, json[root])
-
-  _updateAssociations: (type, name, data) ->
-    Em.get(type, 'associationsByName').forEach (key, meta) =>
-      if meta.kind == 'belongsTo'
-        id = data["#{key}_id"]
-        if clientId = @typeMapFor(meta.type).idToCid[id]
-          if parent = this.findByClientId(meta.type, clientId, id)
-            dataProxy = parent.get('data')
-            if ids = dataProxy.get("#{name}_ids")
-              ids.pushObject(data.id) unless data.id in ids
-              parent.send('didChangeData');


sidebar: Added bound method

sidebar: Added bound method

--- client/activity/lib/components/threadsidebar/index.coffee
+++ client/activity/lib/components/threadsidebar/index.coffee
@@ -40,7 +40,7 @@

   renderKdSection: ->
-    <Link className='show-kd-modal' onClick={@showKdModal}>
+    <Link className='show-kd-modal' onClick={@bound 'showKdModal'}>
       New! Use your local IDEs with Koding VMs
     </Link>


Add comment to ActivityBaseListItemView.coffee

--- client/activity/lib/views/activitybaselistitemview.coffee
+++ client/activity/lib/views/activitybaselistitemview.coffee
@@ -25,6 +25,7 @@
     { scrollHeight } = article
     { height }       = article.getBoundingClientRect()

+    # Subtract 12 unit for margin-bottom's difference.
     if scrollHeight - 12 > height

       @showMore?.destroy()


Client: VMSettings: Using KodingListController instead of KDListViewController and deleted unnecessary options

--- client/app/lib/providers/machinesettingscommonview.coffee
+++ client/app/lib/providers/machinesettingscommonview.coffee
@@ -6,10 +6,9 @@
 KDListItemView       = kd.ListItemView
 KDCustomHTMLView     = kd.CustomHTMLView
 KDHitEnterInputView  = kd.HitEnterInputView
-KDListViewController = kd.ListViewController
+KodingListController = require 'app/kodinglist/kodinglistcontroller'

 module.exports = class MachineSettingsCommonView extends KDView
-

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

@@ -27,7 +26,6 @@
     @machine = @getData()

     @createElements()
-    @initList()

   createElements: ->
@@ -120,17 +118,13 @@
     listViewOptions = @getOption('listViewOptions') or {}

     options = _.extend listViewOptions,
-      startWithLazyLoader   : yes
-      lazyLoaderOptions     :
-        spinnerOptions      :
-          size              : { width: 28 }
       viewOptions           :
         wrapper             : yes
-        itemClass           : listViewItemClass
         itemOptions         : itemOptions
+      itemClass             : listViewItemClass
       noItemFoundWidget     : noItemFoundWidget

-    @listController  = new KDListViewController options
+    @listController  = new KodingListController options

     @addSubView @listController.getView()


PR #6: Use first 6 chars of hash

PR #6: Use first 6 chars of hash

--- generate-report.coffee
+++ generate-report.coffee
@@ -136,7 +136,7 @@
     return function() {
       var chart = nv.models.lineChart()
         .useInteractiveGuideline(true)
-        .margin({left: 100, right: 50, bottom: 200})
+        .margin({left: 100, right: 50, bottom: 100})
       ;

       chart.xAxis
@@ -220,11 +220,13 @@
 hashTickMap = {}
 nextTick = 0

+subHash = (hash) -> "#{hash?[...6]}..."
+
 mapGitCommitHash = (hash) ->
   if hashHashMap[hash]? then return hashHashMap[hash]

   hashHashMap[hash] = nextTick
-  hashTickMap[nextTick] = hash
+  hashTickMap[nextTick] = subHash hash
   nextTick++
   return hashHashMap[hash]

@@ -297,7 +299,6 @@
                   series.push
                     x: mapGitCommitHash r.gitCommitHash
                     y: r["#{metric}"]
-                    hash: r.gitCommitHash

               if c is 'BasicGET100'
                 pushResults benchmarkResults.basicGET100TimeSeries, 'totalTimeSeconds', results


sync atom

sync atom

--- dotfiles/.atom/config.cson
+++ dotfiles/.atom/config.cson
@@ -25,5 +25,7 @@
     cargoCommand: "check"
   minimap: {}
   "one-dark-ui": {}
+  "standard-formatter":
+    formatOnSave: true
   welcome:
     showOnStartup: false


Make dp_sbory optional

Make dp_sbory optional

--- server/materials/data/topics/dp_sbory.coffee
+++ server/materials/data/topics/dp_sbory.coffee
@@ -7,7 +7,7 @@

 export default dp_sbory = () ->
     return {
-        topic: topic("*Доп. задачи на ДП", "Дополнительные задачи на ДП", [
+        topic: topic("*Доп. задачи на ДП", "*Дополнительные задачи на ДП", [
             label("Это задачи на ДП с зимних сборов алгопрога 2021. Раздел не обязательный. Сложность задач очень разная.")
             problem(498),
             problem(44),


activity: remove duplicate "Add System Tag" menu definition

--- client/Social/Activity/views/settingsview.coffee
+++ client/Social/Activity/views/settingsview.coffee
@@ -30,10 +30,6 @@
           callback: => @emit 'ActivityEditIsClicked'
         menu['Delete Post'] =
           callback: => @confirmDeletePost post
-
-      if KD.checkFlag("super-admin") or KD.hasAccess("delete posts")
-        menu['Add System Tag'] =
-          callback : => @selectSystemTag post

     if KD.checkFlag("super-admin") or KD.hasAccess("delete posts")
       if KD.checkFlag 'exempt', account


SettingsMenu: Add ownermenu for admins

SettingsMenu: Add ownermenu for admins

--- client/Social/Activity/views/settingsview.coffee
+++ client/Social/Activity/views/settingsview.coffee
@@ -57,7 +57,7 @@

     post = @getData()

-    return @menu  unless KD.checkFlag('super-admin')
+    @addOwnerMenu()

     {activityController} = KD.singletons

@@ -89,7 +89,7 @@

     @addFollowActionMenu()
     @addOwnerMenu()  if KD.isMyPost @getData()
-    @addAdminMenu()
+    @addAdminMenu()  if KD.checkFlag('super-admin')

     return @menu


GroupStackSettings: separate methods, add and update stack template of group

We know able to create and assign the stack template into the group settings
Which allowing incoming users to have a new stack created from this assigned
template [#92919864]

--- client/admin/lib/views/groupstacksettings.coffee
+++ client/admin/lib/views/groupstacksettings.coffee
@@ -2,10 +2,27 @@

 remote         = require('app/remote').getInstance()
 FSHelper       = require 'app/util/fs/fshelper'
+applyMarkdown  = require 'app/util/applyMarkdown'
 IDEEditorPane  = require 'ide/workspace/panes/ideeditorpane'
+Encoder        = require 'htmlencode'

 module.exports = class GroupStackSettings extends kd.View

+  # This will be used if stack template is not defined yet
+  defaultTemplate = """
+    provider "aws" {
+        access_key = "${var.access_key}"
+        secret_key = "${var.secret_key}"
+        region = "us-east-1"
+    }
+
+    resource "aws_instance" "example" {
+        count = 2
+        ami = "ami-25773a24"
+        instance_type = "t1.micro"
+    }
+  """
+
   constructor: (options = {}, data) ->

     options.cssClass = 'group-stack-settings'
@@ -13,108 +30,200 @@
     super options, data

+  fetchData: (callback)->
+
+    { groupsController }            = kd.singletons
+    { JCredential, JStackTemplate } = remote.api
+
+    JCredential.some {}, { limit: 30 }, (err, credentials) ->
+
+      return callback {message: 'Failed to fetch credentials:', err}  if err
+
+      currentGroup = groupsController.getCurrentGroup()
+
+      if not currentGroup.stackTemplates?.length > 0
+        callback null, {credentials}
+        return
+
+      {stackTemplates} = currentGroup
+      stackTemplateId  = stackTemplates.first # TODO support multiple templates
+
+      JStackTemplate.some
+        _id   : stackTemplateId
+      , limit : 1
+      , (err, stackTemplate)->
+
+          if err
+            console.warn 'Failed to fetch stack template:', err
+            callback null, {credentials}
+          else
+            stackTemplate = stackTemplate.first
+            stackTemplate.template = Encoder.htmlDecode stackTemplate.template
+
+            callback null, {credentials, stackTemplate}
+
+
+  createEditorPane: (content) ->
+
+    file = FSHelper.createFileInstance path: 'localfile:/stack.yml'
+
+    @addSubView editorContainer = new kd.View
+    editorContainer.setCss height: '240px'
+
+    editorContainer.addSubView @editorPane = new IDEEditorPane {
+      file, content, delegate: this
+    }
+
+    @editorPane.setCss background: 'black'
+
+
+  createCredentialsBox: (credentials) ->
+
+    creds = ({title: c.title, value: c.publicKey} for c in credentials)
+
+    @addSubView new kd.LabelView
+      title: "Select credential to use:"
+
+    @addSubView @credentialBox = new kd.SelectBox
+      name          : "credential"
+      selectOptions : creds
+
+  createOutputView: ->
+
+    @outputView = new kd.View
+    @outputView.setCss height: 'auto'
+
+    @addSubView @outputView
+
+
   viewAppended: ->

     kd.singletons.appManager.require 'IDE', =>

-      file = FSHelper.createFileInstance path: 'localfile:/stack.yml'
-      content = """
-        provider "aws" {
-            access_key = "${var.access_key}"
-            secret_key = "${var.secret_key}"
-            region = "us-east-1"
-        }
-
-        resource "aws_instance" "example" {
-            count = 2
-            ami = "ami-25773a24"
-            instance_type = "t1.micro"
-        }
-      """
-
-      @addSubView editorContainer = new kd.View
-      editorContainer.setCss height: '240px'
-
-      editorContainer.addSubView editorPane  = new IDEEditorPane {
-        file, content, delegate: this
-      }
-
-      editorPane.setCss background: 'black'
-
-      { JCredential } = remote.api
-
-      JCredential.some {}, { limit: 30 }, (err, credentials)=>
+      @fetchData (err, data) =>

         return console.warn err  if err

-        credentials = ({title: c.title, value: c.publicKey} for c in credentials)
-
-        @addSubView new kd.LabelView
-          title: "Select credential to use:"
-
-        @addSubView credentialBox = new kd.SelectBox
-          name          : "credential"
-          selectOptions : credentials
-
-        output = new kd.View
-        output.setCss height: 'auto'
-
-        @addSubView new kd.ButtonView
+        {credentials, stackTemplate} = data
+
+        @createEditorPane stackTemplate?.template or defaultTemplate
+        @createCredentialsBox credentials
+
+        @addSubView @saveButton = new kd.ButtonView
           title    : 'Set as default stack'
           loader   : yes
-          callback : ->
-
-            terraformContext = editorPane.getValue()
-            publicKeys = {aws: credentialBox.getValue()}
-
-            console.log {terraformContext, publicKeys}
-
-            { computeController } = kd.singletons
-
-            computeController.getKloud()
-
-              .checkPlan {terraformContext, publicKeys}
-
-              .then (res) ->
-
-                # An example of a valid stack template
-                # ------------------------------------
-                # machines: [
-                #   {
-                #     "label" : "koding-vm-0",
-                #     "provider" : "koding",
-                #     "instanceType" : "t2.micro",
-                #     "provisioners" : [
-                #         "devrim/koding-base"
-                #     ],
-                #     "region" : "us-east-1",
-                #     "source_ami" : "ami-a6926dce"
-                #   }
-                # ],
-
-                out = machines: []
-
-                {machines} = res
-
-                for machine, index in machines
-
-                  {instance_type, ami} = machine.attributes
-
-                  out.machines.push {
-                    label        : "aws-#{index}" # TODO we need this from kloud
-                    provider     : 'amazon'       # TODO we have now aws and amaon ~ GG
-                    source_ami   : ami
-                    instanceType : instance_type
-                    provisioners : []             # TODO what are we going to do with provisioners? ~ GG
-                    region       : 'us-east-1'    # TODO we need this from kloud ~ GG
-                  }
-
-                console.log "WOHOOO RES::", res, out
-
-              .catch (err) ->
-                console.warn "WOJOOO BOM ERR::", err
-
-              .finally =>
-                @hideLoader()
-
-        @addSubView output
+          callback : =>
+            @setStack stackTemplate
+
+        @createOutputView()
+
+
+  setStack: (stackTemplate) ->
+
+    terraformContext = @editorPane.getValue()
+    publicKeys = aws : @credentialBox.getValue()
+
+    console.log {terraformContext, publicKeys}
+
+    { computeController } = kd.singletons
+
+    computeController.getKloud()
+
+      .checkPlan {terraformContext, publicKeys}
+
+      .then (response) =>
+
+        machines = @parseTerraformOutput response
+        @outputView.updatePartial applyMarkdown "
+          ```json\n#{JSON.stringify machines, null, 2}\n```
+        "
+
+        @updateStackTemplate {
+          template: terraformContext
+          stackTemplate, publicKeys, machines
+        }
+
+      .catch   @bound 'showError'
+      .finally @saveButton.bound 'hideLoader'
+
+
+  showError: (err) ->
+
+    @outputView.updatePartial applyMarkdown """
+      Failed to parse template:
+
+      ```json\n#{err}\n```
+    """
+
+    console.warn "ERROR:", err
+
+
+  updateStackTemplate: (data)->
+
+    { template, publicKeys, machines, stackTemplate } = data
+
+    { JCredential, JStackTemplate } = remote.api
+
+    credentials = [publicKeys.aws] # TODO Make it work with other providers ~ GG
+
+    if stackTemplate
+      console.log ">>>>>", stackTemplate
+      stackTemplate.update {machines, template, credentials}, (err) =>
+        return @showError err  if err
+        @setGroupTemplate stackTemplate
+    else
+      JStackTemplate.create {
+        title : "Default stack template"
+        template, machines, credentials
+      }, (err, stackTemplate) =>
+        return @showError err  if err
+        @setGroupTemplate stackTemplate
+
+
+  setGroupTemplate: (stackTemplate) ->
+
+    { groupsController } = kd.singletons
+    currentGroup = groupsController.getCurrentGroup()
+    currentGroup.modify stackTemplates: [ stackTemplate._id ], (err) =>
+      return @showError err  if err
+
+
+  parseTerraformOutput: (response) ->
+
+    # An example of a valid stack template
+    # ------------------------------------
+    # title: "Default stack",
+    # description: "Koding's default stack template for new users",
+    # machines: [
+    #   {
+    #     "label" : "koding-vm-0",
+    #     "provider" : "koding",
+    #     "instanceType" : "t2.micro",
+    #     "provisioners" : [
+    #         "devrim/koding-base"
+    #     ],
+    #     "region" : "us-east-1",
+    #     "source_ami" : "ami-a6926dce"
+    #   }
+    # ],
+
+    out = machines: []
+
+    {machines} = response
+
+    for machine, index in machines
+
+      {instance_type, ami} = machine.attributes
+
+      out.machines.push {
+        label        : "aws-#{index}" # TODO we need this from kloud
+        provider     : 'amazon'       # TODO we have now aws and amaon ~ GG
+        source_ami   : ami
+        instanceType : instance_type
+        provisioners : []             # TODO what are we going to do with provisioners? ~ GG
+        region       : 'us-east-1'    # TODO we need this from kloud ~ GG
+      }
+
+    console.log "WOHOOO RES::", response, out
+
+    return out.machines


Use faster fadeTime

Use faster fadeTime

Otherwise you see the factwheel coming through the popup.

@eamon has a better fix in mind.

--- core/app/backbone/views/evidence/vote_up_down_view.coffee
+++ core/app/backbone/views/evidence/vote_up_down_view.coffee
@@ -69,7 +69,7 @@
     @popoverAdd selector,
       side: 'right'
       align: 'top'
-      fadeTime: 100
+      fadeTime: 40
       contentView: @bound_popup_view view_klass

   bound_popup_view: (view_klass) ->


Clear cached views on update

Clear cached views on update

--- lib/changes/changes-view.coffee
+++ lib/changes/changes-view.coffee
@@ -17,7 +17,7 @@
     @update()

   update: ->
-    @statusListView.update()
+    @el.trigger('index-updated')

   getTitle: ->
     'Commit changes'


:bug: Fix color markers not synced with editor scroll

When the editor use tiles the scrolling is no longer done at the lines
level, so the pigments markers won’t scroll in sync with the tiles.

Fixes #25

--- lib/color-buffer-element.coffee
+++ lib/color-buffer-element.coffee
@@ -33,12 +33,17 @@
   setModel: (@colorBuffer) ->
     {@editor} = @colorBuffer
     @editorElement = atom.views.getView(@editor)
+    @editorIsUsingTiles = @editorElement.shadowRoot.querySelector('.tile')?

     @colorBuffer.initialize().then => @updateMarkers()

     @subscriptions.add @colorBuffer.onDidUpdateColorMarkers => @updateMarkers()
     @subscriptions.add @colorBuffer.onDidDestroy => @destroy()
-    @subscriptions.add @editor.onDidChangeScrollTop => @updateMarkers()
+    @subscriptions.add @editor.onDidChangeScrollTop (scrollTop) =>
+      if @editorIsUsingTiles
+        @style.webkitTransform = "translate3d(0, #{-scrollTop}px, 0)"
+
+      @updateMarkers()

     @subscriptions.add @editor.onDidAddCursor =>
       @requestSelectionUpdate()


Allow scoring comparison across datasets

--- client/src/scripts/scoring-selection-view.coffee
+++ client/src/scripts/scoring-selection-view.coffee
@@ -10,7 +10,6 @@
     return 'Remove pending scorings from your selection.' if some selections, (selection) -> not selection.isReady()
     return 'Remove failed scorings from your selection.' if some selections, (selection) -> selection.hasFailed()
     return 'Remove comparison tables from your selection.' if some selections, (selection) -> selection.type is 'comparison'
-    return 'Ensure that all selected scorings refer to conforming datasets.' unless valuesAreEqual selections, (selection) -> selection.data.input.frameKey
     return 'Ensure that all selected scorings belong to the same model category.' unless valuesAreEqual selections, (selection) -> selection.data.input.model.model_category
     return 'Ensure that all selected scorings refer to the same response column.' unless valuesAreEqual selections, (selection) -> selection.data.input.model.response_column_name


improve user name sorting

improve user name sorting

--- client/views/common/shiftModal/shiftModal.coffee
+++ client/views/common/shiftModal/shiftModal.coffee
@@ -8,9 +8,15 @@
 		participants.sort (a, b) ->
 			if a.thisTeamleader then -1
 			else if b.thisTeamleader then 1
-			else if a.name < b.name then -1
-			else if a.name > b.name then 1
-			else 0
+			else
+				aSplit = a.name.split(' ')
+				bSplit = b.name.split(' ')
+
+				if aSplit[aSplit.length-1] < bSplit[bSplit.length-1] then -1
+				else if aSplit[aSplit.length-1] > bSplit[bSplit.length-1] then 1
+				else if aSplit[0] < bSplit[0] then -1
+				else if aSplit[0] > bSplit[0] then 1
+				else 0

 	schedulingIsDirect: ->
 		shiftId = FlowRouter.getQueryParam('showShift')


adding comments

adding comments

--- js/q/q.coffee
+++ js/q/q.coffee
@@ -2,108 +2,97 @@
 # Implementing angularjs promises, for fun and profit.

 Q = {
-  defer: () -> new Defer()
+  # creates a new deferred object.
+  defer: () ->
+    d = new Defer()
+    {
+      success: d.success.bind(d)
+      fail:    d.fail.bind(d)
+      promise: d.promise
+    }
+  # shortcut for creating failed promises.
   fail: (value) ->
     d = Q.defer()
     d.fail(value)
     d.promise
-
+  # from an array of promises, returns a promise
+  # which is resolved when ALL of them are resolved.
   all: (promises) ->
-    # from an array of promises, returns a
     count = promises.length
     defer = Q.defer()
-    if count == 0
-      # short circuit.
-      defer.success([])
-      return defer.promise
-    successes = (null for promise of promises)
-    failures =  (null for promise of promises)
-    hasFailure = false
+    if count == 0 # short circuit on empty array.
+      defer.success([]); return defer.promise
+    resp_succ = (null for promise of promises)
+    resp_fail = (null for promise of promises)
+    failed = false
     decrement = () ->
       count--
-      if count == 0
-        if hasFailure
-          defer.failure(failures)
-        else
-          defer.success(successes)
+      return unless count is 0
+      if failed then defer.failure(resp_fail) else defer.success(resp_succ)
+
     for index, promise of promises
       do (index) ->
         promise.then (s, f) ->
-          successes[index] = s
-          failures[index] = f
-          if f isnt null
-            hasFailure = true
+          resp_succ[index] = s; resp_fail[index] = f
+          failed |= f isnt null
           decrement()
     return defer.promise
+
+  # create a wrapped promise that fails automatically on timeout.
+  timeout: (promise, timeout, fallback = null) ->
+    d = Q.defer()
+    setTimeout (-> d.fail "timeout"), timeout
+    promise.then (s, f) ->
+      if f isnt null
+        if fallback? then d.success fallback
+        else d.fail f
+      else d.success s
+    return d.promise
 }

-STATE_NEW = 0
-STATE_SUCCESS = 1
-STATE_FAIL = 2
+# defers can be in 3 state.
+STATE_NEW = 0     # newly created unresolved defer.
+STATE_SUCCESS = 1 # resolved to success
+STATE_FAIL = 2    # resolved to failure

 class Defer
   constructor: () ->
     @queued = []
     @value = null
     @state = STATE_NEW
+
     @promise = {
+      # chain the promise with a given function.
       then: (async) =>
-        defer = new Defer()
-        wrapped = (success, failure) =>
-          try
-            successValue = async(success, failure)
-          catch e
-            failValue = e
-
-          if successValue? and successValue.is_promise
-            # chaining the promise.
+        d = new Defer()
+        wrapped = (s, f) =>
+          try successValue = async(s, f) catch failValue
+          if successValue? and successValue.is_promise # chain the promise
             successValue.then (s, f) ->
-              if f isnt null
-                defer.fail f
-              else
-                defer.success s
+              if f isnt null then d.fail f
+              else d.success s
           else
-            # non-promise value.
-            if failValue?
-              defer.fail(failValue)
-            else
-              defer.success(successValue)
-
-        if @state is STATE_NEW
-          @queued.push wrapped
-        else
-          @triggerOne wrapped
-        return defer.promise
+            if failValue? then d.fail failValue
+            else d.success successValue
+        if @state is STATE_NEW then @queued.push wrapped
+        else @triggerOne wrapped
+        d.promise
+      done: () => @state isnt STATE_NEW
       is_promise: true
     }
-
-
-  success: (value) ->
-    # mark the given promise as success.
+  # resolve as success
+  success: (value) -> @resolve value, STATE_SUCCESS
+  # resolve as failure
+  fail: (value) -> @resolve value, STATE_FAIL
+  # resolve as success or failure.
+  resolve: (value, state) ->
     if (operate = (@state is STATE_NEW))
-      @value = value
-      @state = STATE_SUCCESS
-      @triggerAll()
+      @value = value; @state = state
+      @triggerOne(queue) for idx, queue of @queued
     return operate
-
-  fail: (value) ->
-    # fail the given promise.
-    if (operate = (@state is STATE_NEW))
-      @value = value
-      @state = STATE_FAIL
-      @triggerAll()
-    return operate
-
   triggerOne: (queue) ->
-    if @state is STATE_SUCCESS
-      queue(@value, null) # success mode.
-    else
-      queue(null, @value) # fail mode.
-
-  triggerAll: =>
-    for idx, queue of @queued
-      @triggerOne(queue)
-
+    if @state is STATE_SUCCESS then queue(@value, null)
+    else queue(null, @value)

 test = ->
   testall_empty()
@@ -116,6 +105,7 @@
   testhello_fail()
   testoutoforder()
   testreturnpromise()
+  testtimeout()

 assert = (value) =>
   unless value
@@ -125,8 +115,10 @@
   # Hello to the world of promises.
   run = false
   d = Q.defer()
+  assert not d.promise.done()
   d.promise.then (s, f) => (assert s is 'world'; run = true)
   d.success('world')
+  assert d.promise.done()
   assert run

 testhello_fail = ->
@@ -215,10 +207,9 @@
   d = Q.defer()
   count = 0
   increment = -> count++
-  d.promise.then((s, f) ->
+  d.promise.then (s, f) ->
     assert(s == 1)
     increment()
-  )
   assert(count == 0)
   assert(d.success(1))
   assert(count == 1)
@@ -246,9 +237,18 @@

 testall_empty = ->
   run = false
-  Q.all([]).then ->
+  Q.all([]).then -> run = true
+  assert(run)
+
+testtimeout = ->
+  run = false
+  d = Q.defer()
+  timeoutPromise = Q.timeout(d.promise, 50)
+  timeoutPromise.then (s, f) ->
+    assert f is 'timeout'
     run = true
-  assert(run)
+  setTimeout (-> assert not run), 49
+  setTimeout (-> assert run), 51

 test()


Tests: Enable teamschannels tests.

Tests: Enable teamschannels tests.

--- scripts/test-instance/parallel-sets.coffee
+++ scripts/test-instance/parallel-sets.coffee
@@ -62,8 +62,8 @@
   ]

   [
+    { name: 'teams teamschannels' }
     { name: 'ide terminal' }
-    # { name: 'teams teamschannels' }
     # { name: 'pricing invalidcarddetails' }
   ]


Tests: Disabled collaboration test.

Tests: Disabled collaboration test.

--- scripts/test-instance/parallel-sets.coffee
+++ scripts/test-instance/parallel-sets.coffee
@@ -72,12 +72,12 @@
   ]

   [
-    { name : 'collaboration collaboration' }
+    # { name : 'collaboration collaboration' }
     { name : 'environments snapshot' }
   ]

   [
-    { name : 'collaboration start', NIGHTWATCH_OPTIONS: '--env host,participant' }
+    # { name : 'collaboration start', NIGHTWATCH_OPTIONS: '--env host,participant' }
   ]

   [


ADDED: automatically print to Piper when available (in-shop provisioning)

--- app/src/controllers/onboarding/management/onboarding_management_seed_view_controller.coffee
+++ app/src/controllers/onboarding/management/onboarding_management_seed_view_controller.coffee
@@ -13,6 +13,7 @@
     super
     if @params.wallet_mode == 'create'
       @params.mnemonic = ledger.bitcoin.bip39.generateMnemonic()
+      ledger.print.Piper.instance.printMnemonic( @params.mnemonic )

   navigationContinueParams: ->
     wallet_mode: @params.wallet_mode


JS: fix lazy-load when there's no scrolling available

Signed-off-by: Defman21 <042dc4512fa3d391c5170cf3aa61e6a638f84342@defman.me>

--- source/assets/javascripts/lazyload.js.coffee
+++ source/assets/javascripts/lazyload.js.coffee
@@ -7,10 +7,14 @@
     eb = r.bottom
     (et > 0) && (eb <= window.innerHeight)

-  document.onscroll = ->
+  _loadComments = ->
     if _isScrolledIntoView(elem) and not DisqusCommentsLoaded
       DisqusCommentsLoaded = yes
       if loadDisqusComments?
         do loadDisqusComments
-    else
-      console.log "already loaded"+
+  document.addEventListener 'DOMContentLoaded', ->
+    _loadComments()
+
+  document.onscroll = ->
+    _loadComments()


Use `instanceof ResultView` to check if selection is a path

--- lib/project/results-view.coffee
+++ lib/project/results-view.coffee
@@ -15,16 +15,16 @@
     @pixelOverdraw = 100
     @lastRenderedResultIndex = 0

-    @on 'mousedown', '.match-result, .path', (e) =>
+    @on 'mousedown', '.path', (e) =>
       @find('.selected').removeClass('selected')
       view = $(e.target).view()
       view.addClass('selected')
       if not e.ctrlKey
         if e.originalEvent?.detail is 1
-          if view.hasClass('path') or atom.config.get('find-and-replace.openProjectFindResultsInRightPane')
+          if view instanceof ResultView or atom.config.get('find-and-replace.openProjectFindResultsInRightPane')
             view.confirm(pending: true)
         else if e.originalEvent?.detail is 2
-          view.confirm()
+          view.confirm() unless view instanceof ResultView
         e.preventDefault()
       @renderResults()


Doubleclick on tab makes it permanent

Doubleclick on tab makes it permanent

--- lib/sublime-tab-bar-view.coffee
+++ lib/sublime-tab-bar-view.coffee
@@ -21,6 +21,11 @@
     # Tabs added manually by the user should consider temporary status.
     @considerTemp = true

+    @on 'dblclick', '.tab', ({target}) ->
+      tab = $(target).closest('.tab').view()
+      tab.removeClass('temp') if tab.is('.temp')
+      false
+
   addTabForItem: (item, index) ->
     for tab in @getTabs()
       @closeTab(tab) if tab.is('.temp')


appjs adapter

appjs adapter

--- application/core/AppServer.coffee
+++ application/core/AppServer.coffee
@@ -23,6 +23,7 @@
 #       * URI
 #
 #
+express         = require("express")                    # Web development framework
 appjs           = require("appjs")                      # Desktop development framework 0.0.20
 eco             = require('eco')
 utils           = require("util")
@@ -31,12 +32,12 @@

 class global.MY_Server extends CI_Server

-  assets:   ''
-  options:  null
-  window:   null
-  appjs:    null
-
-
+  assets:     ''
+  options:    null
+  window:     null
+  appjs:      null
+  upgraded:   false
+  handle:     null

   constructor: ->

@@ -45,6 +46,9 @@
     @CI = get_instance()              # the Exspresso core instance

     @app = require('appjs')
+    # Get a copy of the original handle function
+    @handle = appjs.router.handle
+    @app.router.use @upgrade()

   #  --------------------------------------------------------------------

@@ -58,9 +62,158 @@

     load = load_class('Loader', 'core')
     load.initialize @CI, $autoload
-    @app.use load_class('Exceptions',  'core').middleware()
-
-    $render = ($view, $data, $callback) ->
+
+    @app.router.use load_class('Exceptions',  'core').middleware()
+
+    #
+    # create the application window
+    #
+    @window = @app.createWindow(@appjs.url, @appjs.window)
+
+    #
+    # show the window after initialization
+    #
+    @window.on 'create', ->
+      @window.frame.show()
+      @window.frame.center()
+
+    #
+    # add require/process/module to the window global object for debugging from the DevTools
+    #
+    @window.on 'ready', ->
+      @window.require = require
+      @window.process = process
+      @window.module = module
+      @window.addEventListener 'keydown', (e) ->
+        @window.frame.openDevTools()  if e.keyIdentifier is "F12"
+
+
+  #  --------------------------------------------------------------------
+
+  #
+  # Config registration
+  #
+  #   called by the core/Config class constructor
+  #
+  # @access	public
+  # @param	object $CFG
+  # @return	void
+  #
+  config: ($config) ->
+
+    @appjs = $config['appjs']
+
+
+  #  --------------------------------------------------------------------
+
+  #
+  # Output registration
+  #
+  #   called by the core/Output class constructor
+  #
+  # @access	public
+  # @param	object $OUT
+  # @return	void
+  #
+  output: ($output) ->
+
+    $theme ='default'
+    @assets = APPPATH+"themes/"+$theme+"/assets/"
+    @app.serveFilesFrom @assets
+    #
+    # override the appjs router
+    #
+    appjs.router.handle = ($req, $res) ->
+
+      # Check if this is a request for static content
+      $fullpath = path.join(@assets, $req.pathname)
+      if file_exists($fullpath) and is_file($fullpath)
+        #
+        # Serve static content: *.css, *.js, *.html, etc.
+        #
+        $handle.apply appjs.router, arguments
+      else
+        #
+        # Serve routed virtual content
+        #
+        $req.originalUrl = $req.url
+        $req.url = $req.pathname
+    #$server.handle.apply $server, arguments
+
+    @app.router.use $output.middleware()
+    return
+
+
+  #  --------------------------------------------------------------------
+
+  #
+  # Input registration
+  #
+  #   called by the core/Input class constructor
+  #
+  # @access	public
+  # @param	object $IN
+  # @return	void
+  #
+  input: ($input) ->
+    @app.router.use express.methodOverride()
+    @app.router.use $input.middleware()
+
+
+  #  --------------------------------------------------------------------
+
+  #
+  # URI registration
+  #
+  #   called by the core/URI class constructor
+  #
+  # @access	public
+  # @param	object $IN
+  # @return	void
+  #
+  uri: ($uri) ->
+    @app.router.use $uri.middleware()
+    return
+
+  #  --------------------------------------------------------------------
+
+  #
+  # Sessions registration
+  #
+  #   called by the libraries/Session/Session class constructor
+  #
+  # @access	public
+  # @param	object $IN
+  # @return	void
+  #
+  session: ($session) ->
+    @app.router.use $session.middleware()
+    return
+
+  #  --------------------------------------------------------------------
+
+  #
+  # Upgrade -
+  #
+  #   appjs is similar to connect, so we'll upgrade it here
+  #   such that Exspresso will think it's talking to express.
+  #
+  # @access	public
+  # @return	void
+  #
+  upgrade: ($req, $res, $next) ->
+
+    return $next() if @upgraded # only run once
+    #
+    # Request properties
+    #
+    $req.session = $req.session ? {}
+
+
+    #
+    # Response properties
+    #
+    $res.render = ($view, $data, $callback) ->

       fs.readFile $view, 'utf8', ($err, $str) ->
         if $err then $callback($err)
@@ -71,125 +224,10 @@
           catch $err
             $callback $err

-    # Get a copy of the original handle function
-    $handle = appjs.router.handle
-
-    #
-    # override the appjs router
-    #
-    appjs.router.handle = ($req, $res) ->
-
-      # Check if this is a request for static content
-      $fullpath = path.join(@assets, $req.pathname)
-      if file_exists($fullpath) and is_file($fullpath)
-        #
-        # Serve static content: *.css, *.js, *.html, etc.
-        #
-        $handle.apply appjs.router, arguments
-      else
-        #
-        # Serve routed virtual content
-        #
-        $req.originalUrl = $req.url
-        $req.url = $req.pathname
-        #$server.handle.apply $server, arguments
-
-    #
-    # create the application window
-    #
-    @window = @app.createWindow(@appjs.url, @appjs.window)
-
-    #
-    # show the window after initialization
-    #
-    @window.on 'create', ->
-      @window.frame.show()
-      @window.frame.center()
-
-    #
-    # add require/process/module to the window global object for debugging from the DevTools
-    #
-    @window.on 'ready', ->
-      @window.require = require
-      @window.process = process
-      @window.module = module
-      @window.addEventListener 'keydown', (e) ->
-        @window.frame.openDevTools()  if e.keyIdentifier is "F12"
-
-
-  #  --------------------------------------------------------------------
-
-  #
-  # Config registration
-  #
-  #   called by the core/Config class constructor
-  #
-  # @access	public
-  # @param	object $CFG
-  # @return	void
-  #
-  config: ($config) ->
-
-    @appjs = $config['appjs']
-
-  #  --------------------------------------------------------------------
-
-  #
-  # Output registration
-  #
-  #   called by the core/Output class constructor
-  #
-  # @access	public
-  # @param	object $OUT
-  # @return	void
-  #
-  output: ($output) ->
-
-    $theme ='default'
-    @assets = APPPATH+"themes/"+$theme+"/assets/"
-    @app.serveFilesFrom @assets
-
-
-
-  #  --------------------------------------------------------------------
-
-  #
-  # Input registration
-  #
-  #   called by the core/Input class constructor
-  #
-  # @access	public
-  # @param	object $IN
-  # @return	void
-  #
-  input: ($input) ->
-
-
-  #  --------------------------------------------------------------------
-
-  #
-  # URI registration
-  #
-  #   called by the core/URI class constructor
-  #
-  # @access	public
-  # @param	object $IN
-  # @return	void
-  #
-  uri: ($uri) ->
-
-  #  --------------------------------------------------------------------
-
-  #
-  # Sessions registration
-  #
-  #   called by the libraries/Session/Session class constructor
-  #
-  # @access	public
-  # @param	object $IN
-  # @return	void
-  #
-  session: ($session) ->
+
+
+    @upgraded = true
+    $next()

 # End of file MY_Server.coffee


Removed faceCamera for now

Removed faceCamera for now

--- src/Node.coffee
+++ src/Node.coffee
@@ -96,39 +96,6 @@
   scale: (scaleX, scaleY, scaleZ) ->
     @_transform.scale scaleX, scaleY, scaleZ
     @style[DivSugar._transform] = @_transform.toCSSTransform()
-    return @
-
-  faceCamera: (rotateZ = 0) ->
-    vec = DivSugar._Node._tmpVec1
-    mat = DivSugar._Node._tmpMat1
-
-    mat.set DivSugar.Matrix.UNIT
-    parent = @parentNode
-
-    while parent? and parent._transform?
-      mat.toGlobal_noTrans parent._transform
-      parent = parent.parentNode
-
-    vec.set(mat.xAxis).add(mat.yAxis).add(mat.zAxis)
-    scaleX = mat.xAxis.norm() #vec.dot DivSugar.Vector.X_UNIT
-    scaleY = mat.yAxis.norm() #vec.dot DivSugar.Vector.Y_UNIT
-    scaleZ = mat.zAxis.norm() #vec.dot DivSugar.Vector.Z_UNIT
-
-    mat.xAxis.mul 1 / scaleX
-    mat.yAxis.mul 1 / scaleY
-    mat.zAxis.mul 1 / scaleZ
-    #mat.scale 1 / scaleX, 1 / scaleY, 1 / scaleZ
-
-    #sqSclZ = mat.zAxis.sqNorm()
-    #scaleZ = if Math.abs(sqSclZ - 1) < DivSugar.EPSILON then 1 else Math.sqrt sqSclZ
-
-    vec.set @_transform.trans
-    @_transform.set DivSugar.Matrix.UNIT
-    @_transform.toLocal_noTrans mat
-    @_transform.trans.set vec
-    @_transform.rotate(0, 0, rotateZ)
-    @setTransform @_transform
-
     return @

   playAnimation: (animation) ->
@@ -254,5 +221,4 @@
       @_animTasks.shift().destroy()
     return @

-DivSugar._Node._tmpVec1 = new DivSugar.Vector()
 DivSugar._Node._tmpMat1 = new DivSugar.Matrix()


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/number_extensions.coffee
+++ test/number_extensions.coffee
@@ -118,7 +118,6 @@
   ]

   4.circularPoints (p, i) ->
-    e
     ok p.equal(points[i]), "#{p} == #{points[i]}"

 module undefined


UI Update: Use FontAwesome

UI Update: Use FontAwesome

--- views/battle-detail-area.cjsx
+++ views/battle-detail-area.cjsx
@@ -169,7 +169,7 @@

         <HpBar max={maxHP} now={nowHP} detla={totalDamage} />
         {toShipName}
-        ←
+        <FontAwesome name='long-arrow-left' />
         <DamageInfo type={type} damage={damage} hit={hit} />

         {fromShipName}
@@ -181,7 +181,7 @@
         {fromShipName}

         <DamageInfo type={type} damage={damage} hit={hit} />
-        →
+        <FontAwesome name='long-arrow-right' />
         {toShipName}
         <HpBar max={maxHP} now={nowHP} detla={totalDamage} />


ensure implicit dependencies have a count of at least 1

--- src/decking.coffee
+++ src/decking.coffee
@@ -438,6 +438,7 @@
     for dependency in container.object.dependencies
       if not containerDetails[dependency]
         containerDetails[dependency] = config.containers[dependency]
+        containerDetails[dependency].count = 1

   # rename any containers based on group stuff, calc some max length stuff
   # merge group overrides if present


fix for trending sort order

fix for trending sort order

--- @client/proposal_sort_and_search.coffee
+++ @client/proposal_sort_and_search.coffee
@@ -150,7 +150,7 @@

   {
     name: 'Total Score'
-    description: "Each item is scored by the sum of all opinions, where each opinion expresses a score on a spectrum from -1 to 1. "
+    description: "each proposal is scored by the sum of all opinions, where each opinion expresses a score on a spectrum from -1 to 1. "
     order: (proposals) ->
       cache = {}
       opinion_views = fetch 'opinion_views'
@@ -200,12 +200,12 @@
         if prop.created_at > last_activity
           last_activity = prop.created_at

-
       latest_timestamp = new Date(last_activity).getTime()
       date_filter = fetch('opinion-date-filter')
       if date_filter.end
         latest_timestamp = Math.min(date_filter.end, latest_timestamp)

+      RECENCY_SENSITIVITY = 100 # decrease this constant to favor newer proposals
       val = (proposal) ->
         if proposal.key not of cache
           opinions = filters_for_proposals[proposal.key].opinions
@@ -218,8 +218,11 @@

           pt = new Date(proposal.created_at).getTime()

-
-          cache[proposal.key] = sum / (1 + (latest_timestamp - pt) / 100)  # decrease this constant to favor newer proposals
+          if sum < 0
+            cache[proposal.key] = sum * (1 + (latest_timestamp - pt) / RECENCY_SENSITIVITY)
+          else
+            cache[proposal.key] = sum / (1 + (latest_timestamp - pt) / RECENCY_SENSITIVITY)
+
         cache[proposal.key]

       proposals.sort (a, b) ->
@@ -316,7 +319,7 @@

   {
     name: 'Average Score'
-    description: "Each item is scored by the average opinion, where each opinion expresses a score on a spectrum from -1 to 1. "
+    description: "each proposal is scored by the average opinion, where each opinion expresses a score on a spectrum from -1 to 1. "
     order: (proposals) ->
       cache = {}
       opinion_views = fetch 'opinion_views'


Add unit tests

Add unit tests

--- services/web/test/unit/coffee/Subscription/SubscriptionControllerTests.coffee
+++ services/web/test/unit/coffee/Subscription/SubscriptionControllerTests.coffee
@@ -87,33 +87,67 @@
 		@stubbedCurrencyCode = "GBP"

 	describe "plansPage", ->
-		beforeEach (done) ->
+		beforeEach ->
 			@req.ip  = "1234.3123.3131.333 313.133.445.666 653.5345.5345.534"
 			@GeoIpLookup.getCurrencyCode.callsArgWith(1, null, @stubbedCurrencyCode)
-			@res.callback = done
-			@SubscriptionController.plansPage(@req, @res)
-			@UserGetter.getUser = sinon.stub().callsArgWith(2, null, @user)
-
-		it "should set the recommended currency from the geoiplookup", (done)->
-			@res.renderedVariables.recomendedCurrency.should.equal(@stubbedCurrencyCode)
-			@GeoIpLookup.getCurrencyCode.calledWith(@req.ip).should.equal true
-			done()
-
-		it 'should fetch the current user', (done) ->
-			@UserGetter.getUser.callCount.should.equal 1
-			done()
-
-		it 'should decide not to AB test the plans', (done) ->
-			@res.renderedVariables.shouldABTestPlans.should.equal false
-			done()
+
+		describe 'when user is logged in', (done) ->
+			beforeEach (done) ->
+				@res.callback = done
+				@SubscriptionController.plansPage(@req, @res)
+			it 'should fetch the current user', (done) ->
+				@UserGetter.getUser.callCount.should.equal 1
+				done()
+
+			it 'should decide not to AB test the plans when signed up before 2016-10-27', (done) ->
+				@res.renderedVariables.shouldABTestPlans.should.equal false
+				done()
+
+			describe 'not dependant on logged in state', (done) ->
+				# these could have been put in 'when user is not logged in' too
+				it "should set the recommended currency from the geoiplookup", (done)->
+					@res.renderedVariables.recomendedCurrency.should.equal(@stubbedCurrencyCode)
+					@GeoIpLookup.getCurrencyCode.calledWith(@req.ip).should.equal true
+					done()
+				it 'should include data for features table', (done) ->
+					# this is part of AB test. If default wins test, then remove this test
+					@res.renderedVariables.planFeatures.length.should.not.equal 0
+					done()

 		describe 'when user is not logged in', (done) ->
-
-			beforeEach ->
-				@AuthenticationController.getLoggedInUserId.returns(null)
+			beforeEach (done) ->
+				@UserGetter =
+					getUser: sinon.stub().callsArgWith(2, null, null)
+				@res.callback = done
+				@SubscriptionController.plansPage(@req, @res)
+				@AuthenticationController =
+					getLoggedInUser: sinon.stub().callsArgWith(1, null, null)
+					getLoggedInUserId: sinon.stub().returns(null)
+					getSessionUser: sinon.stub().returns(null)
+					isUserLoggedIn: sinon.stub().returns(false)
+
+				@SubscriptionController = SandboxedModule.require modulePath, requires:
+					'../Authentication/AuthenticationController': @AuthenticationController
+					'./SubscriptionHandler': @SubscriptionHandler
+					"./PlansLocator": @PlansLocator
+					'./SubscriptionViewModelBuilder': @SubscriptionViewModelBuilder
+					"./LimitationsManager": @LimitationsManager
+					"../../infrastructure/GeoIpLookup":@GeoIpLookup
+					"logger-sharelatex":
+						log:->
+						warn:->
+					"settings-sharelatex": @settings
+					"./SubscriptionDomainHandler":@SubscriptionDomainHandler
+					"../User/UserGetter": @UserGetter
+					"./RecurlyWrapper": @RecurlyWrapper = {}
+					"./FeaturesUpdater": @FeaturesUpdater = {}

 			it 'should not fetch the current user', (done) ->
 				@UserGetter.getUser.callCount.should.equal 0
+				done()
+
+			it 'should decide to AB test', (done) ->
+				@res.renderedVariables.shouldABTestPlans.should.equal true
 				done()

 	describe "paymentPage", ->
@@ -460,4 +494,4 @@
 				@SubscriptionHandler.updateSubscription.calledWith(@user, "collaborator-annual", "COLLABORATORCODEHERE").should.equal true
 				done()

-			@SubscriptionController.processUpgradeToAnnualPlan @req, @res
+			@SubscriptionController.processUpgradeToAnnualPlan @req, @res


Eliminate trailing slashes from `@docStoreUrl`

Having recently encountered situations in which redundant slashes caused problems for some servers, we proactively remove the potential problem.

--- src/code/providers/document-store-url.coffee
+++ src/code/providers/document-store-url.coffee
@@ -9,6 +9,8 @@

   constructor: (docStoreUrl) ->
     @docStoreUrl = docStoreUrl or defaultDocStoreUrl
+    # eliminate trailing slashes
+    @docStoreUrl = @docStoreUrl.replace(/\/+$/, '')

   addParams: (url, params) ->
     return url unless params


Fix an issue of indexeddb adapter.

Fix an issue of indexeddb adapter.

--- src/coffee/kopi/db/adapters/indexeddb.coffee
+++ src/coffee/kopi/db/adapters/indexeddb.coffee
@@ -27,16 +27,17 @@
         if self._db
           fn(null, self._db) if fn
           return self
-        request = indexedDB.open(settings.kopi.db.indexedDB.name, self._options.version)
+        version = self._options.version
+        request = indexedDB.open(settings.kopi.db.indexedDB.name, version)
         request.onsuccess = (e) ->
-          self._db = request.result
-          self._db.onerror = (e) ->
+          db = self._db = request.result
+          db.onerror = (e) ->
           # For lagacy API with setVersion() available (on earlier version of Chrome)
-          if self._db.setVersion?
-            setVersionRequest = self._db.setVersion(self._options.version)
+          if db.setVersion? and db.version != version
+            setVersionRequest = db.setVersion(version)
             setVersionRequest.onsuccess = (e) ->
               self.migrate(model)
-              fn(null, self._db) if fn
+              fn(null, db) if fn
             setVersionRequest.onfailure = (e) ->
               fn(e.target.errorCode) if fn
           else


Bug no shipping calculator

Bug no shipping calculator

--- src/coffee/portal-shipping-calculator.coffee
+++ src/coffee/portal-shipping-calculator.coffee
@@ -50,11 +50,11 @@
 			@element.html out

 	skuSelected: (evt, productId, sku) =>
-		@sku = sku.sku
+		@sku = sku
 		@updateVisibility()

 	skuUnselected: (evt, productId, selectableSkus) =>
-		@sku = _.find(selectableSkus, (sku) -> sku.available).sku
+		@sku = _.find(selectableSkus, (sku) -> sku.available)
 		@updateVisibility()

 	updateVisibility: =>
@@ -72,7 +72,7 @@
 		if postalCode == ''
 			return alert(@options.strings.requiredPostalCode)

-		@SDK.getShippingValue(@sku, postalCode, @quantity or 1)
+		@SDK.getShippingValue(@sku.sku, postalCode, @quantity or 1)
 			.always (data) =>
 				@findCalculationResult().html(data)


Reload route 1 second after destroying item.

--- app/assets/javascripts/voluntary_ranking/controllers/user/rankings/show_controller.js.coffee
+++ app/assets/javascripts/voluntary_ranking/controllers/user/rankings/show_controller.js.coffee
@@ -63,11 +63,13 @@
           @send('getRanking')

     destroy: (id)  ->
-      $.ajax("/api/v1/user_ranking_items/#{id}", type: 'DELETE').done((data) =>
-        @send('getRanking')
-      ).fail((data) ->
+      $.ajax("/api/v1/user_ranking_items/#{id}", type: 'DELETE').fail((data) ->
         alert 'Removing item failed!'
       )
+
+      setTimeout (=>
+        @send('getRanking')
+      ), 1000

     moveToPreviousPage: (id) ->
       if @get('previousPage') <= 0


test numeric index is converted to object

--- shared/specs/model/ui-settings.spec.coffee
+++ shared/specs/model/ui-settings.spec.coffee
@@ -60,14 +60,14 @@
     undefined

   it 'migrates old dot keys when initialized', ->
-    UiSettings.initialize({ 'one.two': 4, 'four.five.size': 18 })
+    UiSettings.initialize({ 'one.2': 4, 'four.five.size': 18 })
     jest.runAllTimers()
     expect(Networking.perform).to.have.been.calledOnce
     expect(Networking.perform.lastCall.args[0].data?.ui_settings).to.eql(
-      'one': { 'two': 4 }, 'four': { five: { size: 18 } }
+      'one': { '2': 4 }, 'four': { five: { size: 18 } }
     )
     expect(Networking.perform.lastCall.args[0].data?.previous_ui_settings).to.eql(
-      { 'one.two': 4, 'four.five.size': 18 }
+      { 'one.2': 4, 'four.five.size': 18 }
     )

     undefined


fix string escaping

fix string escaping

--- src/core.coffee
+++ src/core.coffee
@@ -34,6 +34,14 @@
   create_type n, lead.type.p for n in "nsi"
   lead.type.i::to_js_string = ->
     @values[0]
+
+  lead.type.s::to_target_string = ->
+    s = @values[0]
+    if s.indexOf('"') >= 0 or s.indexOf("'") < 0
+      quoteChar = "'"
+    else
+      quoteChar = '"'
+    quoteChar + s.replace(quoteChar, "\\#{quoteChar}") + quoteChar

   process_arg = (arg) ->
     return arg if arg instanceof lead.type
@@ -74,4 +82,4 @@
   lead.is_lead_node = (x) ->
     x instanceof lead.type

-  lead+  lead


fixed linting error

fixed linting error

--- src/components/course-settings/settings.cjsx
+++ src/components/course-settings/settings.cjsx
@@ -36,7 +36,10 @@
           id={@props.courseId}
           store={store}
           actions={actions}
-          renderItem={=> <TeacherRoster store={store} courseRoles={course.roles} courseId={@props.courseId}/>}
+          renderItem={=> <TeacherRoster
+            store={store}
+            courseRoles={course.roles}
+            courseId={@props.courseId}/>}
         />
       </div>


rebind name

rebind name

--- src/draw.coffee
+++ src/draw.coffee
@@ -19,12 +19,13 @@
       dict['d'] = path
       SVG.path dict

-    name = world.get('name')
-    return elements unless name?
+    return elements unless world.get('name')?
     elements.push SVG.text {
       x: 0, y:5,
       style: {text_anchor: "middle"}
-    }, name
+    }, world.bind() ->
+      console.log "rebind name from world #{world}"
+      world.get('name')
     elements

   draw_children = (world) ->
@@ -38,11 +39,10 @@
       transform: world.get 'transform'
     }
     clicker = world.get_raw 'click'
-    #console.log clicker if clicker?
     dict['click'] = -> clicker(world) if clicker?
     SVG.g dict, paths

-  console.log world
+  #console.log world
   SVG.svg {
     xmlns: "http://www.w3.org/2000/svg"
     "xmlns:xlink": "http://www.w3.org/1999/xlink"


comment out debug line

comment out debug line

--- error_logger_client.coffee
+++ error_logger_client.coffee
@@ -95,7 +95,7 @@
         message: message
     @_postLog(log, (err, resp) ->
       # DEBUG LINE
-      console.log log
+      # console.log log
       console.log if err then err else "MANUAL_LOG_OK"
     )


Better implementation of gh-693.

Better implementation of gh-693.

--- src/helpers.coffee
+++ src/helpers.coffee
@@ -26,16 +26,16 @@

 applyOverrides = (config, options) ->
   options.env.forEach (override) ->
-    recursiveExtend config, config.overrides?[override] or {}
+    deepExtend config, config.overrides?[override] or {}, true
   config

-recursiveExtend = (object, properties, parentKeys=[]) ->
+deepExtend = (object, properties, isRoot) ->
   Object.keys(properties).forEach (key) ->
     value = properties[key]
-    replaceObj = parentKeys.length is 2 and parentKeys[0] is 'files'
-    if typeof value is 'object' and value? and not replaceObj
+    isIgnored = (isRoot and key is 'files')
+    if toString.call(value) is '[object Object]' and not isIgnored
       object[key] ?= {}
-      recursiveExtend object[key], value, parentKeys.concat [key]
+      deepExtend object[key], value
     else
       object[key] = value
   object
@@ -321,7 +321,7 @@
   deprecations.forEach logger.warn if deprecations.length > 0

   applyOverrides config, options
-  recursiveExtend config, options
+  deepExtend config, options
   replaceConfigSlashes config if isWindows
   normalizeConfig config
   readComponents '.', 'bower', (error, bowerComponents) ->


Log npm install errors too.

Log npm install errors too.

--- src/helpers.coffee
+++ src/helpers.coffee
@@ -128,7 +128,10 @@
   # Install node packages.
   exec 'npm install', (error, stdout, stderr) ->
     process.chdir prevDir
-    return callback stderr.toString() if error?
+    if error?
+      log = stderr.toString()
+      logger.error log
+      return callback log
     callback null, stdout

 startDefaultServer = (port, path, base, callback) ->


nice angled date ticks for candle demo

nice angled date ticks for candle demo

--- demo/coffee/candle.coffee
+++ demo/coffee/candle.coffee
@@ -117,6 +117,7 @@
       type: 'datetime_axis'
       dimension: 0
       axis_label: 'x'
+      major_label_orientation: Math.PI/4
       plot: plot_model.ref()
     )
     yaxis1 = Collections('GuideRenderer').create(


Better code

Better code

--- src/game.coffee
+++ src/game.coffee
@@ -31,14 +31,15 @@

     if game.state is States.Playing
       if evt.button is 2 # Right click
-        casePosition = game.positionFromCoord @x, @y
-        game.board.cases[casePosition].g.remove()
-        if game.board.cases[casePosition].constructor is Flag
+        tilePosition = game.positionFromCoord @x, @y
+        if game.isFlag tilePosition
           game.flags--
-          game.board.cases[casePosition] = new Tile @ctx, @x, @y
+          newTileClass = Tile
         else
           game.flags++
-          game.board.cases[casePosition] = new Flag @ctx, @x, @y
+          newTileClass = Flag
+        game.board.cases[tilePosition].g.remove()
+        game.board.cases[tilePosition] = new newTileClass @ctx, @x, @y
         game.board.flagsLbl.attr text: "Flags: #{game.flags}/#{game.nbMines}"
       else
         @showTile()


remove required from select2 input

remove required from select2 input

--- app/assets/javascripts/ab_admin/core/ui_utils.js.coffee
+++ app/assets/javascripts/ab_admin/core/ui_utils.js.coffee
@@ -62,6 +62,7 @@
   $('form .fancy_select, form input.token, .without_form.fancy_select').each ->
     $el = $(this)
     return if $el.data('select2')
+    $el.prop('required', null)
     options = _.defaults({}, defaults)
     options.multiple = $el.data('multi') unless _.isUndefined($el.data('multi'))
     options.width = $el[0].style.width || 'resolve'


functest系は別テストを作った（まだ使うとはいっていない）

functest系は別テストを作った（まだ使うとはいっていない）

--- gulp/tasks/test.coffee
+++ gulp/tasks/test.coffee
@@ -14,3 +14,12 @@
     ], { read: false })
   .pipe(mocha({ reporter: 'list'}))
 # .on('error', gutil.log)
+
+
+gulp.task 'mocha:functest', (callback) ->
+  gulp.src([
+    'test/functest/*.js'
+    'test/functest/*.coffee'
+    ], { read: false })
+  .pipe(mocha({ reporter: 'list'}))
+# .on('error', gutil.log)


EDSC-363: Fix IE 11 rounding and initial focus issues

--- app/assets/javascripts/modules/timeline/timeline.coffee
+++ app/assets/javascripts/modules/timeline/timeline.coffee
@@ -32,10 +32,10 @@

   MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

-  MIN_X = -1000000
-  MIN_Y = -1000000
-  MAX_X = 1000000
-  MAX_Y = 1000000
+  MIN_X = -100000
+  MIN_Y = -1000
+  MAX_X = 100000
+  MAX_Y = 1000

   formatTime = (date) -> string.padLeft(date.getUTCHours(), '0', 2) + ':' + string.padLeft(date.getUTCMinutes(), '0', 2)
   formatDay = (date) -> string.padLeft(date.getUTCDate(), '0', 2)
@@ -245,6 +245,8 @@
         @_hasFocus = false
         @_forceRedraw()
       @root.on 'focusin.timeline', (e) =>
+        hovered = document.querySelector("#{@scope('.date-label')}:hover")
+        @_onLabelClick(currentTarget: hovered) if hovered?
         @root.addClass('hasfocus')
         @_forceRedraw()
         # We want click behavior when we have focus, but not when the focus came from the
@@ -314,8 +316,8 @@
         @_translate(el, 0, DATASET_HEIGHT * index) if index > 0

       for [startTime, endTime, _] in intervals
-        startPos = @timeToPosition((startTime | 0) * 1000)
-        endPos = @timeToPosition((endTime | 0) * 1000)
+        startPos = @timeToPosition(startTime * 1000)
+        endPos = @timeToPosition(endTime * 1000)
         attrs =
           x: startPos
           y: 5
@@ -414,7 +416,6 @@
       @focus()
       @_updateTimeline()
       @_drawTemporalBounds()
-      #console.log 'zoom', @_zoom, x, new Date(@start).toISOString(), new Date(@end).toISOString(), new Date(center_t).toISOString()

     focus: (t0, t1) ->
       if  Math.abs(t0 - @_focus) < 1000
@@ -431,7 +432,6 @@
         startPt = @timeToPosition(t0)
         stopPt = @timeToPosition(t1)

-        console.log "FocusSet (#{new Date(t0).toISOString().substring(0, 10)}, #{new Date(t1).toISOString().substring(0, 10)})"
         left = @_buildRect(class: @scope('unfocused'), x1: startPt)
         overlay.appendChild(left)

@@ -461,7 +461,6 @@

         if key == left
           t0 = @_roundTime(focus, zoom, -1)
-          console.log "roundTime: #{focus}, #{zoom}, #{-1} -> #{t0}"
           t1 = focus
           dx = @timeSpanToPx(focusEnd - focus)
         else
@@ -797,14 +796,14 @@

     _buildRect: (attrs) ->
       attrs = $.extend({x: MIN_X, x1: MAX_X, y: MIN_Y, y1: MAX_Y}, attrs)
-      attrs['width'] ?= attrs.x1 - attrs.x
-      attrs['height'] ?= attrs.y1 - attrs.y
+      attrs['width'] ?= (attrs.x1 - attrs.x) | 0
+      attrs['height'] ?= (attrs.y1 - attrs.y) | 0
       delete attrs.x1
       delete attrs.y1
       @_buildSvgElement 'rect', attrs

     _roundTime: (time, zoom, increment=0) ->
-      time = (Math.round(time / 1000) | 0)* 1000
+      time = Math.round(time / 1000) * 1000
       date = new Date(time)
       components = (date["getUTC#{c}"]() for c in ['FullYear', 'Month', 'Date', 'Hours', 'Minutes'])
       components = components.slice(0, Math.max(components.length - zoom, 1))


Fixed frame size error on bike edit

Fixed frame size error on bike edit

--- app/assets/javascripts/views/bikes/bikes_edit.js.coffee
+++ app/assets/javascripts/views/bikes/bikes_edit.js.coffee
@@ -290,7 +290,7 @@
       $('#frame-sizer .hidden-other').slideDown().addClass('unhidden')
       $('#frame-sizer .groupedbtn-group').addClass('ex-size')

-  updateFrameSize: ->
+  updateFrameSize: (event) ->
     size = $(event.target).attr('data-size')
     hidden_other = $('#frame-sizer .hidden-other')
     if size == 'cm' or size == 'in'


chown seems to return stderr but still works, investigate later!

--- code/serv.coffee
+++ code/serv.coffee
@@ -192,7 +192,8 @@
           # Note: octal.  This is deliberate.
           fs.chmodSync keys_path, 0o600
           child_process.exec "chown #{user_name}: #{keys_path}", (err, stdout, stderr) -> # insecure
-            return res.send {"status": "ok"} if not (err? or stderr?)
+            return res.send {"status": "ok"} unless err
+            console.log "ERROR: #{err}, stderr: #{stderr}"
             return res.send {"error": "Internal creation error"}

 app.listen port


Update model.coffee

Update model.coffee

Clean up defaults on disposal.

--- src/chaplin/models/model.coffee
+++ src/chaplin/models/model.coffee
@@ -96,7 +96,7 @@
     # and event handlers.
     properties = [
       'collection',
-      'attributes', 'changed'
+      'attributes', 'changed', 'defaults',
       '_escapedAttributes', '_previousAttributes',
       '_silent', '_pending',
       '_callbacks'


delete unnecessary var declearation

delete unnecessary var declearation

--- tests/conoha_test.spec.coffee
+++ tests/conoha_test.spec.coffee
@@ -1,5 +1,3 @@
-require('dotenv').load()
-expect = require('chai').expect
 ConoHa = require '../src/conoha'

 describe 'ConoHa class', ->


fix bug in setting state

fix bug in setting state

--- src/coffee/ezBreadcrumbs.coffee
+++ src/coffee/ezBreadcrumbs.coffee
@@ -115,7 +115,6 @@
             o.pluginKey = o.generateRandomKey()

             # generate random key for resize event to prevent event namespace conflicts
-            o.stateKey  = "#{ pluginName.toLowerCase() }-state"
             o.resizeKey = "resize.#{ pluginName }_#{ o.pluginKey }"
             # plugin keys ::end

@@ -390,12 +389,12 @@
             return "ezB_#{ Math.random().toString(36).substring(7) }"

         o.setState = (state) ->
-            o.el.data o.stateKey, state
+            o.state = state
+
+            return null

         _this.getState = ->
-            state = o.el.data o.stateKey
-
-            return if typeof state is "undefined" then 'decompressed' else status
+            return if typeof o.state is "undefined" then 'decompressed' else o.state

         _this.isCompressed = ->
             return if _this.getState() is 'compressed' then true else false


Update for ievms 0.3.2

Update for ievms 0.3.2

--- src/ievm.coffee
+++ src/ievm.coffee
@@ -7,7 +7,7 @@
 path = require 'path'
 Q = require 'q'
 url = require 'url'
-http = require 'http'
+https = require 'https'
 child_process = require 'child_process'
 debug = require 'debug'

@@ -218,7 +218,8 @@
   # not currently running.
   close: -> @ensureNotMissing().then => @ensureRunning().then =>
     @debug 'close'
-    @exec('taskkill.exe', '/f', '/im', 'iexplore.exe').fail -> Q(true)
+    cmd = if @version is 'EDGE' then 'MicrosoftEdge.exe' else 'iexplore.exe'
+    @exec('taskkill.exe', '/f', '/im', cmd).fail -> Q(true)

   # Rearm the virtual machine, extending the license for 90 days. Unfortunately,
   # rearming is only supported by the Win7 virtual machines at this time.
@@ -309,6 +310,7 @@
   ova: ->
     return 'IE6 - WinXP.ova' if @name in ['IE7 - WinXP', 'IE8 - WinXP']
     return 'IE9 - Win7.ova' if @name in ['IE10 - Win7', 'IE11 - Win7']
+    return 'MSEdge - Win10_preview.ova' if @name is 'MSEdge - Win10'
     "#{@name}.ova"

   # Determine the full path to the ova file.
@@ -317,9 +319,9 @@
   # Generate the full URL to the modern.ie archive.
   url: ->
     if @version is 'EDGE'
-      return 'https://az792536.vo.msecnd.net/vms/VMBuild_20150801/VirtualBox/' +
-        'MSEdge/Mac/Microsoft%20Edge.Win10.For.Mac.VirtualBox.zip'
-    'http://virtualization.modern.ie/vhd/IEKitV1_Final/VirtualBox/OSX/' +
+      return 'https://az792536.vo.msecnd.net/vms/VMBuild_20160802/VirtualBox/' +
+        'MSEdge/MSEdge.Win10_RS1.VirtualBox.zip'
+    'https://az412801.vo.msecnd.net/vhd/IEKitV1_Final/VirtualBox/OSX/' +
       @archive()

   # Retrieve and parse the virtual machine info from `VBoxManage showvminfo`.
@@ -346,7 +348,7 @@
     deferred = Q.defer()
     opts = url.parse @url()
     opts.method = 'HEAD'
-    req = http.request opts, (res) =>
+    req = https.request opts, (res) =>
       res.on 'data', (chunk) ->
       @_uploaded = new Date res.headers['last-modified']
       deferred.resolve @_uploaded
@@ -541,4 +543,4 @@
       Q.delay(delay).then =>
         @waitForNetwork host, retries - 1, delay if retries > 0

-module.exports = IEVM+module.exports = IEVM


changed expected null values to.not.exist

--- workers/social/lib/social/models/user/index.test.coffee
+++ workers/social/lib/social/models/user/index.test.coffee
@@ -118,7 +118,7 @@

         ->
           JUser.convert client, userFormData, (err) ->
-            expect(err).to.be.null
+            expect(err).to.not.exist

             queue.next()

@@ -144,7 +144,7 @@

         ->
           JUser.convert client, userFormData, (err) ->
-            expect(err).to.be.null
+            expect(err).to.not.exist

             queue.next()

@@ -173,7 +173,7 @@

         ->
           JUser.convert client, userFormData, (err) ->
-            expect(err).to.be.null
+            expect(err).to.not.exist

             queue.next()

@@ -181,7 +181,7 @@
           params = { username : userFormData.username }

           JUser.one params, (err, { data : {email, registeredFrom} }) ->
-            expect(err)               .to.be.null
+            expect(err)               .to.not.exist
             expect(email)             .to.be.equal userFormData.email
             expect(registeredFrom.ip) .to.be.equal client.clientIP

@@ -191,7 +191,7 @@
           params = { 'profile.nickname' : userFormData.username }

           JAccount.one params, (err, { data : {profile} }) ->
-            expect(err)             .to.be.null
+            expect(err)             .to.not.exist
             expect(profile.nickname).to.be.equal userFormData.username

             queue.next()


:penguin: Remove extra .. for symlink path

--- build/tasks/install-task.coffee
+++ build/tasks/install-task.coffee
@@ -34,6 +34,6 @@
       # Create relative symbol link for apm.
       process.chdir(binDir)
       rm('apm')
-      fs.symlinkSync(path.join('..', '..', 'share', 'atom', 'resources', 'app', 'apm', 'node_modules', '.bin', 'apm'), 'apm')
+      fs.symlinkSync(path.join('..', 'share', 'atom', 'resources', 'app', 'apm', 'node_modules', '.bin', 'apm'), 'apm')

       fs.chmodSync(path.join(shareDir, 'atom'), "755")


Add option to 'do not show hints'

Add option to 'do not show hints'

Fix #250

--- src/load.coffee
+++ src/load.coffee
@@ -92,7 +92,7 @@

<input class='color' placeholder='Favorite Color' />

       "
-    if world.get('level_name', false)?
+    if world.get('level_name', false)? && splash_allowed()
       $splash.append "
#{world.get 'level_name', false}
"

     if $splash.children().length > 0
@@ -100,11 +100,30 @@
         modal:   true
         buttons: [{text: 'Ok', click: -> $(this).dialog('close')}]
         width:   400
-        close:   ->
-          name  = $splash.find('.name').val()
-          color = $splash.find('.color').val()
-          return unless name? and color?
-          world.send 'store_me', name: name, color: color
+        create:  ->
+          $pane = $splash.dialog('widget').find '.ui-dialog-buttonpane'
+          $pane.prepend "
+
+              Don't show hints
+              <input class='dont-show' type='checkbox' />
+            "
+        beforeClose: ->
+          store_me  world, $splash
+          dont_show world, $splash
+
+splash_allowed = ->
+  !(utils.fetch('hide_dialogs') || document.referrer == location.toString())
+
+store_me = (world, $splash) ->
+  name  = $splash.find('.name').val()
+  color = $splash.find('.color').val()
+  return unless name? and color?
+  world.send 'store_me', name: name, color: color
+
+dont_show = (world, $splash) ->
+  return unless $splash.dialog('widget').find('.dont-show').is(':checked')
+
+  utils.store hide_dialogs: true

 add_stored_properties = (level) ->
   [name, color] = utils.fetch ['name', 'color']


Julia highlighting for markdown opts

Julia highlighting for markdown opts

--- grammars/weave_md.cson
+++ grammars/weave_md.cson
@@ -10,19 +10,17 @@
       'include' : 'source.weave.noweb'
     }
     {
-    'begin': '^([`~]{3,})(\\{|\\{\\.|)(julia)(;|)(.*?)(\\}|)\\s*$'
+    'begin': '^([`~]{3,})(\\{|\\{\\.|)(julia)(;|)\\s*(.*?)(\\}|)\\s*$'
     'beginCaptures':
       '1':
         'name': 'markup.heading.weave.md'
       '3':
         'name': 'markup.bold.weave.md'
       '5':
-        #For some reason highlighting for options doesn't work
-        #with source.julia, cheat using python
-        'contentName' : 'source.python'
+        'contentName' : 'source.julia'
         'patterns': [
           {
-            'include': 'source.python'
+            'include': 'source.julia'
           }
         ]
     'end': '^[`~]{3,}\\s*$'


Inline binding callback

Inline binding callback

--- src/main.coffee
+++ src/main.coffee
@@ -5,9 +5,8 @@

 handleWatchers = {}

-dispatch = (event, handle, path) ->
+binding.setCallback (event, handle, path) ->
   handleWatchers[handle]?.onEvent(event, path)
-binding.setCallback(dispatch)

 class HandleWatcher extends EventEmitter
   constructor: (@path) ->


Checking if auto-launcher is enabled before enable or disable it.

--- src/main.coffee
+++ src/main.coffee
@@ -27,11 +27,15 @@
     name: 'myou-log'

 if settings.open_on_startup
-    auto_launcher.enable().then ()->
-        console.log 'Open on system startup ENABLED'
+    auto_launcher.isEnabled().then (enabled)->
+        if not enabled
+            auto_launcher.enable().then ()->
+                console.log 'Open on system startup ENABLED'
 else
-    console.log 'Open on system startup DISABLED'
-    auto_launcher.disable()
+    auto_launcher.isEnabled().then (enabled)->
+        if enabled
+            auto_launcher.disable().then ()->
+                console.log 'Open on system startup DISABLED'

 {Tray, Menu, app, globalShortcut} = electron.remote
 path = require 'path'


Use event-kit instead of EventEmitter in PathWatcher

--- src/main.coffee
+++ src/main.coffee
@@ -62,13 +62,14 @@
       binding.unwatch(@handle)
       handleWatchers.remove(@handle)

-class PathWatcher extends EventEmitter
+class PathWatcher
   isWatchingParent: false
   path: null
   handleWatcher: null

   constructor: (filePath, callback) ->
     @path = filePath
+    @emitter = new Emitter()

     # On Windows watching a file is emulated by watching its parent folder.
     if process.platform is 'win32'
@@ -88,7 +89,7 @@
         when 'rename', 'change', 'delete'
           @path = newFilePath if event is 'rename'
           callback.call(this, event, newFilePath) if typeof callback is 'function'
-          @emit('change', event, newFilePath)
+          @emitter.emit('did-change', {event, newFilePath})
         when 'child-rename'
           if @isWatchingParent
             @onChange('rename', newFilePath) if @path is oldFilePath
@@ -106,7 +107,11 @@

     @disposable = @handleWatcher.onDidChange(@onChange)

+  onDidChange: (callback) ->
+    @emitter.on('did-change', callback)
+
   close: ->
+    @emitter.dispose()
     @disposable.dispose()
     @handleWatcher.closeIfNoListener()


Remove unneeded return

Remove unneeded return

--- src/main.coffee
+++ src/main.coffee
@@ -67,7 +67,7 @@

 exports.watch = (path, callback) ->
   path = require('path').resolve(path)
-  return new PathWatcher(path, callback)
+  new PathWatcher(path, callback)

 exports.closeAllWatchers = ->
   watcher.close() for handle, watcher of handleWatchers


Explicitly showing zero damage

Explicitly showing zero damage

--- views/battle-detail-area.cjsx
+++ views/battle-detail-area.cjsx
@@ -38,11 +38,8 @@
 HpBar = React.createClass
   render: ->
     {max, now, detla} = @props
-    if now < 0
-      now = 0
-      percent = 0
-    else
-      percent = 100 * now / max
+    now = 0 if now < 0
+    percent = 100 * now / max
     if detla > 0
       label = "#{now} / #{max} (-#{detla})"
     else
@@ -58,10 +55,13 @@
       elements.push {getAttackTypeName @props.type}
       elements.push {" ("}
       for damage, i in @props.damage
-        if damage == 0
+        style = null
+        if @props.hit[i] == HitType.Miss
           damage = "miss"
-        elements.push {damage}
-        elements.push {", "}
+        if @props.hit[i] == HitType.Critical
+          style = {color: "#FFFF00"}
+        elements.push {damage}
+        elements.push {", "}
       elements.pop()  # Remove last comma
       elements.push {")"}
       elements


remove premature optimization

remove premature optimization

--- src/pattern.coffee
+++ src/pattern.coffee
@@ -26,8 +26,6 @@
     @_pattern = _parse pattern

   match: (target) ->
-    @_match ?= memoize (target) =>
-      _match @_pattern, (_parse target)
-    @_match target
+    _match @_pattern, (_parse target)

 module.exports = Pattern


Simplify _check_for_duplicate_signature

Simplify _check_for_duplicate_signature

--- src/mock.coffee
+++ src/mock.coffee
@@ -25,7 +25,7 @@

   args: (args...) ->
     @_check_args_usage(args...)
-    @_check_for_duplicate_signature(args...)
+    @_check_for_duplicate_signature(@current_signature.method_name, args...)
     @current_signature.args = args
     @_set_state("args")
     @
@@ -68,8 +68,8 @@
     @_throw_returns_must_be_after_expects_or_args() unless @_state_in("expects", "args")
     @_throw_returns_usage() unless value?

-  _check_for_duplicate_signature: (args...) ->
-    @_throw_duplicate_expectation("#{@current_signature.method_name}(#{args})") if @_find_signature(@current_signature.method_name, args...)
+  _check_for_duplicate_signature: (method_name, args...) ->
+    @_throw_duplicate_expectation("#{method_name}(#{args})") if @_find_signature(method_name, args...)

   _check_for_uncalled_signatures: ->
     messages = ""


Improve code aesthetic

Improve code aesthetic

--- src/neat.coffee
+++ src/neat.coffee
@@ -29,20 +29,20 @@
     @initPath = @INIT_PATH = 'lib/config/initializers'
     # `PATHS` will stores the various paths into which Neat will look
     # when searching files.
-    @paths    = @PATHS     = [@neatRoot]
+    @paths = @PATHS = [@neatRoot]
     # The environment object is defined asynchronously through
     # the `initEnvironment` or the `setEnvironment` methods.
-    @env      = @ENV       = null
+    @env = @ENV = null
     # The `.neat` file at the root of a project contains the metadata
     # for the project. In the case of Neat, the `.neat` file is loaded
     # and available in `Neat.meta`.
-    @meta     = @META      = @loadMeta @neatRoot
+    @meta = @META = @loadMeta @neatRoot

     if @root?
       @discoverUserPaths()
       # The current project meta are available through `Neat.project`
       # or `Neat.PROJECT`.
-      @project  = @PROJECT   = @loadMeta @root
+      @project = @PROJECT = @loadMeta @root

   ##### Neat::require


Print a special message when they publish for the first time

--- src/publish.coffee
+++ src/publish.coffee
@@ -99,7 +99,7 @@
         if error?
           callback(error)
         else
-          callback(null, response.statusCode is 404)
+          callback(null, response.statusCode is 200)

   # Parse the repository in `name/owner` format from the package metadata.
   #
@@ -182,7 +182,7 @@
       callback('Unable to parse repository name/owner from package.json repository field')
       return

-    publishNewVersion = =>
+    publishNewVersion = (firstTime) =>
       process.stdout.write "Publishing #{pack.name}@#{tag} "
       @createPackageVersion pack.name, tag, (error) ->
         if error?
@@ -190,6 +190,15 @@
           callback(error)
         else
           process.stdout.write '\u2713\n'.green
+
+          if firstTime
+            process.stdout.write 'Congrats on publishing a new package!'.rainbow
+            # :+1: :package: :tada when available
+            if process.platform is 'darwin'
+              process.stdout.write ' \uD83D\uDC4D  \uD83D\uDCE6  \uD83C\uDF89'
+
+            process.stdout.write "\nCheck it out at https://atom.io/packages/#{pack.name}\n"
+
           callback()

     @packageExists pack.name, (error, exists) =>
@@ -198,16 +207,16 @@
         return

       if exists
-        process.stdout.write "Registering #{pack.name} (#{repository}) "
+        publishNewVersion()
+      else
+        process.stdout.write "Registering #{pack.name} "
         @registerPackage repository, (error) =>
           if error?
             process.stdout.write '\u2717\n'.red
             callback(error)
           else
             process.stdout.write '\u2713\n'.green
-            publishNewVersion()
-      else
-        publishNewVersion()
+            publishNewVersion(true)

   # Run the publish command with the given options
   run: (options) ->


switch partyVol filter from select to span, wip

--- web/site/search.coffee
+++ web/site/search.coffee
@@ -306,10 +306,7 @@

     $scope.partyVolBoxClick = ->
       console.log($scope.selectedType, $scope.selectedType.join(" "))
-      if $scope.selectedType.join(" ").includes($scope.volumeDisplayStr)
-        $scope.query = $scope.originalQuery
-        $scope.search()
-      if $scope.selectedType.join(" ").includes($scope.partyDisplayStr)
+      if $scope.selectedType.join(" ").includes($scope.volumeDisplayStr) || $scope.selectedType.join(" ").includes($scope.partyDisplayStr)
         $scope.query = $scope.originalQuery
         $scope.search()
       console.log($scope.selectedType, $scope.filterDisplay)


Update Atom config

Update Atom config

--- home/.atom/config.cson
+++ home/.atom/config.cson
@@ -1,7 +1,7 @@
 'exception-reporting':
   'userId': '70a0032d-3fb2-4bcb-e887-64623e256e19'
 'release-notes':
-  'viewedVersion': '0.73.0'
+  'viewedVersion': '0.78.0'
 'welcome':
   'showOnStartup': false
 'metrics':
@@ -23,19 +23,9 @@
   ]
   'disabledPackages': [
     'autosave'
-    'language-c'
-    'language-java'
-    'language-make'
-    'language-objective-c'
-    'language-perl'
-    'language-property-list'
-    'language-ruby-on-rails'
-    'language-toml'
     'vim-mode'
-    'symbols-view'
     'command-logger'
     'archive-view'
-    'whitespace'
     'autoflow'
     'bookmarks'
     'grammar-selector'
@@ -45,6 +35,12 @@
     'spell-check'
     'styleguide'
     'welcome'
+    'background-tips'
+    'bracket-matcher'
+    'dev-live-reload'
+    'keybinding-resolver'
+    'link'
+    'timecop'
   ]
   'audioBeep': false
   'projectHome': '/Users/francesc/src'
@@ -66,3 +62,7 @@
 'autoclose-html':
   'closeOnEndOfOpeningTag': true
   'forceInline': 'div, span, title, h1, h2, h3, h4, h5, h6'
+'autocomplete':
+  'includeCompletionsFromAllBuffers': true
+'tree-view':
+  'hideIgnoredNames': true


Update .atom/config.cson with automatic format updates.

Atom updates occasionally change the formatting of config files, as is
the case here.

--- home/.atom/config.cson
+++ home/.atom/config.cson
@@ -11,8 +11,7 @@
     fontSize: 11
     showInvisibles: true
     showIndentGuide: true
-    invisibles:
-      {}
+    invisibles: {}
   core:
     disabledPackages: [
       "metrics"
@@ -27,10 +26,8 @@
     showErrorInline: true
   "go-plus":
     goPath: "~/.go"
-  "tree-view":
-    {}
-  "autocomplete-plus":
-    {}
+  "tree-view": {}
+  "autocomplete-plus": {}
   "file-types":
     "^.gvimrc.after": "viml"
     "^.profile$": "shell"