Tests: Enable openFile test.

Tests: Enable openFile test.

--- tests/src/ide/file.coffee
+++ tests/src/ide/file.coffee
@@ -7,28 +7,28 @@
 module.exports =

-  # openFile: (browser) ->
+  openFile: (browser) ->

-  #   user = helpers.beginTest(browser)
-  #   helpers.waitForVMRunning(browser)
+    user = helpers.beginTest(browser)
+    helpers.waitForVMRunning(browser)

-  #   helpers.openFolderContextMenu(browser, user, 'Web')
+    helpers.openFolderContextMenu(browser, user, 'Web')

-  #   webPath       = '/home/' + user.username + '/Web'
-  #   indexSelector = "span[title='" + webPath + '/index.html' + "']"
+    webPath       = '/home/' + user.username + '/Web'
+    indexSelector = "span[title='" + webPath + '/index.html' + "']"

-  #   browser
-  #     .waitForElementVisible   'li.expand', 15000
-  #     .click                   'li.expand'
-  #     .waitForElementVisible   indexSelector, 15000
-  #     .click                   indexSelector
-  #     .click                   indexSelector + ' + .chevron'
-  #     .waitForElementVisible   'li.open-file', 20000
-  #     .click                   'li.open-file'
-  #     .waitForElementVisible   '.indexhtml',   20000 # Assertion
-  #     .waitForElementVisible   '.ace_content', 20000 # Assertion
-  #     .assert.containsText     '.ace_content', 'Hello World from HTML by Koding' # Assertion
-  #     .end()
+    browser
+      .waitForElementVisible   'li.expand', 15000
+      .click                   'li.expand'
+      .waitForElementVisible   indexSelector, 15000
+      .click                   indexSelector
+      .click                   indexSelector + ' + .chevron'
+      .waitForElementVisible   'li.open-file', 20000
+      .click                   'li.open-file'
+      .waitForElementVisible   '.indexhtml',   20000 # Assertion
+      .waitForElementVisible   '.ace_content', 20000 # Assertion
+      .assert.containsText     '.ace_content', 'Hello World from HTML by Koding' # Assertion
+      .end()

   createFile: (browser) ->


remove commented out block

remove commented out block

--- tutor/src/components/task-step/exercise.cjsx
+++ tutor/src/components/task-step/exercise.cjsx
@@ -86,31 +86,6 @@
     else
       @setState(@getPartsInfo(nextProps))

-  # renderHelpLink: (sections) ->
-  #   return null unless sections? and not _.isEmpty(sections)
-  #   {courseId} = @props
-
-  #   sectionsLinks = _.chain sections
-  #     .map (section) =>
-  #       combined = @sectionFormat(section.chapter_section)
-  #       <BrowseTheBook
-  #         unstyled
-  #         key={combined}
-  #         section={combined}
-  #         courseId={courseId}
-  #         onlyShowBrowsable={false}>
-  #         {combined} {section.title} <i className='fa fa-external-link' />
-  #       </BrowseTheBook>
-  #     .compact()
-  #     .value()
-
-  #   helpLink =
-  #     <div key='task-help-links' className='task-help-links'>
-  #       Comes from&nbsp&nbsp{sectionsLinks}
-  #     </div>
-
-  #   if sectionsLinks.length > 0 then helpLink
-
   stopListeningForProgress: (props) ->
     props ?= @props
     {taskId} = props


wrapper libs list

wrapper libs list

--- natal.coffee
+++ natal.coffee
@@ -24,6 +24,12 @@
 rnPackagerPort  = 8081
 podMinVersion   = '0.38.2'
 process.title   = 'natal'
+
+wrapperLibs =
+  om:        'org.omcljs/om "0.9.0"'
+  'om-next': 'org.omcljs/om "1.0.0-alpha11"'
+
+libNames = Object.keys wrapperLibs

 log = (s, color = 'green') ->


Embed history in form

Embed history in form

--- client/app/Applications/Groups.kdapplication/Views/paymentsettingsview.coffee
+++ client/app/Applications/Groups.kdapplication/Views/paymentsettingsview.coffee
@@ -43,13 +43,8 @@
           click             : =>
             @updateBillingInfo group
         history             :
+          type              : "hidden"
           label             : "History"
-          tagName           : "a"
-          partial           : "Show Payment History"
-          itemClass         : KDCustomHTMLView
-          cssClass          : "billing-link"
-          click             : =>
-            new GroupPaymentHistoryModal {group}
         sharedVM            :
           label             : "Shared VM"
           itemClass         : KDOnOffSwitch
@@ -101,6 +96,19 @@

     @settingsForm = new KDFormViewWithFields formOptions, group

+    # Embed list
+    @dbController = new GroupPaymentHistoryListController
+      group     : group
+      itemClass : AccountPaymentHistoryListItem
+
+    dbList = @dbController.getListView()
+
+    dbListForm = @settingsForm.fields.history
+    dbListForm.addSubView @dbController.getView()
+
+    @dbController.loadItems()
+    # Embed done
+
     @getBillingInfo group

     group.fetchBundle (err, bundle)=>


cleaned up trailing whitespace; merging @geraldalewis's #2033

--- nodes.coffee
+++ nodes.coffee
@@ -918,15 +918,13 @@
         child.expressions = exps = flatten exps

   # `use strict` (and other directives) must be the first expression statement(s)
-  # of a function body. This method ensures the prologue is correctly positioned
+  # of a function body. This method ensures the prologue is correctly positioned
   # above the `constructor`.
   hoistDirectivePrologue: ->
     index = 0
     {expressions} = @body
-    ++index while (node = expressions[index]) and
-      node instanceof Comment or
-      node instanceof Value and
-      node.isString()
+    ++index while (node = expressions[index]) and node instanceof Comment or
+      node instanceof Value and node.isString()
     @directives = expressions.splice 0, index

   # Make sure that a constructor is defined for the class, and properly


Merging type, children and statement functions

--- nodes.coffee
+++ nodes.coffee
@@ -16,19 +16,17 @@
 # Import the helpers we plan to use.
 {compact, flatten, merge, del, index_of}: helpers

-type: (klass, name) ->
-  klass::constructor_name: name
-
-# Helper function that marks a node as a JavaScript *statement*, or as a
-# *pure_statement*. Statements must be wrapped in a closure when used as an
-# expression, and nodes tagged as *pure_statement* cannot be closure-wrapped
-# without losing their meaning.
-statement: (klass, only) ->
-  klass::is_statement: -> true
-  (klass::is_pure_statement: -> true) if only
-
-children: (klass, child_attrs...) ->
-  klass::children_attributes: child_attrs
+# Helper function that registers a node class. If `is_statement` is passed,
+# marks the node as a JavaScript *statement*, or as a *pure_statement*.
+# Statements must be wrapped in a closure when used as an expression, and
+# nodes tagged as *pure_statement* cannot be closure-wrapped without losing
+# their meaning.
+register: (klass, o) ->
+  o: or {}
+  klass::constructor_name: o.name
+  (klass::is_statement: -> true) if o.is_statement
+  (klass::is_pure_statement: -> true) if o.is_pure_statement
+  (klass::children_attributes: o.children) if o.children

 #### BaseNode

@@ -139,14 +137,17 @@
       func.apply(this, arguments)
       child.traverse_children(cross_scope, func) if child instanceof BaseNode

-  # Default implementations of the common node identification methods. Nodes
+  # Default implementations of the common node properties and methods. Nodes
   # will override these with custom logic, if needed.
+  constructor_name:        'BaseNode'
+  children_attributes:     []
+
   unwrap:               -> this
   is_statement:         -> false
   is_pure_statement:    -> false
   top_sensitive:        -> false

-type BaseNode, 'BaseNode'
+register BaseNode, {name: 'BaseNode'}

 #### Expressions

@@ -226,9 +227,7 @@
   return nodes[0] if nodes.length is 1 and nodes[0] instanceof Expressions
   new Expressions(nodes)

-type Expressions, 'Expressions'
-children Expressions, 'expressions'
-statement Expressions
+register Expressions, {name: 'Expressions', is_statement: yes, children: ['expressions']}

 #### LiteralNode

@@ -254,7 +253,7 @@
   toString: (idt) ->
     " \"$@value\""

-type LiteralNode, 'LiteralNode'
+register LiteralNode, {name: 'LiteralNode'}

 #### ReturnNode

@@ -275,9 +274,7 @@
     o.as_statement: true if @expression.is_statement()
     "${@tab}return ${@expression.compile(o)};"

-type ReturnNode, 'ReturnNode'
-statement ReturnNode, true
-children ReturnNode, 'expression'
+register ReturnNode, {name: 'ReturnNode', is_statement: yes, is_pure_statement: yes, children: ['expression']}

 #### ValueNode

@@ -359,8 +356,7 @@

     if op and @wrapped then "($complete)" else complete

-type ValueNode, 'ValueNode'
-children ValueNode, 'base', 'properties'
+register ValueNode, {name: 'ValueNode', children: ['base', 'properties']}

 #### CommentNode

@@ -383,8 +379,7 @@
     else
       "$@tab//" + @lines.join("\n$@tab//")

-type CommentNode, 'CommentNode'
-statement CommentNode
+register CommentNode, {name: 'CommentNode', is_statement: yes}

 #### CallNode

@@ -443,8 +438,7 @@
       meth: "($temp = ${ @variable.source })${ @variable.last }"
     "${@prefix()}${meth}.apply($obj, ${ @compile_splat_arguments(o) })"

-type CallNode, 'CallNode'
-children CallNode, 'variable', 'args'
+register CallNode, {name: 'CallNode', children: ['variable', 'args']}

 #### CurryNode

@@ -469,8 +463,7 @@
     ref: new ValueNode literal utility 'bind'
     (new CallNode(ref, [@meth, @context, literal(@arguments(o))])).compile o

-type CurryNode, 'CurryNode'
-children CurryNode, 'meth', 'context', 'args'
+register CurryNode, {name: 'CurryNode', children: ['meth', 'context', 'args']}

 #### ExtendsNode

@@ -488,8 +481,7 @@
     ref:  new ValueNode literal utility 'extends'
     (new CallNode ref, [@child, @parent]).compile o

-type ExtendsNode, 'ExtendsNode'
-children ExtendsNode, 'child', 'parent'
+register ExtendsNode, {name: 'ExtendsNode', children: ['child', 'parent']}

 #### AccessorNode

@@ -508,8 +500,7 @@
     proto_part: if @prototype then 'prototype.' else ''
     ".$proto_part${@name.compile(o)}"

-type AccessorNode, 'AccessorNode'
-children AccessorNode, 'name'
+register AccessorNode, {name: 'AccessorNode', children: ['name']}

 #### IndexNode

@@ -525,8 +516,7 @@
     idx: @index.compile o
     "[$idx]"

-type IndexNode, 'IndexNode'
-children IndexNode, 'index'
+register IndexNode, {name: 'IndexNode', children: ['index']}

 #### RangeNode

@@ -570,9 +560,7 @@
     arr:  Expressions.wrap([new ForNode(body, {source: (new ValueNode(this))}, literal(name))])
     (new ParentheticalNode(new CallNode(new CodeNode([], arr.make_return())))).compile(o)

-type RangeNode, 'RangeNode'
-children RangeNode, 'from', 'to'
-
+register RangeNode, {name: 'RangeNode', children: ['from', 'to']}

 #### SliceNode

@@ -591,8 +579,7 @@
     plus_part:  if @range.exclusive then '' else ' + 1'
     ".slice($from, $to$plus_part)"

-type SliceNode, 'SliceNode'
-children SliceNode, 'range'
+register SliceNode, {name: 'SliceNode', children: ['range']}

 #### ObjectNode

@@ -620,8 +607,7 @@
     inner: if props then '\n' + props + '\n' + @idt() else ''
     "{$inner}"

-type ObjectNode, 'ObjectNode'
-children ObjectNode, 'properties'
+register ObjectNode, {name: 'ObjectNode', children: ['properties']}

 #### ArrayNode

@@ -651,8 +637,7 @@
     else
       "[$objects]"

-type ArrayNode, 'ArrayNode'
-children ArrayNode, 'objects'
+register ArrayNode, {name: 'ArrayNode', children: ['objects']}

 #### ClassNode

@@ -707,9 +692,7 @@
     returns:   if @returns      then new ReturnNode(@variable).compile(o)  else ''
     "$construct$extension$props$returns"

-type ClassNode, 'ClassNode'
-statement ClassNode
-children ClassNode, 'variable', 'parent', 'properties'
+register ClassNode, {name: 'ClassNode', is_statement: yes, children: ['variable', 'parent', 'properties']}

 #### AssignNode

@@ -810,8 +793,7 @@
     val:    @value.compile(o)
     "${name}.splice.apply($name, [$from, $to].concat($val))"

-type AssignNode, 'AssignNode'
-children AssignNode, 'variable', 'value'
+register AssignNode, {name: 'AssignNode', children: ['variable', 'value']}

 #### CodeNode

@@ -876,8 +858,7 @@
     children: (child.toString(idt + TAB) for child in @children()).join('')
     "\n$idt$children"

-type CodeNode, 'CodeNode'
-children CodeNode, 'params', 'body'
+register CodeNode, {name: 'CodeNode', children: ['params', 'body']}

 #### SplatNode

@@ -933,8 +914,7 @@
       i: + 1
     args.join('')

-type SplatNode, 'SplatNode'
-children SplatNode, 'name'
+register SplatNode, {name: 'SplatNode', children: ['name']}

 #### WhileNode

@@ -982,9 +962,7 @@
       post: ''
     "$pre {\n${ @body.compile(o) }\n$@tab}$post"

-type WhileNode, 'WhileNode'
-statement WhileNode
-children WhileNode, 'condition', 'guard', 'body'
+register WhileNode, {name: 'WhileNode', is_statement: yes, children: ['condition', 'guard', 'body']}

 #### OpNode

@@ -1063,8 +1041,7 @@
     parts: parts.reverse() if @flip
     parts.join('')

-type OpNode, 'OpNode'
-children OpNode, 'first', 'second'
+register OpNode, {name: 'OpNode', children: ['first', 'second']}

 #### TryNode

@@ -1094,9 +1071,7 @@
     finally_part: (@ensure or '') and ' finally {\n' + @ensure.compile(merge(o)) + "\n$@tab}"
     "${@tab}try {\n$attempt_part\n$@tab}$catch_part$finally_part"

-type TryNode, 'TryNode'
-statement TryNode
-children TryNode, 'attempt', 'recovery', 'ensure'
+register TryNode, {name: 'TryNode', is_statement: true, children: ['attempt', 'recovery', 'ensure']}

 #### ThrowNode

@@ -1113,9 +1088,7 @@
   compile_node: (o) ->
     "${@tab}throw ${@expression.compile(o)};"

-type ThrowNode, 'ThrowNode'
-statement ThrowNode
-children ThrowNode, 'expression'
+register ThrowNode, {name: 'ThrowNode', is_statement: true, children: ['expression']}

 #### ExistenceNode

@@ -1140,8 +1113,7 @@
     [first, second]: [first.compile(o), second.compile(o)]
     "(typeof $first !== \"undefined\" && $second !== null)"

-type ExistenceNode, 'ExistenceNode'
-children ExistenceNode, 'expression'
+register ExistenceNode, {name: 'ExistenceNode', children: ['expression']}

 #### ParentheticalNode

@@ -1168,8 +1140,7 @@
     code: code.substr(o, l-1) if code.substr(l-1, 1) is ';'
     if @expression instanceof AssignNode then code else "($code)"

-type ParentheticalNode, 'ParentheticalNode'
-children ParentheticalNode, 'expression'
+register ParentheticalNode, {name: 'ParentheticalNode', children: ['expression']}

 #### ForNode

@@ -1253,9 +1224,7 @@
     close:          if @object then '}}' else '}'
     "$set_result${source_part}for ($for_part) {\n$var_part$body\n$@tab$close$return_result"

-type ForNode, 'ForNode'
-statement ForNode
-children ForNode, 'body', 'source', 'guard'
+register ForNode, {name: 'ForNode', is_statement: yes, children: ['body', 'source', 'guard']}

 #### IfNode

@@ -1358,10 +1327,7 @@
     else_part:  if @else_body then @else_body_node().compile(o) else 'null'
     "$if_part : $else_part"

-
-type IfNode, 'IfNode'
-children IfNode, 'condition', 'body', 'else_body', 'assigner'
-
+register IfNode, {name: 'IfNode', children: ['condition', 'body', 'else_body', 'assigner']}

 # Faux-Nodes
 # ----------


merging master changes into symbology

merging master changes into symbology

--- nodes.coffee
+++ nodes.coffee
@@ -185,12 +185,6 @@
     @expressions[idx] = last.makeReturn()
     this

-  # A bound function uses a local `_this` variable instead of the real `this`.
-  rewriteThis: ->
-    @traverseChildren false, (child) ->
-      if child instanceof ValueNode and child.base.value is 'this'
-        child.base = literal '_this'
-
   # An **Expressions** is the only node that can serve as the root.
   compile: (o) ->
     o or= {}
@@ -204,12 +198,12 @@
   # It would be better not to generate them in the first place, but for now,
   # clean up obvious double-parentheses.
   compileRoot: (o) ->
-    o.indent = @tab = if o.noWrap then '' else TAB
-    o.scope = new Scope(null, this, null)
-    code = @compileWithDeclarations(o)
-    code = code.replace(TRAILING_WHITESPACE, '')
-    code = code.replace(DOUBLE_PARENS, '($1)')
-    if o.noWrap then code else "(function(){\n$code\n})();\n"
+    o.indent  = @tab = if o.noWrap then '' else TAB
+    o.scope   = new Scope(null, this, null)
+    code      = @compileWithDeclarations(o)
+    code      = code.replace(TRAILING_WHITESPACE, '')
+    code      = code.replace(DOUBLE_PARENS, '($1)')
+    if o.noWrap then code else "(function() {\n$code\n})();\n"

   # Compile the expressions body for the contents of a function, with
   # declarations of all inner variables pushed up to the top.
@@ -459,7 +453,7 @@
       utility 'extends'
       """
       (function() {
-      ${@idt(1)}var ctor = function(){ };
+      ${@idt(1)}var ctor = function(){};
       ${@idt(1)}__extends(ctor, $meth);
       ${@idt(1)}return ${meth}.apply(new ctor, ${ @compileSplatArguments(o) });
       $@tab}).call(this)
@@ -589,8 +583,8 @@
     else
       clause = "$@fromVar <= $@toVar ?"
       body   = "var $i = $@fromVar; $clause $i <$@equals $@toVar : $i >$@equals $@toVar; $clause $i += 1 : $i -= 1"
-    post =  "{ ${result}.push($i) };\n${idt}return $result;\n$o.indent"
-    "(function(){${pre}\n${idt}for ($body)$post}).call(this)"
+    post     = "{ ${result}.push($i) };\n${idt}return $result;\n$o.indent"
+    "(function() {${pre}\n${idt}for ($body)$post}).call(this)"

 #### SliceNode

@@ -764,7 +758,10 @@
     @variable instanceof ValueNode

   makeReturn: ->
-    return new Expressions [this, new ReturnNode(@variable)]
+    if @isStatement()
+      return new Expressions [this, new ReturnNode(@variable)]
+    else
+      super()

   isStatement: ->
     @isValue() and (@variable.isArray() or @variable.isObject())
@@ -866,7 +863,7 @@
     top         = del o, 'top'
     o.scope     = sharedScope or new Scope(o.scope, @body, this)
     o.top       = true
-    o.indent    = @idt(if @bound then 2 else 1)
+    o.indent    = @idt(1)
     del o, 'noWrap'
     del o, 'globals'
     i = 0
@@ -886,13 +883,11 @@
       i += 1
     params = (param.compile(o) for param in params)
     @body.makeReturn()
-    @body.rewriteThis() if @bound
     (o.scope.parameter(param)) for param in params
     code = if @body.expressions.length then "\n${ @body.compileWithDeclarations(o) }\n" else ''
-    func = "function(${ params.join(', ') }) {$code${ code and @idt(if @bound then 1 else 0) }}"
-    func = "($func)" if top and not @bound
-    return func unless @bound
-    "(function(_this) {\n${@idt(1)}return $func\n$@tab})(this)"
+    func = "function(${ params.join(', ') }) {$code${ code and @tab }}"
+    return "${utility('bind')}($func, this)" if @bound
+    if top then "($func)" else func

   topSensitive: ->
     true
@@ -927,14 +922,17 @@
   compileParam: (o) ->
     name = @name.compile(o)
     o.scope.find name
-    len = o.scope.freeVariable()
-    o.scope.assign len, "arguments.length"
-    variadic = o.scope.freeVariable()
-    o.scope.assign variadic, "$len >= $@arglength"
-    for trailing, idx in @trailings
-      pos = @trailings.length - idx
-      o.scope.assign(trailing.compile(o), "arguments[$variadic ? $len - $pos : ${@index + idx}]")
-    "$name = ${utility('slice')}.call(arguments, $@index, $len - ${@trailings.length})"
+    end = ''
+    if @trailings.length
+      len = o.scope.freeVariable()
+      o.scope.assign len, "arguments.length"
+      variadic = o.scope.freeVariable()
+      o.scope.assign variadic, "$len >= $@arglength"
+      end = if @trailings.length then ", $len - ${@trailings.length}"
+      for trailing, idx in @trailings
+        pos = @trailings.length - idx
+        o.scope.assign(trailing.compile(o), "arguments[$variadic ? $len - $pos : ${@index + idx}]")
+    "$name = ${utility('slice')}.call(arguments, $@index$end)"

   # A compiling a splat as a destructuring assignment means slicing arguments
   # from the right-hand-side's corresponding array.
@@ -1487,7 +1485,7 @@
   # [goog.inherits](http://closure-library.googlecode.com/svn/docs/closureGoogBase.js.source.html#line1206).
   extends:  """
             function(child, parent) {
-                var ctor = function(){ };
+                var ctor = function(){};
                 ctor.prototype = parent.prototype;
                 child.prototype = new ctor();
                 child.prototype.constructor = child;
@@ -1496,6 +1494,13 @@
               }
             """

+  # Create a function bound to the current value of "this".
+  bind: """
+        function(func, context) {
+            return function(){ return func.apply(context, arguments); };
+          }
+        """
+
   # Shortcuts to speed up the lookup time for native functions.
   hasProp: 'Object.prototype.hasOwnProperty'
   slice:   'Array.prototype.slice'


Issue #1354, 'in' with splatted arrays.

Issue #1354, 'in' with splatted arrays.

--- nodes.coffee
+++ nodes.coffee
@@ -1355,7 +1355,9 @@
   invert: NEGATE

   compileNode: (o) ->
-    if @array instanceof Value and @array.isArray()
+    isArray = @array instanceof Value and @array.isArray()
+    splat   = obj for obj in @array.base.objects when obj instanceof Splat if isArray
+    if isArray and not splat
       @compileOrTest o
     else
       @compileLoopTest o


First draft at loop block scoping again ... works for functions that mention 'this'

--- nodes.coffee
+++ nodes.coffee
@@ -1290,13 +1290,15 @@
   compileNode: (o) ->
     {scope} = o
     {body}  = this
+    hasCode = @body.contains (node) -> node instanceof Code
     name    = not @pattern and @name?.compile o
     index   = @index?.compile o
-    ivar    = if not index then scope.freeVariable 'i' else index
+    ivar    = if not index or hasCode then scope.freeVariable 'i' else index
     varPart = guardPart = defPart = retPart = ''
     idt     = @idt 1
-    scope.find(name,  yes) if name
-    scope.find(index, yes) if index
+    unless hasCode
+      scope.find(name,  yes) if name
+      scope.find(index, yes) if index
     [step, pvar] = @step.compileLoopReference o, 'step' if @step
     if @from
       [tail, tvar] = @to.compileLoopReference o, 'to'
@@ -1334,6 +1336,7 @@
         when  1 then '++'
         when -1 then '--'
         else (if pvar < 0 then ' -= ' + pvar.slice 1 else ' += ' + pvar)
+    body    = Closure.wrap(body, yes) if hasCode
     varPart = idt + namePart + ';\n' if namePart
     defPart += @pluckDirectCall o, body, name, index unless @pattern
     code = guardPart + varPart
@@ -1355,11 +1358,11 @@
       expr = expr.unwrapAll()
       continue unless expr instanceof Call
       val = expr.variable.unwrapAll()
-      continue unless val instanceof Code and not expr.args.length or
-        val instanceof Value and val.base instanceof Code and
+      continue unless (val instanceof Code and not expr.args.length) or
+        (val instanceof Value and val.base.unwrapAll() instanceof Code and
         val.properties.length is 1 and
-        val.properties[0].name?.value is 'call'
-      fn    = val.base or val
+        val.properties[0].name?.value is 'call')
+      fn    = val.base.unwrapAll() or val
       ref   = new Literal o.scope.freeVariable 'fn'
       base  = new Value ref
       args  = compact [name, index]


use a temp var for range expansion, instead of 'i'

--- nodes.coffee
+++ nodes.coffee
@@ -450,8 +450,9 @@
   # part of a comprehension, slice, or splice.
   # TODO: This generates pretty ugly code ... shrink it.
   compile_array: (o) ->
-    body: Expressions.wrap([new LiteralNode('i')])
-    arr:  Expressions.wrap([new ForNode(body, {source: (new ValueNode(this))}, new LiteralNode('i'))])
+    name: o.scope.free_variable()
+    body: Expressions.wrap([new LiteralNode(name)])
+    arr:  Expressions.wrap([new ForNode(body, {source: (new ValueNode(this))}, new LiteralNode(name))])
     (new ParentheticalNode(new CallNode(new CodeNode([], arr)))).compile(o)

 }


fixes to cachebuilder - filenames, kiosk url, escape ~

--- cache_builder/cb.coffee
+++ cache_builder/cb.coffee
@@ -26,18 +26,18 @@
 data = fs.readFileSync atomfn, 'utf8'
 console.log 'read '+data.length+' bytes'

-# try reading shorturls.js
+# try reading shorturls.json
 shorturls = []
-shorturlsfn = 'shorturls.js'
+shorturlsfn = 'shorturls.json'
 try
   shorturlsdata = fs.readFileSync shorturlsfn,'utf8'
   shorturls = JSON.parse shorturlsdata
 catch e
   console.log 'could not read '+shorturlsfn+': '+e

-# try reading cache.js
+# try reading cache.json
 cache = {}
-cachefn = 'cache.js'
+cachefn = 'cache.json'
 try
   cachedata = fs.readFileSync cachefn,'utf8'
   cache = JSON.parse cachedata
@@ -54,13 +54,16 @@
     # work out shorturl later
     shorturls.push { url: url }

-get_baseurl = (feed) ->
-  baseurl = for link in feed.link when link.$.rel == 'self'
+get_feedurl = (feed) ->
+  feedurl = for link in feed.link when link.$.rel == 'self'
     link.$.href
-  if baseurl.length < 1
+  if feedurl.length < 1
     console.log 'No self link found - cannot work out shorturls'
     process.exit -1
-  baseurl = baseurl[0]
+  return feedurl[0]
+
+get_baseurl = (feed) ->
+  baseurl = get_feedurl feed
   ix = baseurl.lastIndexOf '/'
   baseurl = baseurl.slice 0,ix+1
   console.log 'Base URL = '+baseurl
@@ -69,11 +72,16 @@
 # shorturl for each
 make_shorturls = (feed,shorturls) ->
   console.log 'make_shorturls...'
-  # TODO

   # atom url -> get url
   baseurl = get_baseurl feed
   geturl = baseurl+'get.html'
+
+  # request a short-url for internet kiosk view
+  feedurl =get_feedurl feed
+  kioskurl = baseurl+'kiosk.html?f='+encodeURIComponent(feedurl)
+  url = geturl+'?u='+encodeURIComponent(kioskurl)+'&t='+encodeURIComponent("Kiosk View")
+  add_shorturl shorturls,url

   # work out URLs to be shortened
   # get.html?u=URL&t=TITLE&a=HELPERURL...
@@ -150,6 +158,13 @@
   # un-needed files in cache?
   for oldfile in oldfiles when oldfile.path? and not oldfile.needed
     cache.files.push oldfile
+
+get_filename_for_component = (h) ->
+  if h==''
+    return '_'
+  h = encodeURIComponent h
+  return h.replace("~","_")
+  # is that enough??

 # get local cache path for an URL - like java cacheing,
 # maps domain name elements and path elements to folders
@@ -175,7 +190,7 @@
   hs = ["cache"].concat hs,ps
   # make safe filenames
   hs = for h in hs
-    if h=='' then '_' else encodeURIComponent h # is that enough??
+    get_filename_for_component h
   path = hs.join '/'
   return path

@@ -193,7 +208,7 @@
   fix_shorturls = (shorturls,i) ->
     if i >= shorturls.length
       # done
-      console.log 'write shorturls.js'
+      console.log 'write shorturls.json'
       fs.writeFileSync shorturlsfn,JSON.stringify shorturls
     else
       su = shorturls[i]
@@ -251,7 +266,7 @@
   fix_cache = (cache,ix) ->
     if ix >= cache.files.length
       # done!
-      console.log 'write cache.js'
+      console.log 'write cache.json'
       fs.writeFileSync cachefn,JSON.stringify cache
     else
       file = cache.files[ix]


Do not show command in tree-view

Do not show command in tree-view

Scope command `atom-csscomb:execute` just to the text editor

--- menus/csscomb.cson
+++ menus/csscomb.cson
@@ -1,5 +1,5 @@
 'context-menu':
-  'atom-workspace': [{
+  'atom-text-editor': [{
     label: 'Sort CSS properties'
     command: 'atom-csscomb:execute'
   }]


client: increase disconnected check intervals

--- client/Main/main.coffee
+++ client/Main/main.coffee
@@ -148,15 +148,15 @@

   if window.navigator.onLine?
-    KD.utils.repeat 5000, ->
-      unless window.navigator.onLine
+    KD.utils.repeat 10000, ->
+      if window.navigator.onLine
+        destroyCurrentModal()
+      else
         showModal "small", "disconnected"  unless currentModal
-      else
-        destroyCurrentModal()
   else
     window.connectionCheckerReponse = ->

-    KD.utils.repeat 5000, ->
+    KD.utils.repeat 30000, ->
       item = new ConnectionChecker {
         jsonp       : "connectionCheckerReponse"
         crossDomain : yes


Do not show notifications for initial messages.

Fixes #10

--- client/chanslate.coffee
+++ client/chanslate.coffee
@@ -39,10 +39,15 @@
 Template.showMessages.helpers({
     messages: ->
         cursor = ChanslateMessages.find({}, {sort: { at: 1 }})
-        cursor.observe({ added: ->
-            scrollToBottom()
-            if not isInputFocussed and Session.get('haveNotificationPermission')
-                pendingMessagesNotification.show()
+        cursor.observe({
+            # Avoids scrolling to the bottom immediately after site loads and
+            # the associated notifications.
+            _suppress_initial: true
+            added: ->
+                scrollToBottom()
+                havePermission = Session.get('haveNotificationPermission')
+                if not isInputFocussed and havePermission
+                    pendingMessagesNotification.show()
         })
         cursor


Whitespace

Whitespace

--- client/clonewars.coffee
+++ client/clonewars.coffee
@@ -28,7 +28,6 @@
 Template.fileList.helpers
   'files': -> Session.get 'files'

-
 store = new FS.Store.S3 'files',
   folder: Session.get 'username'
 Files = new FS.Collection 'files', stores: [store]


Sort groups by name

Sort groups by name

--- client/frontpage.coffee
+++ client/frontpage.coffee
@@ -1,6 +1,7 @@
 Template.frontpage.helpers
   groups: ->
-    Groups.find()
+    Groups.find {},
+      sort: [['name', 'asc']]
   groupcount: ->
     Groups.find().count()
   canSuper: ->


put back loader

put back loader

--- BackofficeBundle/Resources/public/coffee/mediatheque/mediaModalListeners.coffee
+++ BackofficeBundle/Resources/public/coffee/mediatheque/mediaModalListeners.coffee
@@ -55,7 +55,9 @@
   modalId = $(event.target).parents(".mediaModalContainer").find('.fade').attr('id')

   folderName = $("#" + modalId + " .js-widget-title").text()
-
+
+  displayLoader("#" + modalId + " .modal-body-content")
+
   $.ajax
     url: $(event.target).attr('data-url')
     method: 'GET'


Array: Send out on clear

Array: Send out on clear

--- components/Array.coffee
+++ components/Array.coffee
@@ -20,6 +20,7 @@

     @inPorts.clean.on 'data', () =>
       @points = []
+      @outPorts.array.send @points

     @inPorts.points.on 'data', (point) =>
       @points.push point


updated atom config.cson

updated atom config.cson

--- config-atom/config.cson
+++ config-atom/config.cson
@@ -4,14 +4,18 @@
   editor:
     fontSize: 17
     lineHeight: 1.1
+    scrollPastEnd: true
     showIndentGuide: true
     tabType: "soft"
     zoomFontWhenCtrlScrolling: false
   "exception-reporting":
     userId: "9295d08c-0c7b-383a-085b-88929d08cf02"
   core:
+    audioBeep: false
     disabledPackages: [
+      "turbo-javascript"
       "vim-mode"
+      "polymer-atom"
     ]
     themes: [
       "seti-ui"
@@ -29,8 +33,10 @@
       beautifyEntireFileOnSave: false
   "atom-css-comb":
     readyMadeConfigs: "zen"
+  "atom-ternjs":
+    useSnippets: true
   linter:
-    errorPanelHeight: 142
+    errorPanelHeight: 25
   "linter-eslint":
     disableWhenNoEslintConfig: false
     lintHtmlFiles: true
@@ -38,7 +44,10 @@
     plugins:
       "git-diff": true
       "git-diffDecorationsZIndex": 0
+      "highlight-selected": true
       linter: true
       linterDecorationsZIndex: 0
-      "highlight-selected": true
       selection: true
+  "seti-ui":
+    compactView: true
+    font: "Default Atom Font"


Config: update config for koding.com

Config: update config for koding.com

--- config/main.prod.coffee
+++ config/main.prod.coffee
@@ -8,7 +8,7 @@
   cloudamqp           = "golden-ox.rmq.cloudamqp.com"

   publicPort          = options.publicPort     = "80"
-  hostname            = options.hostname       = "new.koding.com#{if options.publicPort is "80" then "" else ":"+publicPort}"
+  hostname            = options.hostname       = "koding.com#{if options.publicPort is "80" then "" else ":"+publicPort}"
   publicHostname      = options.publicHostname = "https://#{options.hostname}"
   region              = "aws"
   configName          = "prod"


Only running StandingOrder service 'after' callbacks for known standing orders

ie. those in byID or pristineByID

--- app/assets/javascripts/admin/standing_orders/services/standing_orders.js.coffee
+++ app/assets/javascripts/admin/standing_orders/services/standing_orders.js.coffee
@@ -13,11 +13,14 @@
         @pristineByID[standingOrder.id] = angular.copy(standingOrder)

     afterCreate: (id) ->
+      return unless @byID[id]?
       @pristineByID[id] = angular.copy(@byID[id])

     afterUpdate: (id) ->
+      return unless @byID[id]?
       @pristineByID[id] = angular.copy(@byID[id])

     afterRemoveItem: (id, deletedItemID) ->
+      return unless @pristineByID[id]?
       for item, i in @pristineByID[id].standing_line_items when item.id == deletedItemID
         @pristineByID[id].standing_line_items.splice(i, 1)


Teamwork: Added playgrounds button.

Teamwork: Added playgrounds button.

--- client/landing/app/Applications/Teamwork.kdapplication/Views/teamworkapp.coffee
+++ client/landing/app/Applications/Teamwork.kdapplication/Views/teamworkapp.coffee
@@ -6,10 +6,6 @@

     options               = @getOptions()
     instanceName          = if location.hostname is "localhost" then "teamwork-local" else "kd-prod-1"
-    additionalButton      =
-      title               : "Environments"
-      cssClass            : "clean-gray"
-      callback            : (panel, workspace) => @showEnvironmentsModal panel, workspace

     @teamwork             = new TeamworkWorkspace
       name                : options.name                or "Teamwork"
@@ -29,7 +25,14 @@
             cssClass      : "clean-gray tw-tools-button"
             callback      : => @showToolsModal @teamwork.getActivePanel(), @teamwork
           }
-          # additionalButton
+          title           : "Playgrounds"
+          itemClass       : KDButtonViewWithMenu
+          cssClass        : "clean-gray playgrounds-button"
+          menu            :
+            Facebook      :
+              callback    : (panel, workspace) =>
+                @handleEnvironmentSelection "Facebook"
+                # @showEnvironmentsModal panel, workspace
         ]
         floatingPanes     : [ "chat" , "terminal", "preview" ]
         layout            :


account: do not send pin code before password is confirmed while changing email

--- client/account/lib/views/accounteditusername.coffee
+++ client/account/lib/views/accounteditusername.coffee
@@ -205,27 +205,29 @@
           me.shareLocation = formData.shareLocation
           queue.next()
       =>
-        # secondly change user email address
-        JUser.changeEmail {email}, (err, result)=>
-          # here we are simply discarding the email is same error
-          # but do not forget to warn users about other errors
+        return queue.next() if email is @userInfo.email
+
+        options = {skipPasswordConfirmation, email}
+        @confirmCurrentPassword options, (err) =>
           if err
-            return queue.next() if err.message is "EmailIsSameError"
-            @hideSaveButtonLoader()
-            return notify err.message
-
-          options = {skipPasswordConfirmation, email}
-          @confirmCurrentPassword options, (err) =>
+            notify err
+            profileUpdated = false
+            return queue.next()
+
+          JUser.changeEmail {email}, (err, result)=>
             if err
-              notify err
-              profileUpdated = false
+              @hideSaveButtonLoader()
+              notify err.message
               return queue.next()
+
             skipPasswordConfirmation = true
-            modal = new VerifyPINModal 'Update E-Mail', (pin)->
-              remote.api.JUser.changeEmail {email, pin}, (err)->
+            modal = new VerifyPINModal 'Update E-Mail', (pin)=>
+              remote.api.JUser.changeEmail {email, pin}, (err)=>
                 if err
                   notify err.message
                   profileUpdated = false
+                else
+                  @userInfo.email = email
                 queue.next()
             modal.once 'ModalCancelled', @bound 'hideSaveButtonLoader'
       =>


admin-modal: Changed forgotten button name.

--- client/app/MainApp/sidebar/modals/adminmodal.coffee
+++ client/app/MainApp/sidebar/modals/adminmodal.coffee
@@ -214,7 +214,7 @@
                     content   : inputs.Description.getValue()
                     type      : inputs.Type.getValue()
                   , ->
-                    buttons["Broadcast"].hideLoader()
+                    buttons["Broadcast Message"].hideLoader()

               "Cancel Restart":
                 title         : "Cancel Restart"


chat: remove unused video methods

chat: remove unused video methods

--- client/ide/lib/views/chat/idechatmessagepane.coffee
+++ client/ide/lib/views/chat/idechatmessagepane.coffee
@@ -137,9 +137,6 @@
     @addSubView header

-  requestJoinVideo: -> @emit 'ChatVideoRequested'
-  requestLeaveVideo: -> @emit 'ChatVideoLeaveRequested'
-
   requestStartVideo: -> @emit 'ChatVideoStartRequested'
   requestEndVideo: -> @emit 'ChatVideoEndRequested'


app: _globals is already defined in all environments now on

--- client/app/lib/index.coffee
+++ client/app/lib/index.coffee
@@ -35,7 +35,6 @@
   if globals.config.environment in ['dev', 'sandbox']
     global._kd      = kd
     global._remote  = remote
-    global._globals = globals

   remote.once 'ready', ->
     globals.currentGroup = remote.revive globals.currentGroup


Instantly focus TextArea when edit button is clicked.

--- app/assets/javascripts/web/views/messages_view.js.coffee
+++ app/assets/javascripts/web/views/messages_view.js.coffee
@@ -11,6 +11,10 @@

   isScrolledToTop: () ->
     return (0 + @scrollOffset) >= @scrollBody().scrollTop()
+
+  didChangeCurrentMessage: ( () ->
+    @focusTextArea()
+  ).observes('controller.currentMessage')

   didResize: (textarea) -> @organizeLayers()

@@ -60,6 +64,8 @@

         return false

+    @focusTextArea()
+
     @scrollBody().bind("scroll", (event) => @didScroll(this, event))

     # setTimeout((=> $(@scrollParent).trigger("scroll")), 200)
@@ -84,6 +90,10 @@
     top = (@scrollBody()[0].scrollHeight - distance)
     @scrollBody().scrollTop(top)

+  focusTextArea: ->
+    if @state == "inDOM"
+      @textArea().focus().select()
+
   scrollBody: () -> @collection()
   collection: () -> @.$('div.messages')
   form:       () -> @.$('form.new-message')


Clean up some variable names related to touch

--- app/assets/utensils/carousel_touch/carousel_touch.coffee
+++ app/assets/utensils/carousel_touch/carousel_touch.coffee
@@ -19,13 +19,13 @@
     @initializeScroller()

   initializeScroller: ->
-    scrollOptions =
+    scroll_options =
       isPaged: true,
       defaultOrientation: utensils.TouchScroller.HORIZONTAL,
       scrollerDelegate: @createScrollDelegate(),
       disabledElements: "img",
       pagedEasingFactor: 4
-    @scroller = new utensils.TouchScroller(@el[0], @slider[0], scrollOptions)
+    @scroller = new utensils.TouchScroller(@el[0], @slider[0], scroll_options)

 # PUBLIC #

@@ -36,7 +36,7 @@
 # PROTECTED #

   createScrollDelegate: =>
-    updatePosition: ( positionX, positionY, isTouching ) =>
+    updatePosition: (position_x, position_y, is_touching) =>
       @pressed_and_didnt_move = false
     touchStart: =>
       @pause()
@@ -52,14 +52,14 @@
       @index = @scroller.getPage()
       @scrollerPageUpdated(@scroller.getPage())
       @transition()
-    closestIndexChanged: (closestIndex) =>
-      @index = closestIndex
-      @scrollerPageUpdated(closestIndex)
+    closestIndexChanged: (closest_index) =>
+      @index = closest_index
+      @scrollerPageUpdated(closest_index)

   scrollerPageUpdated: (index) ->
     # do nothing - used in infinite scroller

-  transition: =>
+  transition: ->
     super()
     @scroller.setPage(@index, false)


browserify: removed unused modules

browserify: removed unused modules

--- client/ide/lib/index.coffee
+++ client/ide/lib/index.coffee
@@ -1,5 +1,3 @@
-dateFormat = require 'dateformat'
-sinkrow = require 'sinkrow'
 ndpane = require 'ndpane'
 _ = require 'underscore'
 kd = require 'kd'
@@ -12,7 +10,6 @@
 KDSplitViewPanel = kd.SplitViewPanel
 remote = require('app/remote').getInstance()
 globals = require 'globals'
-getCollaborativeChannelPrefix = require 'app/util/getCollaborativeChannelPrefix'
 nick = require 'app/util/nick'
 showError = require 'app/util/showError'
 whoami = require 'app/util/whoami'
@@ -21,7 +18,6 @@
 FSHelper = require 'app/util/fs/fshelper'
 AppController = require 'app/appcontroller'
 CollaborationController = require './collaborationcontroller'
-IDEChatView = require './views/chat/idechatview'
 IDEContentSearch = require './views/contentsearch/idecontentsearch'
 IDEEditorPane = require './workspace/panes/ideeditorpane'
 IDEFileFinder = require './views/filefinder/idefilefinder'
@@ -32,7 +28,6 @@
 IDETerminalPane = require './workspace/panes/ideterminalpane'
 IDEView = require './views/tabview/ideview'
 IDEWorkspace = require './workspace/ideworkspace'
-RealTimeManager = require './realtimemanager'
 splashMarkups = require './util/splash-markups'
 AceApplicationTabView = require 'ace/aceapplicationtabview'
 AceFindAndReplaceView = require 'ace/acefindandreplaceview'


IDE: Quit IDE instance when ws removed.

IDE: Quit IDE instance when ws removed.

--- client/ide/lib/index.coffee
+++ client/ide/lib/index.coffee
@@ -109,7 +109,7 @@

     appManager.on 'AppIsBeingShown', (app) =>

-      return  unless app instanceof IDEAppController
+      return  unless app is this

       @setActivePaneFocus on, yes

@@ -125,16 +125,24 @@
       if app.getId() is @getId() and not @layoutManager.isSnapshotRestored()
         @layoutManager.restoreSnapshot()

-      @bindListeners()
+      @bindListeners()  unless @listenersBound

   bindListeners: ->
+
+    @listenersBound = yes

     @on 'CloseFullScreen', =>
       [ideView] = @ideViews.filter (ideView) -> ideView.isFullScreen
       ideView.emit 'CloseFullScreen'  if ideView

     @on 'SnapshotUpdated', @bound 'saveLayoutSize'
+
+    kd.singletons.notificationController.on 'WorkspaceRemoved', (data) =>
+      { machineUId, slug } = data
+
+      if @mountedMachineUId is machineUId and slug is @workspaceData.slug
+        @quit()

   prepareIDE: (withFakeViews = no) ->


--- client/ide/lib/index.coffee
+++ client/ide/lib/index.coffee
@@ -840,6 +840,10 @@
         @mountedMachine.getBaseKite().removeFromActiveSessions session

       @statusBar.showInformation()  if ideViewLength is 0
+
+      # Return if participant is leaving from collaboration session.
+      return  if @isInSession and not @amIHost and not @rtm
+
       @writeSnapshot()

     ideView.tabView.on 'PaneAdded', (pane) =>


Add undefined check to "getBaseKite()" usage

--- client/ide/lib/index.coffee
+++ client/ide/lib/index.coffee
@@ -854,7 +854,10 @@
       delete @generatedPanes[pane.view.hash]

       if session = pane.view.remote?.session
-        @mountedMachine.getBaseKite().removeFromActiveSessions session
+        # we need to check against kite existence because while a machine
+        # is getting destroyed/stopped/reinitialized we are invalidating it's
+        # kite instance to make sure every call is stopped. ~ GG
+        @mountedMachine.getBaseKite()?.removeFromActiveSessions? session

       @statusBar.showInformation()  if ideViewLength is 0


Fixed a rendering bug

Fixed a rendering bug

--- client/views/viewMap.coffee
+++ client/views/viewMap.coffee
@@ -12,9 +12,11 @@
 generateLabel = (sys)->
   sys.n+"\nMorpheus Deathbrew - Tengu"

+rsys = []
 addSys = (sys)->
   id = parseInt sys._id
   g.graph.addNode id, {label:generateLabel(sys)}
+  rsys.push sys._id

 addJump = (jump)->
   return if !_.contains(rsys, jump.s) || !_.contains(rsys, jump.t)
@@ -33,6 +35,7 @@
       g.render() if shouldRenderMap()
     removed: (sys)->
       g.graph.delNode sys._id
+      rsys = _.without rsys, sys._id
       g.render() if shouldRenderMap()
   JumpDB.find().observe
     added: (jump)->


parseInt on _id

parseInt on _id

--- client/views/viewMap.coffee
+++ client/views/viewMap.coffee
@@ -40,8 +40,9 @@
     changed: (sys)->
       updateSys sys
     removed: (sys)->
-      g.delNode sys._id, true
-      rsys = _.without rsys, sys._id
+      id = parseInt sys._id
+      g.delNode id, true
+      rsys = _.without rsys, id
       global.mapDirty = true
   JumpDB.find().observe
     added: (jump)->


Define a new property without any definition

--- lib/Table.coffee
+++ lib/Table.coffee
@@ -26,7 +26,7 @@
     Define a new property.
     ###
     property: (property, options) ->
-        @schema.properties[property] = options
+        @schema.properties[property] = options ? {}
         @indentifier property if property.identifier

     ###
@@ -221,7 +221,7 @@
         @exists records, (err, recordIds) ->
             return callback err if err
             for recordId in recordIds
-                return callback new Error "User #{recordId} already exists" if recordId?
+                return callback new Error "Record #{recordId} already exists" if recordId?
             multi = redis.multi()
             multi.incr "#{s.db}:#{s.name}_incr" for x in records
             multi.exec (err, recordIds) ->


add healthcheck on network containers. have dependent containers wait for the check to succeed

--- src/coffee/compose.coffee
+++ src/coffee/compose.coffee
@@ -2,10 +2,11 @@
 path      = require 'path'
 resolvep  = require 'resolve-path'

+composeLib = require './compose/lib.coffee'
+
 module.exports = (config) ->
   vlan = if config.vlan then " @#{config.vlan}" else  ''
   networkValue = "#{config.host_if} -i eth0 @CONTAINER_NAME@ dhclient#{vlan}"
-  networkEnv = 'eth0_pipework_cmd'

   augmentCompose: (instance, options, doc) ->
     addNetworkContainer = (serviceName, service) ->
@@ -21,6 +22,12 @@
           network_mode: 'none'
           labels: labels
           stop_signal: 'SIGKILL'
+          healthcheck:
+            test: "ifconfig eth0 | grep 'inet addr:'"
+            interval: '1s'
+            timeout: '5s'
+            retries: 60
+
         if service.container_name
           netcontainer['container_name'] = "#{service.container_name}-net"

@@ -30,6 +37,11 @@
         delete service.hostname
         delete service.net
         service.network_mode = "service:bb-net-#{serviceName}"
+
+        depends_on = composeLib.transformDependsOnToObject(service.depends_on) or {}
+        depends_on["bb-net-#{serviceName}"] = condition: 'service_healthy'
+        service.depends_on = depends_on
+
       else service.network_mode = "service:bb-net-#{service.labels['bigboat.service.name']}"

     resolvePath = (root, path) ->
@@ -95,11 +107,11 @@
         service.volumes.push '/var/run/docker.sock:/var/run/docker.sock'

     for serviceName, service of doc.services
+      migrateLinksToDependsOn serviceName, service
       addExtraLabels serviceName, service
       addNetworkContainer serviceName, service
       addVolumeMapping serviceName, service
       addDockerMapping serviceName, service
-      migrateLinksToDependsOn serviceName, service
       migrateLogging serviceName, service
       restrictCompose serviceName, service


Comments again

Comments again

--- cosmo.coffee
+++ cosmo.coffee
@@ -1,6 +1,7 @@
 window.Cosmo =
   version: '0.1.0'

+# comment
 # All apps should be an extended instance of this class
 class Cosmo.Router
   # app regions, assumes main content goes in a div#container


Only delete pdf file when options.filename is not set

--- lib/index.coffee
+++ lib/index.coffee
@@ -56,7 +56,12 @@
       filename = file.toString()
       fs.readFile filename, (err, buffer) ->
         return callback(err) if err
-        fs.unlink filename, (err) ->
+
+        # Only delete file when options.filename is not defined
+        unless options.filename
+          fs.unlink filename, (err) ->
+            callback(err, buffer)
+        else
           callback(err, buffer)

   child.stdin.write(string, 'utf8')


Add some docs.

Add some docs.

--- src/compilers/base.coffee
+++ src/compilers/base.coffee
@@ -4,9 +4,13 @@

 helpers = require '../helpers'

-# Example
-#   group [['a', 1], ['b', 2], ['a', 3], ['c', 4], ['a', 0]]
-#   -> [['a', [1, 3, 0]], ['b', [2]], ['c', [4]]]
+# Takes 2-element array.
+# Examples
+#
+#   > group [['a', 1], ['b', 2], ['a', 3], ['c', 4], ['a', 0]]
+#   [['a', [1, 3, 0]], ['b', [2]], ['c', [4]]]
+#
+# Returns new array in format [[key, values]].
 group = (items) ->
   itemsMap = {}
   for [destination, data] in items
@@ -35,6 +39,8 @@
     @timeoutId = setTimeout (=> @clear callback), @timeout

+# Queue, that would be used for tracking file writing in compilers.
+# For example, both SASS & CSS compilers use one output file: `main.css`.
 class WriteQueue extends Queue
   timeout: 200

@@ -116,6 +122,7 @@
       file.match pattern

+# Compiler that concatenates all files (e.g. main.css + helpers.css).
 class exports.ConcatenatingCompiler extends exports.Compiler
   constructor: ->
     super
@@ -134,6 +141,7 @@
     @globalWriteQueue.add [@getBuildPath(@destination), data], callback

+# Compiler that just copies all files from @sourceDirectory to build dir.
 class exports.CopyingCompiler extends exports.Compiler
   map: (file, callback) ->
     callback null, file


inline asserts

inline asserts

--- src/config/turtles.coffee
+++ src/config/turtles.coffee
@@ -74,10 +74,8 @@
     if counter >= program.length()
       program = turtles.call('reload_program', args)
       counter = 0
-    signal = program.at(counter)
-    assert signal, "No signal"
-    action = world.get('signals')[signal]
-    assert action, "No action"
+    assert signal = program.at(counter), "No signal"
+    assert action = world.get('signals')[signal], "No action"
     turtles.map_children (child) -> child.call(action['do'], action)
     world.put('program_counter', counter + 1)
   interval: 500


minor style and function changes to filteredselect

--- lib/assets/javascripts/directives/filteredselect.js.coffee
+++ lib/assets/javascripts/directives/filteredselect.js.coffee
@@ -77,6 +77,7 @@
   stylize: ->
     @search.addClass('md-input') if @element.hasClass('md-input')
     @search.css({'width': '100%','color': 'black'})
+    @element.css('position','relative').css('overflow','visible')
     searchCss = window.getComputedStyle(@search[0])
     @typeAhead.css('padding-left', parseFloat(searchCss["padding-left"]) + parseFloat(searchCss["margin-left"]) + parseFloat(searchCss["border-left-width"]) + 'px')
     @typeAhead.css('padding-top',  parseFloat(searchCss["padding-top"])  + parseFloat(searchCss["margin-top"])  + parseFloat(searchCss["border-top-width"])  + 'px')
@@ -114,12 +115,15 @@
   focusFunction: (event) =>
     @buildTemplate()
   blurFunction: (search,event) =>
-    obj={}
-    obj[@functions.viewValue] = search.val()
-    val = @filter('filter')(@functions.collection(@scope), obj)[0]
-    @updateValue @functions.modelValueFn(val)
-    search.css
-    search.val(@functions.viewValueFn(val))
+    if search.val().length < 4
+      search.val('')
+    else
+      obj={}
+      obj[@functions.viewValue] = search.val()
+      val = @filter('filter')(@functions.collection(@scope), obj)[0]
+      @updateValue @functions.modelValueFn(val)
+      search.css
+      search.val(@functions.viewValueFn(val))
   keydownFunction: (search,typeAhead,template,input) =>
     keypress = (direction) ->
       index = if direction == 'next' then 0 else template.find('a').length - 1


comment convert function

comment convert function

--- init.coffee
+++ init.coffee
@@ -25,6 +25,6 @@

 # Create all requests and upload directory
 module.exports.convert = (done = ->) ->
-    convertImage (err) ->
-        createThumb () ->
-            done()+    #convertImage (err) ->
+    createThumb () ->
+        done()


adding a separate command `linkUp` to use after `parse`. This happens afterwards and ensures that the skipLogicCriteria are linked back to their questions

--- dkobo/koboform/static/js/xlform/model_xlform.coffee
+++ dkobo/koboform/static/js/xlform/model_xlform.coffee
@@ -55,6 +55,9 @@
       @_parent = arg._parent
       delete arg._parent
     super arg
+
+  parse: ->
+  linkUp: ->

   getValue: (what)->
     if what then @get(what).getValue() else @get("value")
@@ -142,7 +145,7 @@
       # or make the code resilient to allow parse to be called
       # muiltiple times
       @rows.add surveyRows, collection: @rows, silent: true
-    @rows.invoke('parse')
+    @rows.invoke('linkUp')

   toCsvJson: ()->
     # build an object that can be easily passed to the "csv" library
@@ -345,8 +348,10 @@
     throw new Error("List not found: #{list}")  unless listToSet
     @get("type").set("list", listToSet)
   parse: ->
-    for key, val of @attributes
-      val.parse()
+    val.parse()  for key, val of @attributes
+
+  linkUp: ->
+    val.linkUp()  for key, val of @attributes

   attributesArray: ()->
     arr = ([k, v] for k, v of @attributes)
@@ -386,7 +391,6 @@
         required: true
     {}
   idAttribute: "name"
-  parse: () ->

   constructor: (@key, valOrObj={}, @parentRow)->
     if @key of XLF.RowDetailMixins
@@ -437,8 +441,9 @@
     3. (optional) The response text
     ###
     unless opts.silent
-      @parse()
-  parse: ()->
+      @linkUp()
+
+  linkUp: ()->
     survey = @get("parentRow").getSurvey()
     name = @get("name")
     if name
@@ -512,6 +517,9 @@
       ``
     catch e
       @skipLogicCollection.parseable = false
+
+  linkUp: ->
+    @skipLogicCollection.each (i)-> i.linkUp()

 @XLF.RowDetailMixins =
   relevant: SkipLogicDetailMixin


Proper visibility change handling.

Proper visibility change handling.

--- emulator/frontend/managers/execution-manager.coffee
+++ emulator/frontend/managers/execution-manager.coffee
@@ -26,8 +26,7 @@
         @setDefaults()

     initListeners: ->
-        window.addEventListener "focus", @onFocus
-        window.addEventListener "blur", @onBlur
+        document.addEventListener "visibilitychange", @onVisibilityChange

     setDefaults: ->
         logger.info "Using default execution configuration"
@@ -63,24 +62,24 @@
         @inputManager.processSources()
         @videoManager.renderFrame()
         @updateFPS()
-        cancelAnimationFrame @drawId # Cancel previous request if it wasnt performed yet
+        cancelAnimationFrame @drawId # Cancel previous request if it wasn't performed yet
         @drawId = requestAnimationFrame @draw

     draw: =>
         @videoManager.drawFrame()

     ###########################################################
-    # Focus / Blur
+    # Visibility change
     ###########################################################

-    onFocus: =>
-        logger.info "Gained focus"
-        @start() if @runningBeforeBlur
-
-    onBlur: =>
-        logger.info "Lost focus"
-        @runningBeforeBlur = @isRunning()
-        @stop()
+    onVisibilityChange: =>
+        if document.hidden
+            logger.info "Lost visibility"
+            @autoPaused = @isRunning()
+            @stop()
+        else
+            logger.info "Gained visibility"
+            @start() if @autoPaused

     ###########################################################
     # Inputs


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- source/javascripts/_cornerstone/array_extensions.js.coffee
+++ source/javascripts/_cornerstone/array_extensions.js.coffee
@@ -431,7 +431,7 @@
     result = []

     while i < end
-      result.push(@[i.mod(this.length)])
+      result.push(@[i.mod(@length)])
       i += 1

     return result


removed .only

removed .only

--- test/07-events.coffee
+++ test/07-events.coffee
@@ -6,7 +6,7 @@

 gamerCred = null

-describe.only 'Events', ->
+describe 'Events', ->

 	msgid = null


Messages#show - Show last error view if accepted message has errors

--- app/assets/javascripts/admin/views/messages/show.js.coffee
+++ app/assets/javascripts/admin/views/messages/show.js.coffee
@@ -15,13 +15,15 @@
   showInitialSubView: ->
     switch @model.get('queue_name')
       when 'accepted'
-        @$el.find('#detail-view').html JST["admin/templates/messages/_payload"](model: @model)
-        @$el.find('[data-template=payload]').addClass('active')
-        SyntaxHighlighter.highlight()
+        if @model.has_errors()
+          @$el.find('#detail-view').html JST["admin/templates/messages/_last_error"](model: @model)
+          @$el.find('[data-template=last_error]').addClass('active')
+        else
+          @$el.find('#detail-view').html JST["admin/templates/messages/_payload"](model: @model)
+          @$el.find('[data-template=payload]').addClass('active')
       when 'archived'
         @$el.find('#detail-view').html JST["admin/templates/messages/_result"](model: @model)
         @$el.find('[data-template=result]').addClass('active')
-        SyntaxHighlighter.highlight()
       when 'incoming'
         @$el.find('#detail-view').html JST["admin/templates/messages/_children"](model: @model)
         @$el.find('[data-template=children]').addClass('active')


Add auth handler to remove session data when sign out

--- app/assets/javascripts/initializers/session_restore.coffee
+++ app/assets/javascripts/initializers/session_restore.coffee
@@ -11,6 +11,10 @@
           sessionStorage.setItem('authToken', auth.get('authToken'))
           sessionStorage.setItem('authUserId', auth.get('userId'))

+        auth.addHandler 'signOutSuccess', ->
+          sessionStorage.removeItem('authToken')
+          sessionStorage.removeItem('authUserId')
+
         authToken = sessionStorage.getItem('authToken')
         authUserId = sessionStorage.getItem('authUserId')


fix wrong cursor when hovering over trace-links in spotlight-view; #295

--- app/assets/javascripts/views/spotlight_dataset_view.coffee
+++ app/assets/javascripts/views/spotlight_dataset_view.coffee
@@ -17,10 +17,10 @@
           <a href="/datasets/<%= name %>/view" title="View tracing">

-
+

-
+

@@ -54,7 +54,8 @@
     @ui.volumeTraceLink.click(@submitForm.bind(@, "volumeTracing"))

-  submitForm : (type) ->
+  submitForm : (type, event) ->

+    event.preventDefault()
     @ui.contentTypeInput.val(type)
     @ui.form.submit()


switch mathjax cdn to https

switch mathjax cdn to https

test plan:
* make sure that the advanced math editor works
when using https

fixes #CNVS-5061

Change-Id: I99e173574897498086b000b505262bb67fa2135a
Reviewed-on: https://gerrit.instructure.com/19299
Reviewed-by: Bracken Mosbacker <48b846001bca4166dc3fb7711563afc17525921e@instructure.com>
Product-Review: Bracken Mosbacker <48b846001bca4166dc3fb7711563afc17525921e@instructure.com>
Tested-by: Jenkins <d95b56ce41a2e1ac4cecdd398defd7414407cc08@instructure.com>
QA-Review: Adam Phillipps <0e18f44c1fec03ec4083422cb58ba6a09ac4fb2a@instructure.com>

--- app/coffeescripts/views/tinymce/EquationToolbarView.coffee
+++ app/coffeescripts/views/tinymce/EquationToolbarView.coffee
@@ -26,7 +26,7 @@
       )
       $('#mathjax-view .mathquill-tab-bar li:first-child').addClass('mathquill-tab-selected')

-      $.getScript("http://cdn.mathjax.org/mathjax/2.1-latest/MathJax.js?config=TeX-AMS_HTML.js", @addMathJaxEvents)
+      $.getScript("https://c328740.ssl.cf1.rackcdn.com/mathjax/2.1-latest/MathJax.js?config=TeX-AMS_HTML.js", @addMathJaxEvents)

     addMathJaxEvents: =>
       renderPreview = ->


[A/B] Temporarily force into control

[A/B] Temporarily force into control

--- src/desktop/components/split_test/middleware.coffee
+++ src/desktop/components/split_test/middleware.coffee
@@ -15,4 +15,8 @@
       test.set v
       res.locals.sd[k.toUpperCase()] = v

+  # FIXME: Remove when new A/B test launches
+  if runningTests['client_navigation_v4']
+    res.locals.sd['CLIENT_NAVIGATION_V4'] = 'control'
+
   next()


:lipstick: Use less aggressive colors in specs

--- spec/minimap-element-spec.coffee
+++ spec/minimap-element-spec.coffee
@@ -65,11 +65,11 @@
         #{stylesheet}

         atom-text-editor atom-text-editor-minimap, atom-text-editor::shadow atom-text-editor-minimap {
-          background: red;
+          background: rgba(255,0,0,0.3);
         }

         atom-text-editor atom-text-editor-minimap::shadow .minimap-visible-area, atom-text-editor::shadow atom-text-editor-minimap::shadow .minimap-visible-area {
-          background: green;
+          background: rgba(0,255,0,0.3);
         }
       """


Don't overwrite newer stances in uniqueStancesByUserId

--- angular/core/models/poll_model.coffee
+++ angular/core/models/poll_model.coffee
@@ -18,7 +18,7 @@
       @belongsTo 'author', from: 'users'
       @belongsTo 'discussion'
       @hasMany   'pollOptions'
-      @hasMany   'stances'
+      @hasMany   'stances', sortBy: 'createdAt', sortDesc: true

     group: ->
       @discussion().group() if @discussion()
@@ -38,6 +38,9 @@
     uniqueStances: (order, limit) ->
       _.slice(_.sortBy(_.values(@uniqueStancesByUserId()), order), 0, limit)

+    stanceFor: (user) ->
+      @uniqueStancesByUserId()[user.id]
+
     lastStanceByUser: (user) ->
       @uniqueStancesByUserId()[user.id]

@@ -47,11 +50,8 @@
     uniqueStancesByUserId: ->
       stancesByUserId = {}
       _.each @stances(), (stance) ->
-        stancesByUserId[stance.participantId] = stance
+        stancesByUserId[stance.participantId] = stancesByUserId[stance.participantId] or stance
       stancesByUserId
-
-    stanceFor: (user) ->
-      @uniqueStancesByUserId()[user.id]

     group: ->
       @discussion().group() if @discussion()


Deleted unused coffeescript file. All its code has now been migrated to angularJS.

--- app/assets/javascripts/modules/read_feed.js.coffee
+++ app/assets/javascripts/modules/read_feed.js.coffee
@@ -1,58 +0,0 @@
-#= require ./alert_hiding
-#= require ./shared_functions
-
-window.Feedbunch ||= {}
-
-$(document).ready ->
-
-  #-------------------------------------------------------
-  # Load read and unread feed entries when clicking on the "Show read entries" button
-  #-------------------------------------------------------
-  ###
-  $("body").on "click", "#show-read-button", ->
-    if $(this).hasClass("disabled") == false
-      Feedbunch.loading_entries this
-      # Load the entries via Ajax
-      $.get(Feedbunch.current_feed_path, {include_read: true}, insert_entries)
-        .fail (xhr, textStatus, errorThrown) ->
-          Feedbunch.entries_loaded(Feedbunch.current_feed_id)
-          if xhr.status == 404
-            Feedbunch.alertTimedShowHide $("#no-entries")
-          else
-            Feedbunch.alertTimedShowHide $("#problem-loading")
-  ###
-
-
-  ########################################################
-  # COMMON FUNCTIONS
-  ########################################################
-
-  #-------------------------------------------------------
-  # Function to insert new entries in the list
-  #-------------------------------------------------------
-  insert_entries = (entries, status, xhr) ->
-    $("#feed-entries").html entries
-    Feedbunch.entries_loaded(Feedbunch.current_feed_id)
-
-  #-------------------------------------------------------
-  # Show the feed title and link it to the feed URL
-  #-------------------------------------------------------
-  show_feed_title = (feed)->
-    feed_title = $(feed).attr "data-feed-title"
-    $("#feed-title a").text feed_title
-    $("#feed-title").removeClass "hidden"
-    feed_url = $(feed).attr "data-feed-url"
-    if feed_url? && feed_url.length > 0
-      $("#feed-title a").attr "href", feed_url
-    else
-      $("#feed-title a").removeAttr 'href'
-
-  #-------------------------------------------------------
-  # Set global variables with the currently selected feed, its folder, path and refresh path.
-  #-------------------------------------------------------
-  set_global_variables = (feed)->
-    Feedbunch.current_feed_path = $(feed).attr "data-feed-path"
-    Feedbunch.current_feed_id = $(feed).attr "data-feed-id"
-    Feedbunch.current_feed_folder_id = $(feed).attr "data-folder-id"
-    Feedbunch.current_feed_folder_id ||= "none"
-    Feedbunch.current_folder_id = $(feed).parent().closest("[data-folder-id]").attr "data-folder-id"


make tagsinput compatible with Turbolinks

--- app/cells/folio/console/tagsinput/tagsinput.coffee
+++ app/cells/folio/console/tagsinput/tagsinput.coffee
@@ -6,7 +6,7 @@
   else
     []

-$ ->
+init = ->
   $inputs = $('.folio-console-tagsinput').not('.folio-console-selectize--bound')
   return if $inputs.length is 0

@@ -36,3 +36,15 @@
               <strong>#{escape(data.input)}</strong>…
             </div>
           """
+
+dispose = ->
+  $('.folio-console-tagsinput').each ->
+    @selectize?.destroy()
+
+if Turbolinks?
+  $(document)
+    .on 'turbolinks:load', init
+    .on 'turbolinks:before-cache', dispose
+
+else
+  $ init


Adjust to better code style in test

Adjust to better code style in test

--- test/mock.test.coffee
+++ test/mock.test.coffee
@@ -10,7 +10,7 @@
       res.statusCode.should.equal 200
       json = JSON.parse res.body
       json.should.have.property('test')
-      json.test.should.equal true
+      json.test.should.be.true
       done()

 describe 'Mock file', ->
@@ -19,7 +19,7 @@
       res.statusCode.should.equal 200
       json = JSON.parse res.body
       json.should.have.property('test')
-      json.test.should.equal true
+      json.test.should.be.true
       done()

   it 'POST /test1 should serve test1_post.json', (done) ->
@@ -27,7 +27,7 @@
       res.statusCode.should.equal 200
       json = JSON.parse res.body
       json.should.have.property('post')
-      json.post.should.equal true
+      json.post.should.be.true
       done()


Add default value for referer

Add default value for referer

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -32,7 +32,7 @@
   portalProxyOptions.preserveHost = true
   portalProxyOptions.cookieRewrite = "#{accountName}.vtexlocal.com.br"

-  rewriteReferer = (referer) ->
+  rewriteReferer = (referer = '') ->
     if secureUrl
       referer = referer.replace('http:', 'https:')
     return referer.replace('vtexlocal', environment)


Use chromeAppDevPath

Use chromeAppDevPath

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -661,11 +661,11 @@
       chromeAppInline:
         vulcanizeInline(
             chromeAppDevPath + '/polymer/ext-missing.html',
-            'build/dev/uproxy/chrome/app/polymer/vulcanized-inline.html')
+            chromeAppDevPath + '/polymer/vulcanized-inline.html')
       chromeAppCsp:
         vulcanizeCsp(
             chromeAppDevPath + '/polymer/vulcanized-inline.html',
-            'build/dev/uproxy/chrome/app/polymer/vulcanized.html')
+            chromeAppDevPath + '/polymer/vulcanized.html')
       firefoxInline:
         vulcanizeInline(
             firefoxDevPath + '/data/generic_ui/polymer/root.html',


fix indent error (copy)

fix indent error (copy)

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -39,7 +39,7 @@
     clean:
       build:
         options:
-        no-write: true
+          no-write: true
         src: ['index.js*', 'lib/*']

     coffee:
@@ -99,19 +99,19 @@

   grunt.registerTask 'git:commit:release', ->
     msg = grunt.config 'release.options.commitMessage'
-  return runSimple "git commit -m '#{msg}'"
+    return runSimple "git commit -m '#{msg}'"

   grunt.registerTask 'git:isClean', ->
     res = runSilent 'git status -s'
     return unless res.output
     grunt.log.error 'Uncommitted changes'
     grunt.log.writelns res.output
-  return false
+    return false

   grunt.registerTask 'git:tag:release', ->
     tag = grunt.config 'release.options.tagName'
     msg = grunt.config 'release.options.tagMessage'
-  return runSimple "git tag  #{tag} -m '#{msg}'"
+    return runSimple "git tag  #{tag} -m '#{msg}'"

   _semverSync = 'node_modules/semver-sync/bin/semver-sync'

@@ -120,9 +120,9 @@
     return false unless res.code == 0
     if res.code == 0
       grunt.log.writeln res.output
-    return
+      return
     grunt.error res.output
-  return false
+    return false

 # release:


Changed path to 'cli-test.coffee' after migrating to 'e2e' directory. Broke out 'clean' task.

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -12,10 +12,13 @@

     gruntfile: 'Gruntfile.coffee'

-    clean: [
-      'coverage',
-      'lib/*.js'
-    ]
+    clean:
+      cover: [
+        'coverage'
+      ],
+      instrumented: [
+        'lib/*.js'
+      ]

     watch:
       options:
@@ -60,10 +63,8 @@
           reporter: 'mocha-phantom-coverage-reporter'
           require: 'coffee-script/register'
         src: [
-          # Unit Test
           'test/unit/*-test.coffee'
-          # Acceptance Test
-          'test/cli-test.coffee'
+          'test/e2e/cli-test.coffee'
         ]

     coveralls:


Disable uglify for now

Disable uglify for now

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -180,7 +180,7 @@
     "browserify:dist",
     "compileStyles",
     "copy:dist",
-    "uglify:dist",
+    # "uglify:dist",
     "cssmin:dist"
   ]


Remove unneeded stdout/stderr output forwarding

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -203,10 +203,7 @@
       spawn cmd: 'pkill', args: ['Atom'], -> callback()
     commands.push (callback) ->
       atomBinary = path.join(CONTENTS_DIR, 'MacOS', 'Atom')
-      spawn cmd: atomBinary, args: ['--test', "--resource-path=#{__dirname}"], (error, result) ->
-        process.stderr.write(result.stderr)
-        process.stdout.write(result.stdout)
-        callback(error)
+      spawn cmd: atomBinary, args: ['--test', "--resource-path=#{__dirname}"], (error) ->  callback(error)
     grunt.util.async.waterfall commands, (error) -> done(error)

   grunt.registerTask 'nof', 'Un-focus all specs', ->


Gruntfile: closure main entry point

Gruntfile: closure main entry point

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -41,7 +41,7 @@
     deps: "#{paths.js_dir}/deps.js"

     # main entry point
-    main: "#{paths.js_src}/main.js"
+    main: "#{paths.js_dir}/src/main.js"

     # output file for the compiler
     compiled: paths.minified


compress vulcanized js #224

compress vulcanized js #224

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -167,7 +167,7 @@
           flatten: true
           dest: '/'
         ,
-          src: ['app.js']
+          src: ['index.js']
           expand: true
           dest: '/'
         ,


Add tests directory to watch task

Add tests directory to watch task

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -9,7 +9,7 @@
         dest: 'chrome-app/lib/pomodoro.min.js'

     watch:
-      files: ['src/*.coffee','chrome-app/**','!chrome-app/lib/**']
+      files: ['src/*.coffee','tests/*.coffee','chrome-app/**','!chrome-app/lib/**']
       tasks: ['test','compile','launch']
       options:
         livereload:


Fixed jasmine task name.

Fixed jasmine task name.

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -83,7 +83,7 @@
             build: ['src/tmp']

         jasmine:
-            fsm:
+            build:
                 src: ['build/content-edit.js']
                 options:
                     specs: 'spec/content-edit-spec.js'


Dont destroy .git folder

Dont destroy .git folder

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -23,7 +23,7 @@
         options:
           base: 'dist/'

-    clean: ['dist/']
+    clean: ['dist/*']

     watch:
       docs:


Write Cucumber snippets in CoffeeScript. [#89369394]

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -82,6 +82,7 @@
             framework: 'cucumber'
             cucumberOpts:
               require: ['features/support/**/*', 'features/step_definitions/**/*']
+              coffee: true
             specs: [featureDir + featureFiles]
     sass:
       options:


removing unused option

removing unused option

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -86,7 +86,6 @@
         mainConfigFile: 'config/requirejs.js',
         name: 'components/almond/almond',
         out: 'dist/streetsmap.js'
-        wrap: false

       debug:
         options:


Separate out tasks because of async

Separate out tasks because of async

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -422,17 +422,17 @@
       when 'stylus'
         # Compile with or without variable injection
         if grunt.task.exists(styleVariableFile)
-          grunt.task.run('stylus:withVariables')
+          grunt.task.run [
+            'stylus:withVariables'
+            'runAutoprefixer'
+            'runCssShrink'
+          ]
         else
-          grunt.task.run('stylus:noVariables')
-
-        if grunt.task.exists('tmp/style.css')
-          grunt.task.run('autoprefixer')
-
-        # Optimize only when we're in production and if there are stylesheets
-        if NODE_ENV isnt 'dev' and
-           grunt.task.exists('public/style.css')
-          grunt.task.run('cssshrink')
+          grunt.task.run [
+            'stylus:noVariables'
+            'runAutoprefixer'
+            'runCssShrink'
+          ]

       when 'jade'
         grunt.task.run(templateTasks)
@@ -440,6 +440,15 @@
       # Compile dependencies
       when 'deps'
         runOnDeps('build')
+
+  grunt.registerTask 'runAutoprefixer', ->
+    if grunt.file.exists('tmp/style.css')
+      grunt.task.run 'autoprefixer'
+
+  # Optimize only when we're in production and if there are stylesheets
+  grunt.registerTask 'runCssShrink', ->
+    if NODE_ENV isnt 'dev' and grunt.task.exists('public/style.css')
+      grunt.task.run('cssshrink')

   # We need to manually handle components as the `cwd` path is dynamic
   # depending on the assets


added CNAME entry

added CNAME entry

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -84,7 +84,7 @@
                     dest: 'dist/'
                 },{
                     expand: true
-                    src: ['index.html']
+                    src: ['index.html', 'CNAME']
                     dest: 'dist/'
                     filter: 'isFile'
                 }]


build rules for adventure SOCKS

build rules for adventure SOCKS

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -29,6 +29,7 @@
   'simpleTurn'
   'simpleChurnChatChromeApp'
   'copyPasteChurnChatChromeApp'
+  'adventure'
 ]

 # Makes the distribution build.
@@ -109,6 +110,26 @@
   'browserify:copyPasteChurnChatFreedomModule'
   'browserify:copyPasteChurnChatChromeApp'
   'copy:libsForCopyPasteChurnChatChromeApp'
+]
+
+taskManager.add 'adventureBase', [
+  'base'
+  'browserify:adventureFreedomModule'
+]
+
+taskManager.add 'adventureChromeApp', [
+  'adventureBase'
+  'copy:libsForAdventureChromeApp'
+]
+
+taskManager.add 'adventureFirefoxApp', [
+  'adventureBase'
+  'copy:libsForAdventureFirefoxApp'
+]
+
+taskManager.add 'adventure', [
+  'adventureChromeApp'
+  'adventureFirefoxApp'
 ]

 # Create unit test code
@@ -356,6 +377,23 @@
             'uproxy-obfuscators'
           ]
           localDestPath: 'samples/copypaste-churn-chat-chromeapp/'
+
+      libsForAdventureChromeApp:
+        Rule.copyLibs
+          npmLibNames: ['freedom-for-chrome']
+          pathsFromDevBuild: ['adventure', 'churn-pipe', 'loggingprovider']
+          pathsFromThirdPartyBuild: [
+            'uproxy-obfuscators'
+          ]
+          localDestPath: 'samples/adventure-chromeapp/'
+      libsForAdventureFirefoxApp:
+        Rule.copyLibs
+          npmLibNames: ['freedom-for-firefox']
+          pathsFromDevBuild: ['adventure', 'churn-pipe', 'loggingprovider']
+          pathsFromThirdPartyBuild: [
+            'uproxy-obfuscators'
+          ]
+          localDestPath: 'samples/adventure-firefoxapp/data/'

       # Integration Tests.
       libsForIntegrationTcp:
@@ -463,6 +501,7 @@
       turnFrontendFreedomModule: Rule.browserify 'turn-frontend/freedom-module'
       simpleChurnChatFreedomModule: Rule.browserify 'samples/simple-churn-chat-chromeapp/freedom-module'
       copyPasteChurnChatFreedomModule: Rule.browserify 'samples/copypaste-churn-chat-chromeapp/freedom-module'
+      adventureFreedomModule: Rule.browserify 'adventure/freedom-module'
       # Browserify specs
       arraybuffersSpec: Rule.browserifySpec 'arraybuffers/arraybuffers'
       arraybuffersCovSpec: Rule.addCoverageToBrowserify(Rule.browserifySpec 'arraybuffers/arraybuffers')


Added livereload to grunt watch

Added livereload to grunt watch

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -104,6 +104,8 @@
           "assets/src/js/templates.js": ["assets/coffee/apps/**/*.html"]

     watch:
+      options:
+         livereload: true
       coffee:
         files: 'assets/coffee/**/*.coffee'
         tasks: ["clean", "jst", "coffee", "concat"]


chore: remove unused tasks for building adapters

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -16,24 +16,14 @@
   # Project configuration.
   grunt.initConfig
     pkgFile: 'package.json'
-
+
     files:
       server: ['lib/**/*.js']
       client: ['static/testacular.src.js']
-      jasmine: ['adapter/jasmine.src.js']
-      mocha: ['adapter/mocha.src.js']
-      ngScenario: ['adapter/angular-scenario.src.js']
-      require: ['adapter/require.src.js']
-      qunit: ['adapter/qunit.src.js']
       grunt: ['grunt.js', 'tasks/**/*.js']

     build:
       client: '<%= files.client %>'
-      jasmine: '<%= files.jasmine %>'
-      mocha: '<%= files.mocha %>'
-      ngScenario: '<%= files.ngScenario %>'
-      require: '<%= files.require %>'
-      qunit: '<%= files.qunit %>'

     test:
       unit: 'simplemocha:unit'
@@ -72,27 +62,7 @@
         files:
           src: '<%= files.client %>'
         options: JSHINT_BROWSER
-      jasmine:
-        files:
-          src: '<%= files.jasmine %>'
-        options: JSHINT_BROWSER
-      mocha:
-        files:
-          src: '<%= files.mocha %>'
-        options: JSHINT_BROWSER
-      qunit:
-        files:
-          src: '<%= files.qunit %>'
-        options: JSHINT_BROWSER
-      ngScenario:
-        files:
-          src: '<%= files.ngScenario %>'
-        options: JSHINT_BROWSER
-      require:
-        files:
-          src: '<%= files.require %>'
-        options: JSHINT_BROWSER
-
+
       options:
         quotmark: 'single'
         camelcase: true


Shifted around the binding of anchors to actions so that we can bind anchors in popups

--- app/assets/javascripts/init.js.coffee
+++ app/assets/javascripts/init.js.coffee
@@ -126,6 +126,10 @@
     return
   return

+connectAnchors = (parentElement) ->
+  $(parentElement).find('a.songAnchor').click songAnchorClicked
+  $(parentElement).find('a.leaderAnchor').click leaderAnchorClicked
+
 handleAjaxBusy = (xhr) ->
   if $(xhr.target).is("form")
     #form is being submitted make things look pretty in the mean time
@@ -226,10 +230,9 @@
       marginTop: '7px'
     }, 'fast', 'linear'
     return
-  $('a.songAnchor').click songAnchorClicked
-  $('a.leaderAnchor').click leaderAnchorClicked
   $('td[contenteditable=true]').on('focus', ceBeforeUpdate).on 'blur', ceDoUpdate
   $('td[contenteditable=true]').on 'paste', cePaste
+  connectAnchors document
   $("<div>").addClass("ajaxbusy").css("display", "none").appendTo "body"
   return


Update App.scenario_url() to reflect new ETE URLs

--- app/assets/javascripts/lib/app.coffee
+++ app/assets/javascripts/lib/app.coffee
@@ -113,7 +113,7 @@

   # Used on the console for debugging
   scenario_url: =>
-    "#{globals.api_url}/data/#{@scenario.api_session_id()}"
+    "#{globals.api_url}/inspect/#{@scenario.api_session_id()}"

   # Prepares the Merit Order abd FCE checkboxes
   setup_checkboxes: =>


Rename PodsFetcher => PodsLoader.

Rename PodsFetcher => PodsLoader.

--- app/assets/javascripts/pods.js.coffee
+++ app/assets/javascripts/pods.js.coffee
@@ -9,7 +9,7 @@
     $('.progress-container').hide().html($('.progress-tpl').html()).slideDown(1000)
   finish: ->
     $('.progress').slideUp(1000)
-class PodsFetcher
+class PodsLoader
   delegate: null
   requests: []
   cancel: ->
@@ -40,11 +40,11 @@
 class @PodsController
   constructor: ->
     @progressBar = new PodsProgressBar()
-    @fetcher = new PodsFetcher()
-    @fetcher.delegate = @
+    @loader = new PodsLoader()
+    @loader.delegate = @
   pods: []
   loadPods: ->
-    @fetcher.loadPods()
+    @loader.loadPods()
     @progressBar.start()
   didLoad: (chunk_id, pods) ->
     @progressBar.update(chunk_id)


fix export to pdf syntax style issue.

fix export to pdf syntax style issue.

--- lib/style.coffee
+++ lib/style.coffee
@@ -41,7 +41,7 @@
           markdownPreviewRules.push(rule.cssText)

   return markdownPreviewRules
-          .concat(getTextEditorStyles())
+          .concat(if atom.config.get('markdown-preview-enhanced.useGitHubSyntaxTheme') then [] else getTextEditorStyles())
           .join('\n')
           .replace(/atom-text-editor/g, 'pre.editor-colors')
           .replace(/:host/g, '.host') # Remove shadow-dom :host selector causing problem on FF


:lipstick: Use a oneliner in getCells

:lipstick: Use a oneliner in getCells

--- lib/table.coffee
+++ lib/table.coffee
@@ -149,8 +149,6 @@
   #     ######  ######## ######## ########  ######

   getCells: ->
-    cells = []
-    @rows.forEach (row) -> cells = cells.concat(row.getCells())
-    cells
+    @rows.reduce ((cells, row) -> cells.concat row.getCells()), []

   getCellsCount: -> @getCells().length


Added method for extending component load paths

--- lib/NoFlo.coffee
+++ lib/NoFlo.coffee
@@ -123,3 +123,9 @@
 exports.Component = component.Component
 exports.Port = port.Port
 exports.graph = graph
+
+# Method for extending include paths for
+# NoFlo components
+exports.addComponentIncludePaths = (paths) ->
+  for path in paths
+    require.paths.unshift path


Refresh filter counters in Kanban after user assignment/unassigment

--- app/coffee/modules/kanban/main.coffee
+++ app/coffee/modules/kanban/main.coffee
@@ -241,9 +241,10 @@
             usModel.assigned_to = userid
         @kanbanUserstoriesService.replaceModel(usModel)

-        promise = @repo.save(usModel)
-        promise.then null, ->
-            console.log "FAIL" # TODO
+        @repo.save(usModel).then =>
+            @.generateFilters()
+            if @.isFilterDataTypeSelected('assigned_users') || @.isFilterDataTypeSelected('role')
+                @.filtersReloadContent()

     onAssignedUsersDeleted: (ctx, userid, usModel) ->
         assignedUsersIds = _.clone(usModel.assigned_users, false)
@@ -259,9 +260,10 @@

         @kanbanUserstoriesService.replaceModel(usModel)

-        promise = @repo.save(usModel)
-        promise.then null, ->
-            console.log "FAIL" # TODO
+        @repo.save(usModel).then =>
+            @.generateFilters()
+            if @.isFilterDataTypeSelected('assigned_users') || @.isFilterDataTypeSelected('role')
+                @.filtersReloadContent()

     refreshTagsColors: ->
         return @rs.projects.tagsColors(@scope.projectId).then (tags_colors) =>


New test

New test

--- test/specs/run.coffee
+++ test/specs/run.coffee
@@ -46,10 +46,12 @@
       package_file = JSON.parse FS.readFileSync "#{@temp_dir}/package.json"
       readme_file = FS.readFileSync "#{@temp_dir}/README.md"
       tag_check_result = Exec 'git tag -l 1.2.4'
+      tag_message_result = Exec 'git --no-pager log -1 --decorate=short --format="%B" 1.2.4'

       assert.equal package_file.version, '1.2.4'
       assert.equal readme_file.toString(), 'TEST FILE\n=========\n\n1.2.4'
       assert.equal tag_check_result.toString(), '1.2.4\n'
+      assert.equal tag_message_result.toString(), 'Release 1.2.4\n\n'
       assert FS.existsSync "#{@temp_dir}/pre_command"
       assert FS.existsSync "#{@temp_dir}/post_command"
       assert FS.existsSync "#{@temp_dir}/post_complete"


Refactor Invitation AJAX Request

Refactor Invitation AJAX Request

- Add reusable callback functions

--- apps/tools/components/send_invitation/index.coffee
+++ apps/tools/components/send_invitation/index.coffee
@@ -8,7 +8,35 @@
   $submit = $el.find '.js-submit'
   $errors = $el.find '.js-errors'

-  submissionTimeout = null;
+  submissionTimeout = null
+  label = $submit.text()
+
+  onSuccess = () ->
+    $form.trigger 'reset'
+
+    $submit
+      .prop 'disabled', false
+      .text 'Sent!'
+
+    submissionTimeout = setTimeout (-> $submit.text label), 2500
+
+    track.submit 'Invitation sent from user'
+
+  onFailure = (message) ->
+    $errors
+      .show()
+      .html message
+
+    $submit
+      .prop 'disabled', false
+      .text 'Error'
+
+    submissionTimeout = setTimeout ->
+      $submit.text label
+      $errors.empty()
+    , 5000
+
+    track.error 'Invitation not sent, try again.'

   $form.on 'submit', (e) ->
     e.preventDefault()
@@ -16,8 +44,6 @@
     submissionTimeout && clearTimeout(submissionTimeout);

     serializer = new Serializer $form
-
-    label = $submit.text()

     $submit
       .prop 'disabled', true
@@ -28,49 +54,10 @@
       type: 'POST'
       data: serializer.data()

-    .then ->
-      $form.trigger 'reset'
-
-      $submit
-        .prop 'disabled', false
-        .text 'Sent!'
-
-      submissionTimeout = setTimeout (-> $submit.text label), 2500
-
-      track.submit 'Invitation sent from user'
+    .then onSuccess

     .catch ({ responseJSON: { message, description }}) ->
-      $errors
-        .show()
-        .html """
-          #{message}

-          #{description}
-        """
-
-      $submit
-        .prop 'disabled', false
-        .text 'Error'
-
-      submissionTimeout = setTimeout ->
-        $submit.text label
-        $errors.empty()
-      , 5000
-
-      track.error 'Invitation not sent, try again.'
+      onFailure("#{message}
#{description}")

     .catch ->
-      $errors
-        .show()
-        .html """
-          Something went wrong, please contact info@are.na if the problem persists.
-        """
-
-      $submit
-        .prop 'disabled', false
-        .text label
-
-      submissionTimeout = setTimeout ->
-        $errors.empty()
-      , 15000
-
-      track.error 'Invitation not sent: server error. Try again.'
+      onFailure("Something went wrong, please contact info@are.na if the problem persists.")


Fixed - tab switches to main view automatically when opening any new window plugin

--- views/single-tabarea.cjsx
+++ views/single-tabarea.cjsx
@@ -154,8 +154,8 @@
         {
           counter = 1
           plugins.map (plugin, index) =>
-            if plugin.handleClick
-              <MenuItem key={2 + index} eventKey={0} onSelect={plugin.handleClick}>
+            if plugin.handleClick?
+              <MenuItem key={2 + index} eventKey={@state.key} onSelect={plugin.handleClick}>
                 {plugin.displayName}
               </MenuItem>
             else
@@ -180,7 +180,7 @@
         {
           counter = 1
           plugins.map (plugin, index) =>
-            if !plugin.handleClick
+            if !plugin.handleClick?
               key = (counter += 1)
               <div id={plugin.name} className="poi-app-tabpane #{if @state.key == key then 'show' else 'hidden'}">
                 <PluginWrap plugin={plugin} selectedKey={@state.key} index={key} />


inject cordova file transfer

inject cordova file transfer

--- www/js/model.coffee
+++ www/js/model.coffee
@@ -13,9 +13,9 @@
 	ret.pathname = lpath.join ret.pathname, url
 	if model.transport() == 'io' then "/#{url}" else lurl.format ret

-angular.module('starter.model', ['ionic', 'PageableAR', 'util.file'])
-
-	.factory 'resource',  ($rootScope, pageableAR, $http, $log, fileService) ->
+angular.module('starter.model', ['ionic', 'PageableAR', 'util.file', 'ngCordova.plugins.fileTransfer'])
+
+	.factory 'resource',  ($rootScope, pageableAR, $http, $log, fileService, $cordovaFileTransfer) ->

 		pageableAR.setTransport(pageableAR.Model.iosync)

@@ -295,11 +295,11 @@
 					file = new Attachment _.pick(@, 'type', 'to', 'body', 'local')
 					if file.local instanceof MediaFile
 						opts =
-							fileName: file.name
-							mimeType: 'audio/wav'
+							fileName: file.local.name
+							mimeType: file.local.type
 							params: _.pick file, 'to', 'type', 'body'
 							headers: $http.defaults.headers.common
-						$cordovaFileTransfer.upload file.$urlRoot(), file.url, opts
+						$cordovaFileTransfer.upload file.$urlRoot(), file.local.localURL, opts
 					else
 						file.$save()


update $urlRoot for rest or io api

update $urlRoot for rest or io api

--- www/js/model.coffee
+++ www/js/model.coffee
@@ -24,7 +24,7 @@
 resource = ($rootScope, pageableAR, Upload) ->

 	class RosterItem extends pageableAR.Model
-		$urlRoot: "#{env.server.app.url}/api/roster"
+		$urlRoot: "/api/roster"

 		$parse: (data, opts) ->
 			ret = super(data, opts)
@@ -44,7 +44,7 @@
 	class Roster extends pageableAR.PageableCollection
 		_instance = null

-		$urlRoot: "#{env.server.app.url}/api/roster"
+		$urlRoot: "/api/roster"

 		model: RosterItem

@@ -65,7 +65,7 @@

 		_me = null

-		$urlRoot: "#{env.server.app.url}/api/user"
+		$urlRoot: "/api/user"

 		@me: ->
 			_me ?= new User id: 'me'
@@ -111,7 +111,7 @@
 	class Users extends pageableAR.PageableCollection
 		_instance = null

-		$urlRoot: "#{env.server.app.url}/api/user"
+		$urlRoot: "/api/user"

 		model: User

@@ -129,7 +129,7 @@
 				visitors:	'Visitors'
 			values: ['Members-Only', 'Unmoderated', 'Moderated']

-		$urlRoot: "#{env.server.app.url}/api/group"
+		$urlRoot: "/api/group"

 		$defaults:
 			type:		'Members-Only'
@@ -154,7 +154,7 @@
 	class Groups extends pageableAR.PageableCollection
 		_instance = null

-		$urlRoot: "#{env.server.app.url}/api/group"
+		$urlRoot: "/api/group"

 		model: Group

@@ -165,7 +165,7 @@
 	class GroupsPrivate extends pageableAR.PageableCollection
 		_instance = null

-		$urlRoot: "#{env.server.app.url}/api/group/membersOnly"
+		$urlRoot: "/api/group/membersOnly"

 		model: Group

@@ -173,7 +173,7 @@
 			_instance ?= new GroupsPrivate()

 	class Msg extends pageableAR.Model
-		$urlRoot: "#{env.server.app.url}/api/msg"
+		$urlRoot: "/api/msg"

 		$parse: (data, opts) ->
 			ret = super(data, opts)
@@ -187,7 +187,7 @@
 			return ret

 	class Attachment extends pageableAR.Model
-		$urlRoot: "#{env.server.app.url}/api/msg/file"
+		$urlRoot: "api/msg/file"

 		$save: (values = {}, opts = {}) ->
 			_.extend @, values
@@ -216,7 +216,7 @@
 			@restsync(op, model, opts)

 	class Msgs extends pageableAR.PageableCollection
-		$urlRoot: "#{env.server.app.url}/api/msg"
+		$urlRoot: "/api/msg"

 		model: Msg


Make the function public accessible

Make the function public accessible

--- lib/utils.coffee
+++ lib/utils.coffee
@@ -110,12 +110,12 @@
       });
     status

-  getHomePath: ->
+  @getHomePath: ->
     os.homedir() ? "/"

   @isTokamakProject: ->
     dir = _.find(atom.project.getPaths(), (x) -> x?)
-    proj_path = if dir? then dir.toString() else getHomePath()
+    proj_path = if dir? then dir.toString() else @getHomePath()
     config_file = path.join(proj_path, 'tokamak.toml')
     console.log(config_file)
     fs.existsSync(config_file)


Search completion; better SimpleCache.

Search completion; better SimpleCache.

SimpleCache should reset the timer very time it's rotated (including
when the allowed number of entries is exceeded.

--- lib/utils.coffee
+++ lib/utils.coffee
@@ -211,16 +211,18 @@
 # they are discarded.
 class SimpleCache
   # expiry: expiry time in milliseconds (default, one hour)
-  # entries: maximum number of entries
+  # entries: maximum number of entries in @cache (there may be this many entries in @previous, too)
   constructor: (@expiry = 60 * 60 * 1000, @entries = 1000) ->
     @cache = {}
-    @previous = {}
-    rotate = => @rotate()
-    setInterval rotate, @expiry
+    @rotate() # Force starts the rotation timer.

   rotate: ->
     @previous = @cache
     @cache = {}
+    # We reset the timer every time the cache is rotated (which could be because a previous timer expired, or
+    # because the number of @entries was exceeded.
+    clearTimeout @timer if @timer?
+    @timer = Utils.setTimeout @expiry, => @rotate()

   has: (key) ->
     (key of @cache) or key of @previous


cleanup

cleanup

--- lib/utils.coffee
+++ lib/utils.coffee
@@ -47,16 +47,17 @@
   atom.views.getView(model)

 # Return function to restore editor's scrollTop and fold state.
+
+getAllFoldMarkers = (editor) ->
+  # [TODO] REMOVE-on=displayLayer-is-out
+  finder = editor.displayLayer ? editor.displayBuffer
+  finder.findFoldMarkers({})
+
 saveEditorState = (editor) ->
   editorElement = getView(editor)
   scrollTop = editorElement.getScrollTop()

-  if editor.displayLayer?
-    foldMarkers = editor.displayLayer.findFoldMarkers({})
-  else
-    foldMarkers = editor.displayBuffer.findFoldMarkers({})
-
-  foldStartRows = foldMarkers.map (m) -> m.getStartPosition().row
+  foldStartRows = getAllFoldMarkers(editor).map (m) -> m.getStartPosition().row
   ->
     for row in foldStartRows.reverse() when not editor.isFoldedAtBufferRow(row)
       editor.foldBufferRow(row)
@@ -492,11 +493,9 @@
   rangeStart.union(rangeEnd)

 getTokenizedLineForRow = (editor, row) ->
-  if editor.tokenizedBuffer?
-    editor.tokenizedBuffer.tokenizedLineForRow(row)
-  else
-    # [TODO] Remove this when min engine update to 1.9.0
-    editor.displayBuffer.tokenizedBuffer.tokenizedLineForRow(row)
+  # [TODO] REMOVE-on=displayLayer-is-out
+  tokenizedBuffer = editor.tokenizedBuffer ? editor.displayBuffer.tokenizedBuffer
+  tokenizedBuffer.tokenizedLineForRow(row)

 getScopesForTokenizedLine = (line) ->
   for tag in line.tags when tag < 0 and (tag % 2 is -1)
@@ -531,7 +530,7 @@
           position = new Point(row, column)
           results.push {scope, position, stop}
       else
-        # [TODO] Remove this when engine updated to >=1.9
+        # [TODO] REMOVE-on=displayLayer-is-out
         if tokenIterator.isHardTab?
           column += switch
             when tokenIterator.isHardTab() then 1


Fix reply/cancel toggle when submitting post

--- assets/javascripts/views/reply_post_form.js.coffee
+++ assets/javascripts/views/reply_post_form.js.coffee
@@ -44,6 +44,7 @@
   show: =>
     @is_hidden = false
     @$container.removeClass('hide')
+    @once 'ready', @hide
     @focusAfterText()
     if $button = @getReplyButton()
       @show_text ?= $button.text()


Update sumatra.coffee

Update sumatra.coffee

Add annotated source documentation

TODO: Merge into lib/

--- pkg/sumatra.coffee
+++ pkg/sumatra.coffee
@@ -26,6 +26,9 @@
   # Bind the `perform()` method to the `action` as set in the definition
   # of this plugin. Overriding this method removes the guarantee that
   # perform() will be called at all...
+  #
+  # If `action:` is set to `null`, this method will not bind `perform()` to
+  # anything.
   bindEvents: ->
     if @action?
       @element.on @action, @perform
@@ -35,7 +38,13 @@
   # The event binding that handles `action`. Override this with your own
   # method. You must override this method or the `bindEvents` method to
   # get this plugin to do anything.
+
 # Define a Sumatra plugin as a jQuery plugin.
+#
+# Arguments:
+# - **plugin_name:** The name of the plugin as called from jQuery.
+# - **plugin_code:** A function that returns a single object, which responds
+#                    to a constructor of 3 arguments at least.
 #
 # Example:
 #     sumatra 'myPlugin', ->
@@ -44,8 +53,13 @@
 #         initialize:
 #           alert 'loaded'
 @sumatra = (plugin_name, plugin_code) ->
+  # Instantiate a PluginHelper and apply the current scope.
   PluginHelper = plugin_code.apply this

+  # Define a jQuery plugin named `plugin_name`.
   jQuery.fn[plugin_name] = (options={}) ->
     @each (index, element) ->
+      # For each element, create a `PluginHelper` instance
+      # of the passed-in `plugin_code` and apply the jQuery
+      # plugin parameters to the constructor.
       new PluginHelper(element, index, options)


Fix the cache for the last time

Fix the cache for the last time

--- lib/cache.coffee
+++ lib/cache.coffee
@@ -97,13 +97,13 @@
     @next.prev = this
     item.next = this

-  get: ->
-    if _.isArray(@value) && _.isObject(@value[0])
-      @sub item for item in @value
-    else if _.isObject(@value)
-      @sub @value
+  get: (value = @value) ->
+    if _.isArray(value)
+      @get(item) for item in value
+    else if _.isObject(value)
+      @sub value
     else
-      @value
+      value

   sub: (parent) ->
     child = {}


clean console.log

clean console.log

--- views/akashic-resource-chart.cjsx
+++ views/akashic-resource-chart.cjsx
@@ -140,7 +140,6 @@
       @resourceChart.options.animation = true
       console.log "map create"
   shouldComponentUpdate: (nextProps, nextState)->
-    console.log "in shouldComponentUpdate"
     if @resourceChart is null
       true
     else if nextState.showRange isnt @state.showRange or nextState.showScale isnt @state.showScale


🐛 Code Bank `game.` wrongfully removed (#205)

--- ozaria/site/views/play/level/tome/SpellPaletteView.coffee
+++ ozaria/site/views/play/level/tome/SpellPaletteView.coffee
@@ -116,7 +116,7 @@
         console.log 'could not find doc for', propName, 'from', allDocs['__' + propName]
         doc = propName
       if doc
-        @entries.push @addEntry(doc, section, subSection)
+        @entries.push @addEntry(doc, section, subSection, false)
     @entryGroups = _.groupBy @entries, (entry) -> entry.doc.section


[DOC] Add documentation for src/frontend/stats.coffee.

--- src/frontend/stats.coffee
+++ src/frontend/stats.coffee
@@ -21,6 +21,7 @@
         @_jqChart = PrivateValue.GetOnly ($ '#' + @name)
         (do @_jqChart.get).bind "plothover", @displayTickData

+    # Checks for new data and displays it after.
     displayTickData: (event, pos, item) =>
         if item?
             if @prevPoint isnt item.dataIndex
@@ -35,6 +36,7 @@
             do $("#tooltip").remove
             @prevPoint = null

+    # Displays an updated tooltip with its new position.
     showTooltip: (x, y, contents) =>
         $('
' + contents + '
').css({
               position: 'absolute',


Fix windows assets bug.

Fix windows assets bug.

--- src/fs_utils/asset.coffee
+++ src/fs_utils/asset.coffee
@@ -12,7 +12,7 @@
 #
 # Returns String.
 getAssetDirectory = (path, convention) ->
-  split = path.split('/')
+  split = path.split(common.sep)
   # Creates thing like this
   # 'app/', 'app/assets/', 'app/assets/thing/', 'app/assets/thing/thing2.html'
   split


fix: get the projects

fix: get the projects

--- app/routes/authenticated/index.coffee
+++ app/routes/authenticated/index.coffee
@@ -3,6 +3,6 @@
 IndexRoute = Ember.Route.extend

   model: ->
-    @modelFor("authenticated")
+    @modelFor("authenticated").get('projects')

 `export default IndexRoute`


limit response to 600 characters

limit response to 600 characters

--- src/plugins/kamaln7/urbandictionary/urbandictionary.coffee
+++ src/plugins/kamaln7/urbandictionary/urbandictionary.coffee
@@ -51,11 +51,11 @@

             response =
               pages: data.list.length
-              result: data.list[page]
+              result: data.list[page].substring 0, 600 # limit response to 600 characters
       catch error
         err = 'An error occurred.'
       finally
         cb(err, response)

   module.exports =
-    Plugin: Plugin+    Plugin: Plugin