Fix spelling in a comment.

Fix spelling in a comment.

error: pathspec 'test/lib/dom.coffee' did not match any file(s) known to git

--- test/lib/dom.coffee
+++ test/lib/dom.coffee
@@ -0,0 +1,1245 @@
+
+casper.test.begin "DOM Testing", 53, (test) ->
+
+
+  casper.start()
+
+    # ADD ---------------------------------------------------------------------
+
+    # The ADD function adds the item to the current set of items that can have
+    # other actions taken on them. For example, after performing an ADD you
+    # may want to add a css class to all the items in the set.
+
+    .then ->
+
+      originalCount = 0
+      testCount = 0
+      combinedThingCount = 0
+
+      @.evaluate ->
+
+        originalCount = junction("body").length
+        testCount = junction("#test").length
+        combinedThing = junction("body").add("#test")
+        combinedThingCount = thing.length
+
+      test.assertEquals originalCount + testCount,
+                        combinedThingCount,
+                        ["ADD is successful"]
+
+      return
+
+
+    # ADD-CLASS ---------------------------------------------------------------
+
+    # The ADD-CLASS function adds a css class to the item selected.
+
+    .then ->
+
+      @.evaluate ->
+
+        junction("#test").addClass("testing")
+
+      test.assertExists ".testing", ["ADDCLASS is successful"]
+
+      return
+
+
+    # AFTER -------------------------------------------------------------------
+
+    # The AFTER function adds the designated markup AFTER the selected item.
+
+    .then ->
+
+      @.evaluate ->
+
+        junction("#test").append("

")
+        junction("#foo-before").after("

")
+
+      testElement = @.evaluate ->
+        te = document.getElementById("foo-before")
+        temp = te.nextSibling
+        return temp
+
+      test.assertEquals testElement.attributes[0].textContent,
+                        "foo-after",
+                        ["AFTER is successful"]
+
+      return
+
+
+    # APPEND ------------------------------------------------------------------
+
+    # The APPEND function adds the element as the last child of the selected item
+
+    .then ->
+
+      # resultWrapper = @evaluate(->
+      #   wrapper = {}
+      #   try
+      #     junction("

").appendTo("#test")
+      #
+      #     # store your return values in the wrapper
+      #   catch error
+      #     wrapper.error = error
+      #   wrapper
+      # )
+      #
+      # # Handle the result and possible errors:
+      # if resultWrapper.error
+      #   error = resultWrapper.error
+      #   @echo "An error occurred: " + JSON.stringify(error.message)
+
+      # else
+      #   result = JSON.stringify(resultWrapper.result)
+      #   @echo result
+
+      @.evaluate ->
+
+        junction("body").append "

"
+
+      test.assertExists "#second", ["APPEND is successful"]
+
+      return
+
+
+    # APPENDTO ----------------------------------------------------------------
+
+    # The APPENDTO function works the same as the APPEND function...just
+    # is written backwards.
+
+    .then ->
+
+      @.evaluate ->
+
+        junction("

").appendTo("body")
+
+      test.assertExists "#appendTo", ["APPENDTO is successful"]
+
+      return
+
+
+    # ATTR --------------------------------------------------------------------
+
+    # The ATTR function gets the value of the first element of the set or
+    # sets the value of all the elements in the set.
+
+    .then ->
+
+      # should return null if the item doesn't exist
+      theThing = @.evaluate ->
+
+        junction("#this_does_not_exist").attr("class")
+
+      test.assertEquals theThing, null, ["ATTR returns null if the item doesn't exist"]
+
+      # should get the attribute
+      theThing = @.evaluate ->
+
+        junction("#test").attr("class")
+
+      test.assertEquals theThing, "testing", ["ATTR successfully get the attribute"]
+
+      # should set the attribute
+      theThing = @.evaluate ->
+
+        junction("#test").attr("class", "foo").attr("class")
+
+      test.assertEquals theThing, "foo", ["ATTR successfully sets an attribute"]
+
+      return
+
+
+    # BEFORE ------------------------------------------------------------------
+
+    # The BEFORE function adds the designated markup BEFORE the selected item.
+
+    .then ->
+
+      @.evaluate ->
+
+        junction("body").append("

")
+        junction("#before").append("

")
+        junction("#foo-after2").before("

")
+
+      testElement = @.evaluate ->
+        te = document.getElementById("foo-after2")
+        temp = te.previousSibling
+        return temp
+
+      test.assertEquals testElement.attributes[0].textContent,
+                        "foo-before2",
+                        ["BEFORE is successful"]
+
+      return
+
+
+    # CHILDREN ----------------------------------------------------------------
+
+    # The CHILDREN function gets the children of the current element
+
+    .then ->
+
+      numOfChildren = @.evaluate ->
+
+        test = junction("#before")
+        test.html("

")
+        element = junction("#el")
+        return test.children().length
+
+      test.assertEquals numOfChildren, 1, ["CHILDREN is successful"]
+
+      return
+
+
+    # CLONE -------------------------------------------------------------------
+
+    # The CLONE function creates a new junction object containing the currently
+    # selected elements
+
+    .then ->
+
+      @.evaluate ->
+
+        junction("body").append("

")
+        junction("#clone").addClass("clone")
+
+      clonedClass = @.evaluate ->
+
+        element = junction("#clone").clone()
+        element.attr("class", "foo").attr("class")
+        return element.attr("class")
+
+      originalClass = @.evaluate ->
+
+        element = junction("#clone")
+        return element.attr("class")
+
+      test.assertEquals clonedClass, "foo", ["CLONE is successful"]
+      test.assertEquals originalClass, "clone", ["CLONE doesn't modify original set"]
+
+      return
+
+
+    # CLOSEST -----------------------------------------------------------------
+
+    # The CLOSEST function looks in the current set of elements and it's
+    # parents for the first element that matches.
+
+    .then ->
+
+      @.evaluate ->
+
+        junction("body").append("

")
+        junction("#closest").append("

")
+        junction("#closest").append("

")
+
+      closestDiv = @.evaluate ->
+
+        return junction("#closestChildOne").closest("#closest")
+
+      test.assertEquals closestDiv[0].id, "closest", ["CLOSEST is successful"]
+
+      return
+
+
+    # CSS ---------------------------------------------------------------------
+
+    # The CSS function gets and/or sets the style from the selected element
+
+    .then ->
+
+      @.evaluate ->
+
+        junction("body").append("

")
+        junction("#css").css("margin-top", "2px")
+
+      testThing = @.evaluate ->
+
+        test = junction("#css")
+        return junction._getStyle(test[0], "margin-top")
+
+      test.assertEquals testThing, "2px", ["CSS is successful"]
+
+      return
+
+
+    # EQ ----------------------------------------------------------------------
+
+    # The EQ function returns the item at the specified index in a junction object
+
+    .then ->
+
+      @.evaluate ->
+
+        junction("body").append("

")
+
+      testThing = @.evaluate ->
+
+        return junction("#eq")
+
+      testThing2 = @.evaluate ->
+
+        return junction("#eq").eq(0)
+
+      testThing3 = @.evaluate ->
+
+        return junction("#eq").eq(100000)
+
+      test.assertEquals testThing2[0], testThing[0], ["EQ is successful"]
+
+      test.assertEquals testThing3[0], undefined, ["EQ out of range is undefined"]
+
+      return
+
+
+    # FILTER ------------------------------------------------------------------
+
+    # The FILTER function filters out the selected set if it does NOT match
+    # the specified element.
+
+    .then ->
+
+      @.evaluate ->
+
+        junction("body").append("

")
+        junction("#filter").append("

")
+
+      numberOfDivs = @.evaluate ->
+
+        test = junction("div")
+        return test.filter("#filterChild").length
+
+      test.assertEquals numberOfDivs, 1, ["FILTER is successful"]
+
+      return
+
+
+    # FIND --------------------------------------------------------------------
+
+    # The FIND function finds the selected item.
+
+    .then ->
+
+      testThing = @.evaluate ->
+
+        return junction("body").find("#test").attr("class")
+
+      test.assertEquals testThing, "foo", ["FIND is successful"]
+
+      return
+
+
+    # FIRST -------------------------------------------------------------------
+
+    # The FIRST function returns the first element of the set.
+
+    .then ->
+
+      @.evaluate ->
+
+        junction("body").append("

")
+        junction("body").append("

")
+
+      testThing = @.evaluate ->
+
+        return junction(".first").first()[0]
+
+      test.assertEquals testThing.id, "firstOne", ["FIRST is successful"]
+
+      return
+
+
+    # GET ---------------------------------------------------------------------
+
+    # The GET function returns the DOM node at the passed index.
+
+    .then ->
+
+      testThing = @.evaluate ->
+
+        return junction("#test")
+
+      getThing = @.evaluate ->
+
+        return junction("#test").get(0)
+
+      test.assertEquals getThing.id, testThing[0].id, ["GET is successful"]
+
+      return
+
+
+    # HASCLASS ----------------------------------------------------------------
+
+    # The HASCLASS function tells you if a particular element has the specified
+    # class.
+
+    .then ->
+
+      hasFooClass = @.evaluate ->
+
+        return junction("#test").hasClass("foo")
+
+      test.assertEquals hasFooClass, true, ["HASCLASS is successful"]
+
+      return
+
+
+    # HEIGHT ------------------------------------------------------------------
+
+    # The HEIGHT function gets the height of the first element, or sets the
+    # height for everything in the set.
+
+    .then ->
+
+      setHeight = @.evaluate ->
+
+        junction("body").append("

")
+        junction("#height").height(300)
+        return junction("#height").height()
+
+      test.assertEquals setHeight, 300, ["HEIGHT is successful"]
+
+      return
+
+
+    # HTML --------------------------------------------------------------------
+
+    # The HTML function gets/sets the innerHTML attribute for all the elements.
+
+    .then ->
+
+
+      @.evaluate ->
+
+        junction("body").append("

")
+        junction("#html").append("

")
+        junction("#html").append("

")
+
+      htmlOne = @.evaluate ->
+
+        htmlOne = junction("#htmlChildOne")
+        htmlOne.innerHTML = "

"
+        return htmlOne.innerHTML
+
+      htmlTwo = @.evaluate ->
+
+        htmlTwo = junction("#htmlChildTwo").html("

")
+        return htmlTwo.html()
+
+      test.assertEquals htmlTwo, htmlOne, ["HTML is successful"]
+
+      return
+
+
+    # INDEX -------------------------------------------------------------------
+
+    # The INDEX function returns the index of the current element in the set.
+    # If you don't specify the selector it will return the first node.
+
+    # NOTE: Couldn't figure out how to get this to work. Seems like this
+    # should work. The INDEX is returning null.
+
+    # From SHOESTRING:
+
+		#

+		#

+		#

+		#

+
+  	# test('`.index()`', function() {
+  	# 	var $indexed = $fixture.find( ".index div" );
+  	# 	equal( $indexed.index( ".first" ), 0 ); <--- I'm testing this
+  	# 	equal( $indexed.index( ".second" ), 1 );
+    #
+  	# 	var $second = $fixture.find( ".index .second" );
+  	# 	equal( $second.index(), 1 );
+  	# });
+
+    .then ->
+
+      testThing = @.evaluate ->
+
+        junction("body").append("

")
+        junction(".index").append("

")
+        junction(".index").append("

")
+
+        thing = junction(".index div")
+        return thing.index(".childOne")
+
+      @.echo testThing
+
+      # test.assertEquals 1, 1, ["Index isn't finished yet."]
+      test.assertEquals testThing, 0, ["INDEX is successful."]
+
+      return
+
+
+    # INSERTAFTER -------------------------------------------------------------
+
+    # The INSERTAFTER function inserts the current set of things AFTER the
+    # matching selector.
+
+    .then ->
+
+      @.evaluate ->
+
+        junction("body").append("

")
+        junction("

").insertAfter("#insertAfter")
+
+      testElement = @.evaluate ->
+
+        te = document.getElementById("insertAfter")
+        temp = te.nextSibling
+        return temp
+
+      test.assertEquals testElement.attributes[0].textContent,
+                        "insertAfter2",
+                        ["INSERTAFTER is successful."]
+
+      return
+
+
+    # INSERTBEFORE ------------------------------------------------------------
+
+    # The INSERTBEFORE function inserts the current set of things BEFORE the
+    # matching selector.
+
+    .then ->
+
+      @.evaluate ->
+
+        junction("body").append("

")
+        junction("

").insertBefore("#insertBefore")
+
+      testElement = @.evaluate ->
+
+        te = document.getElementById("insertBefore")
+        temp = te.previousSibling
+        return temp
+
+      test.assertEquals testElement.attributes[0].textContent,
+                        "insertBefore2",
+                        ["INSERTBEFORE is successful."]
+
+      return
+
+
+    # IS ----------------------------------------------------------------------
+
+    # The IS function checks to see if anything in the current set of elements
+    # matches the selector.
+
+    .then ->
+
+      testThing = @.evaluate ->
+
+        return junction("#test").is("#test")
+
+      test.assertEquals testThing, true, ["IS is success."]
+
+      return
+
+
+    # LAST --------------------------------------------------------------------
+
+    # The LAST function returns the last element of a set.
+
+    .then ->
+
+      @.evaluate ->
+
+        junction("body").append("

")
+        junction("body").append("

")
+
+      testThing = @.evaluate ->
+
+        return junction(".last").last()[0]
+
+      test.assertEquals testThing.id, "lastTwo", ["LAST is successful"]
+
+      return
+
+
+    # NEXT --------------------------------------------------------------------
+
+    # The NEXT function returns an object with the set of siblings of each
+    # element in the original set.
+
+    # NOTE: Maybe I don't know what I'm doing but I don't think this is
+    # working correctly. There are 3 things inside .next so thing.next().length
+    # should be returning 2. Instead it's returning 0.
+
+    # From SHOESTRING:
+
+    #

+		#

+		#

+		#

+		#

+    #
+  	# test( '`.next()`', function() {
+  	# 	var $first, $all;
+    #
+  	# 	$first = $fixture.find( ".next .first" );
+  	# 	$all = $fixture.find( ".next > div" );
+    #
+    #
+  	# 	equal( $first.next().length, 1 );
+  	# 	equal( $first.next()[0], $fixture.find(".next .second")[0]);
+    #
+  	# 	equal( $all.next().length, 2 ); <--- I'M TESTING THIS
+  	# 	equal( $all.next()[0], $fixture.find(".next .second")[0]);
+  	# 	equal( $all.next()[1], $fixture.find(".next .third")[0]);
+  	# 	equal( $all.next()[2], undefined );
+  	# });
+
+    .then ->
+
+      nextLength = @.evaluate ->
+
+        junction("body").append("

")
+        junction(".next").append("

")
+        junction(".next").append("

")
+        junction(".next").append("

")
+
+        thing = junction("body").find(".next > div")
+        return thing.next().length
+
+      @.echo nextLength
+
+      test.assertEquals nextLength, 2, ["NEXT is successful."]
+
+      return
+
+
+    # NOT ---------------------------------------------------------------------
+
+    # The NOT function removes the selected elements from the current set
+
+    .then ->
+
+      isSoCount = @.evaluate ->
+
+        junction("body").append("

")
+        junction(".not").append("

")
+        junction(".not").append("

")
+        junction(".not").append("

")
+
+        thing = junction(".not > div")
+        return thing.not(".is-not").length
+
+      test.assertEquals isSoCount, 1, ["NOT is successful."]
+
+      return
+
+
+    # OFFSET ------------------------------------------------------------------
+
+    # The OFFSET function returns an object with the "top" and "left" properties
+    # of the first elements offsets
+
+    # SHOESTRING does NOT have a test for this.
+
+    .then ->
+
+      test.assertEquals 1, 1, ["OFFSET is not finished."]
+
+      return
+
+
+    # PARENT ------------------------------------------------------------------
+
+    # The PARENT function returns the first parents for each element in the set.
+
+    # TODO: Add a second test for the second child
+
+    .then ->
+
+      parent = @.evaluate ->
+
+        junction("body").append("

")
+        junction(".parent").append("

")
+        junction(".parent").append("

")
+
+        return junction(".parent")[0]
+
+      childOneParent = @.evaluate ->
+
+        children = junction(".child")
+
+        return children.parent()[0]
+
+      test.assertEquals childOneParent.attributes[0].textContent,
+                        parent.attributes[0].textContent,
+                        ["PARENT is successful."]
+
+      return
+
+
+    # PARENTS -----------------------------------------------------------------
+
+    # The PARENTS functions returns the set of all parents matching the selector
+    # for each element in the set.
+
+    # TODO: create tests for the rest of the parents array. See "echo" for the
+    # rest of the items.
+
+    .then ->
+
+      @.evaluate ->
+
+        junction("body").append("

")
+        junction(".parents").append("

")
+        junction(".parentOne").append("

")
+        junction(".parents").append("

")
+        junction(".parentTwo").append("

")
+
+        parents = junction(".parents")
+
+        children = parents.find(".child")
+
+        # __utils__.echo children.parents().length
+        # __utils__.echo children.parents()[0].attributes[0].textContent
+        # __utils__.echo children.parents()[1].attributes[0].textContent
+        # __utils__.echo children.parents()[2]
+        # __utils__.echo children.parents()[3].innerHTML
+        # __utils__.echo junction("html")[0].innerHTML
+        # __utils__.echo children.parents()[4].attributes[0].textContent
+
+      index0 = @.evaluate ->
+
+        indexThing = junction(".parents").find(".child").parents()[0]
+        return indexThing.attributes[0].textContent
+
+      index1 = @.evaluate ->
+
+        indexThing = junction(".parents").find(".child").parents()[1]
+        return indexThing.attributes[0].textContent
+
+      test.assertEquals index0, "parentOne", ["PARENTS returns correct parent at index 0."]
+      test.assertEquals index1, "parents", ["PARENTS returns correct parent at index 1"]
+
+      return
+
+
+    # PREPEND -----------------------------------------------------------------
+
+    # The PREPEND function adds the element or HTML string before the children
+    # of each element in the set.
+
+    # NOTE: It looks like this function doesn't work right now.
+
+    # From SHOESTRING:
+
+		#

+		#

+    #
+    # test( '`.prepend() adds a first child element', function() {
+  	# 	var tmp, $prepend = $fixture.find( ".prepend" );
+    #
+  	# 	tmp = $(	"

" );
+  	# 	$prepend.append( tmp[0] );
+  	# 	$prepend.append( "

" );
+  	# 	$prepend.append( ".testel" );
+    #
+  	# 	equal( $prepend.find( ".first" )[0], tmp[0] );
+  	# 	equal( $prepend.find( ".second" ).length, 1 );
+  	# 	equal( $prepend.find( ".testel" ).length, 1 );
+  	# });
+
+    # Interestingly, they don't actually test with .prepend here. This may
+    # may not work on their end either.
+
+    # As a first step I'm just trying to test whether or not the item was
+    # actually added to the DOM. That is failing.
+
+    .then ->
+
+      @.evaluate ->
+
+        junction("body").append("

")
+
+        junction(".prepend").prepend("

")
+
+      # test.assertEquals 1, 1, ["Prepend is not finished."]
+      test.assertExists ".firstPrependedThing", ["PREPEND is successful"]
+
+      return
+
+
+    # PREPENDTO ---------------------------------------------------------------
+
+    # The PREPENDTO function adds each element of the current set BEFORE the
+    # children of the selected elements.
+
+    # NOTE: I just going to guess that this function doesn't work yet. The
+    # Shoestring docs show the test for it using AppendTo. That tells me it
+    # doesn't work yet. Will try to clarify and then revisit.
+
+    # From SHOESTRING:
+
+  	# test( '`.prependTo() adds the all elements to the selected element` ', function() {
+  	# 	var tmp, $prepend = $fixture.find( ".prepend" );
+    #
+  	# 	tmp = $(	"

" );
+    #
+  	# 	tmp.appendTo( "#qunit-fixture > .prepend" );
+    #
+  	# 	equal( $prepend.find( ".first" )[0], tmp[0] );
+  	# });
+
+    .then ->
+
+      @.evaluate ->
+
+        junction("

").prependTo("body")
+
+      test.assertExists ".prependTo", ["PREPENDTO is successful."]
+
+      return
+
+
+    # PREV --------------------------------------------------------------------
+
+    # The PREV function returns an object containing one sibling before each
+    # element in the original set.
+
+    # It doesn't seem like this is working either. According to the Shoestring
+    # tests thing.prev().length here should return 1.
+
+    # From SHOESTRING:
+
+		#

+		#

+		#

+		#

+		#

+
+  	# test( '`.prev()`', function() {
+  	# 	var $last, $all;
+    #
+  	# 	$last = $fixture.find( ".prev div.third" );
+  	# 	$all = $fixture.find( ".prev > div" );
+    #
+  	# 	equal( $last.prev().length, 1 ); <--- I'M TESTING THIS
+  	# 	equal( $last.prev()[0], $fixture.find(".prev .second")[0]);
+    #
+  	# 	// ordering correct according to jquery api
+  	# 	// http://api.jquery.com/prev/
+  	# 	equal( $all.prev().length, 2 );
+  	# 	equal( $all.prev()[0], $fixture.find(".prev .first")[0]);
+  	# 	equal( $all.prev()[1], $fixture.find(".prev .second")[0]);
+  	# 	equal( $all.prev()[2], undefined );
+  	# });
+
+    .then ->
+
+      prevLength = @.evaluate ->
+
+        junction("body").append("

")
+        junction(".prev").append("

")
+        junction(".prev").append("

")
+        junction(".prev").append("

")
+
+        thing = junction(".prev div.prevThree")
+
+        return thing.prev().length
+
+      @.echo prevLength
+
+      test.assertEquals prevLength, 1, ["PREV is successful."]
+
+      return
+
+
+    # PREVALL -----------------------------------------------------------------
+
+    # The PREVALL function returns an object with the set of ALL siblings before
+    # each element in the original set.
+
+    # This doesn't look like it's working. According to the Shoestring tests
+    # thing.prevAll().length should be returning 2.
+
+    # From SHOESTRING:
+
+		#

+		#

+		#

+		#

+		#

+
+  	# test( '`.prevAll()`', function() {
+  	# 	var $last;
+    #
+  	# 	$last = $fixture.find( ".prevall div.third" );
+    #
+  	# 	equal( $last.prevAll().length, 2 ); <--- I"M TESTING THIS
+    #
+  	# 	// ordering correct according to jquery api
+  	# 	// http://api.jquery.com/prevall/
+  	# 	equal( $last.prevAll()[0], $fixture.find(".prevall .second")[0]);
+  	# 	equal( $last.prevAll()[1], $fixture.find(".prevall .first")[0]);
+  	# 	equal( $last.prevAll()[2], undefined );
+  	# });
+
+    .then ->
+
+      prevAllLength = @.evaluate ->
+
+        junction("body").append("

")
+        junction(".prevall").append("

")
+        junction(".prevall").append("

")
+        junction(".prevall").append("

")
+
+        thing = junction(".prevall div.prevallThree")
+
+        return thing.prevAll().length
+
+      @.echo prevAllLength
+
+      test.assertEquals prevAllLength, 2, ["PREVALL is successful."]
+
+      return
+
+
+    # PROP --------------------------------------------------------------------
+
+    # The PROP function gets the property value on the first element or sets
+    # the property value on all the elements in the set.
+
+    .then ->
+
+      # gets the property
+      property = @.evaluate ->
+
+        junction("body").append("

")
+
+        return junction(".prop").prop("class")
+
+      test.assertEquals property, "prop", ["PROP gets the property correctly"]
+
+      property = @.evaluate ->
+
+        junction(".prop").prop("class", "bar")
+
+        return junction(".bar").prop("class")
+
+      test.assertEquals property, "bar", ["PROP sets the property correctly."]
+
+      return
+
+
+    # PROPFIX -----------------------------------------------------------------
+
+    # SHOESTRING does not have a test for this.
+
+    # REMOVE ------------------------------------------------------------------
+
+    # The REMOVE function removes the current set of elements from the DOM.
+
+    .then ->
+
+      @.evaluate ->
+
+        junction("body").append("

")
+
+        junction(".remove").remove()
+
+      test.assertDoesntExist ".remove", ["REMOVE is successful."]
+
+      return
+
+
+    # REMOVEATTR --------------------------------------------------------------
+
+    # The REMOVEATTR function removes an attribute from each element in the
+    # current set
+
+    .then ->
+
+      before = @.evaluate ->
+
+        junction("body").append("

")
+        return junction(".removeattr")[0]
+
+      after = @.evaluate ->
+
+        junction(".removeattr").removeAttr("data-foo")
+        return junction(".removeattr")[0]
+
+      test.assertNotEquals after.attributes[1],
+                          before.attributes[1],
+                          ["REMOVEATTR removed the attribute"]
+
+      return
+
+
+    # REMOVECLASS -------------------------------------------------------------
+
+    # The REMOVECLASS function removes the class from the DOM for each element
+    # in the set.
+
+    .then ->
+
+      before = @.evaluate ->
+
+        junction("body").append("

")
+        return junction(".removeClass")[0]
+
+      after = @.evaluate ->
+
+        junction(".removeClass").removeClass("foo")
+        return junction(".removeClass")[0]
+
+      test.assertNotEquals after.className,
+                          before.className,
+                          ["REMOVECLASS removed the class."]
+
+      return
+
+
+    # REMOVEPROP --------------------------------------------------------------
+
+    # The REMOVEPROP function removes a property from each element of the
+    # current set.
+
+    .then ->
+
+      before = @.evaluate ->
+
+        junction("body").append("

")
+        return junction(".removeProp")
+
+      after = @.evaluate ->
+
+        junction(".removeProp").removeProp("class")
+        return junction(".removeProp")
+
+      test.assertNotEquals after, before, ["REMOVEPROP removed the property."]
+
+      return
+
+
+    # REPLACEWITH -------------------------------------------------------------
+
+    # The REPLACEWITH function replaces each element in the current set with
+    # the element or string specified.
+
+    # This function doesn't seem to be working. There should be a div with a
+    # class of "replacement" but it doesn't exist. Also, it looks like it got
+    # rid of the "replaceWith" div, but didn't add the "replacement" one back?
+
+    # From SHOESTRING:
+
+		#

+
+  	# test( '`.replaceWith()`', function() {
+  	# 	var $replaceWith = $fixture.find( ".replace-with" );
+    #
+  	# 	equal( $fixture.find( ".replace-with" ).length, 1 );
+    #
+  	# 	var old = $replaceWith.replaceWith( "

" );
+    #
+  	# 	equal( $fixture.find( ".replace-with" ).length, 0 );
+  	# 	equal( $fixture.find( ".replacement" ).length, 1 );
+  	# 	ok( old[0].className === "replace-with", "Returned element should be the original element copied" );
+  	# });
+
+    .then ->
+
+      before = @.evaluate ->
+
+        junction("body").append("

")
+        return junction(".replaceWith")[0]
+
+      after = @.evaluate ->
+
+        testThing = junction(".replaceWith")
+        testThing = testThing.replaceWith("

")
+        return junction(".replacement")[0]
+
+      @.echo before.className
+      @.echo after
+
+      test.assertNotEquals after, null, ["REPLACEWITH: The after object isn't null"]
+
+      # TODO: When this test passes, write a test to check the before and after.
+
+      return
+
+
+    # SERIALIZE ---------------------------------------------------------------
+
+    # The SERIALIZE function serializes child input element values into
+    # an object
+
+    .then ->
+
+      data = @.evaluate ->
+
+        junction("body").append("

")
+
+        testThing = junction(".serialize")
+
+        i = 0
+
+        while i < junction.inputTypes.length
+          type = junction.inputTypes[i]
+          input = "<input type='" + type + "'" + " name='" + type + "'" + " value='" + type + "'></input>"
+          testThing.append input
+          i++
+
+        otherThing = testThing.serialize()
+
+        return otherThing
+
+      test.assertEquals data["color"], "color", ["SERIALIZE is successful."]
+
+      return
+
+
+    # SIBLINGS ----------------------------------------------------------------
+
+    # The SIBLINGS function gets all of the sibling elements for each element
+    # in the current set.
+
+    .then ->
+
+      siblingCount = @.evaluate ->
+
+        junction("body").append("

")
+        junction(".siblings").append("

")
+        junction(".siblings").append("

")
+        junction(".siblings").append("

")
+
+        return junction(".siblingTwo").siblings().length
+
+      test.assertEquals siblingCount, 2, ["SIBLINGS is successful."]
+
+      return
+
+
+    # TEXT --------------------------------------------------------------------
+
+    # The TEXT function recursively retrieves the text content of each element
+    # in the current set.
+
+    .then ->
+
+      containerText = @.evaluate ->
+
+        junction("body").append("
Some Test Text
")
+        return junction(".text").text()
+
+      testText = "Some Test Text"
+
+      test.assertEquals containerText, testText, ["TEXT is successful."]
+
+      return
+
+
+    # TOGGLECLASS -------------------------------------------------------------
+
+    # The TOGGLECLASS function should add a class to the selected element if
+    # it isn't found or remove the class if it is found.
+
+    # Note: This is only in this library. Not in SHOESTRING.
+
+    .then ->
+
+      before = @.evaluate ->
+
+        junction("body").append("

")
+        return junction(".toggleClass").prop("class")
+
+      after = @.evaluate ->
+
+        junction(".toggleClass").toggleClass("someClass")
+        return junction(".toggleClass").prop("class")
+
+      test.assertNotEquals before, after, ["TOGGLECLASS removed the class."]
+
+      addClassBack = @.evaluate ->
+
+        junction(".toggleClass").toggleClass("someClass")
+        return junction(".toggleClass").prop("class")
+
+      test.assertNotEquals after, addClassBack, ["TOGGLECLASS added the class"]
+
+      return
+
+
+    # VAL ---------------------------------------------------------------------
+
+    # The VAL function gets the value of the first element or sets the value
+    # of all the elements in the current set.
+
+    .then ->
+
+      # Check to see that the function gets the value of the first element
+      itemValue = @.evaluate ->
+
+        junction("body").append("<input type='color' name='color' value='blue' class='val'></input>")
+        valItem = junction(".val")
+        return valItem.val()
+
+      test.assertEquals itemValue, "blue", ["VAL gets a value correctly."]
+
+      # Check to see that the function sets the value on the elements.
+      itemSetValue = @.evaluate ->
+
+        valItem = junction(".val")
+        valItem.val("orange")
+        return valItem.val()
+
+      test.assertEquals itemSetValue, "orange", ["VAL sets a value correctly."]
+
+      return
+
+
+    # WIDTH -------------------------------------------------------------------
+
+    # The WIDTH function gets the width value of the first element or sets the
+    # width for all the elements in the current set.
+
+    .then ->
+
+      widthValue = @.evaluate ->
+
+        junction("body").append("

")
+        widthItem = junction(".width")
+        widthItem.width("400px")
+        return widthItem.width()
+
+      test.assertEquals widthValue, 400, ["WIDTH is successful."]
+
+      return
+
+
+    # WRAPINNER ---------------------------------------------------------------
+
+    # The WRAPINNER function wraps the child elements in the provided HTML
+
+    # TODO: Write a test to check if the function actually wrapped .inner
+    # with .wrapper
+
+    .then ->
+
+      @.evaluate ->
+
+        junction("body").append("

")
+        junction(".wrapinner").append("

")
+        wrapInnerItem = junction(".wrapinner")
+        wrapInnerItem.wrapInner("

")
+
+      test.assertExists ".wrapper", ["WRAPINNER is successful."]
+
+      return
+
+
+  casper.run ->
+    test.done()
+    return
+
+  return


Include mean and standard deviations on box charts

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/tejasbubane/exercism.io.git/'


error message for creating an employee updated

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/roseliux/CafeTownsend-Angular-Rails.git/'


Added torro app

Added torro app

error: pathspec 'TorrentSearcher/site-static/webapp/app.coffee' did not match any file(s) known to git

--- TorrentSearcher/site-static/webapp/app.coffee
+++ TorrentSearcher/site-static/webapp/app.coffee
@@ -0,0 +1 @@
+torro_app = angular.module('torro')


test teacher link

test teacher link

error: pathspec 'tutor/specs/components/course_settings/add-teacher-link.spec.cjsx' did not match any file(s) known to git

--- tutor/specs/components/course_settings/add-teacher-link.spec.cjsx
+++ tutor/specs/components/course_settings/add-teacher-link.spec.cjsx
@@ -0,0 +1,35 @@
+{React, Testing, sinon, _, ReactTestUtils} = require '../helpers/component-testing'
+{Promise}      = require 'es6-promise'
+ld = require 'lodash'
+
+jest.mock('../../../src/helpers/clipboard')
+Clipboard = require '../../../src/helpers/clipboard'
+
+AddTeacher = require '../../../src/components/course-settings/add-teacher-link'
+COURSE_ID = '1'
+ROSTER = require '../../../api/courses/1/roster.json'
+
+
+{RosterActions, RosterStore} = require '../../../src/flux/roster'
+
+displayPopover = (props) ->
+  new Promise( (resolve, reject) ->
+    wrapper = mount(<AddTeacher {...props} />)
+    wrapper.simulate('click')
+    resolve(_.last document.querySelectorAll('.modal.add-instructor'))
+  )
+
+describe 'Course Settings, undrop student', ->
+
+  beforeEach ->
+    Clipboard.copy.mockClear()
+    @props =
+      courseId: COURSE_ID
+    RosterActions.loaded(ROSTER, COURSE_ID)
+
+  it 'displays teacher join url when clicked', ->
+    displayPopover(@props).then (dom) ->
+      expect(dom.querySelector('input').value).to.equal(
+        RosterStore.get(COURSE_ID).teach_url
+      )
+      expect(Clipboard.copy).toHaveBeenCalled()


payment: fix typo s/newer/never/ [fixes #78618494]

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/andrewjcasal/koding.git/'


Activity: appcontroller fetch improved

Activity: appcontroller fetch improved


Add location hash on Bootstrap tab clicks allowing a history state for tab clicks

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/maclover7/codetriage.git/'


updated return type documentation

updated return type documentation

--- app/assets/javascripts/condition.js.coffee
+++ app/assets/javascripts/condition.js.coffee
@@ -52,7 +52,7 @@

   ###*
   Ordinality
-  @returns {String}
+  @returns {CodedValue}
   ###
   ordinality: -> new hQuery.CodedValue @json['ordinality_code']['code'], @json['ordinality_code']['codeSystem']


Use Switch case instead of if-els-if.

Use Switch case instead of if-els-if.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/evercam/evercam-dashboard.git/'


Working on an overhaul

Working on an overhaul

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/damianb/crimson.git/'


Added assignees api methods

Added assignees api methods

error: pathspec 'modules/github/api/issues/assignees.coffee' did not match any file(s) known to git

--- modules/github/api/issues/assignees.coffee
+++ modules/github/api/issues/assignees.coffee
@@ -0,0 +1,8 @@
+$.extend GitHub.api,
+  'GET /repos/:owner/:repo/assignees':
+    doc: "This call lists all the available assignees (owner + collaborators) to which issues may be assigned."
+    f: 'getAssignees'
+
+  'GET /repos/:owner/:repo/assignees/:assignee':
+    doc: 'Check to see if a user is an assignee of a repo.'
+    f: 'isAssignee'


Check select value isn't empty before redirecting.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/lonelyplanet/rizzo.git/'


a known-good standalone config for Tutor

error: pathspec 'configs/webpack/testing-tutor.config.coffee' did not match any file(s) known to git

--- configs/webpack/testing-tutor.config.coffee
+++ configs/webpack/testing-tutor.config.coffee
@@ -0,0 +1,67 @@
+path = require 'path'
+webpack = require 'webpack'
+ExtractTextPlugin = require 'extract-text-webpack-plugin'
+
+DEV_LOADERS = ['react-hot', 'webpack-module-hot-accept']
+
+module.exports =
+  devtool: 'eval-source-map'
+  resolve:
+    root: [
+      path.resolve(__dirname, '../../tutor')
+      path.resolve(__dirname, '../../tutor/src')
+    ]
+    extensions: ['', '.js', '.json', '.coffee', '.cjsx']
+  entry:
+    tutor: [
+      'index.coffee',
+      'resources/styles/tutor.less'
+    ]
+    qa: [
+      'src/qa.coffee'
+    ]
+  output:
+    path: 'dist'
+    publicPath: 'http://localhost:8000/dist/'
+    filename: '[name].js'
+
+  module:
+    loaders:   [
+      { test: /\.coffee$/, loaders: DEV_LOADERS.concat('coffee-loader')}
+      { test: /\.cjsx$/,   loaders: DEV_LOADERS.concat('coffee-jsx-loader')}
+      { test: /\.svg/,     loader: 'svg-url-loader'}
+      { test: /\.(png|jpg)/, loader: 'file-loader?name=[name].[ext]'}
+      { test: /\.json$/,   loader: 'json-loader' }
+      {
+        test: /\.(woff|woff2|eot|ttf)/
+        loader: "url-loader?limit=30000&name=[name]-[hash].[ext]"
+      }
+      {
+        test: /\.less$/,   loaders: DEV_LOADERS.concat(
+          'style-loader', 'css-loader', 'less-loader'
+        ) }
+    ]
+
+  plugins: [
+    new webpack.HotModuleReplacementPlugin()
+  ]
+
+  devServer:
+    port: 8000
+    historyApiFallback: true
+    # It suppress error shown in console, so it has to be set to false.
+    quiet: false
+    progress: true
+    # It suppress everything except error, so it has to be set to false as well
+    # to see success build.
+    noInfo: false
+    filename: '[name].js',
+    stats:
+      # Config for minimal console.log mess.
+      assets: false,
+      colors: true,
+      version: false,
+      hash: false,
+      timings: false,
+      chunks: false,
+      chunkModules: false


further cleanup and finetuning of server

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/call-a3/claimed.git/'


Removed setConfig() subscription as configs are set in package settings. Response to #19 and #22

--- lib/atom_pair.coffee
+++ lib/atom_pair.coffee
@@ -54,7 +54,6 @@
     # Register command that toggles this view
     @subscriptions.add atom.commands.add 'atom-workspace', 'AtomPair:start new pairing session': => @startSession()
     @subscriptions.add atom.commands.add 'atom-workspace', 'AtomPair:join pairing session': => @joinSession()
-    @subscriptions.add atom.commands.add 'atom-workspace', 'AtomPair:set configuration keys': => @setConfig()
     @subscriptions.add atom.commands.add 'atom-workspace', 'AtomPair:invite over hipchat': => @inviteOverHipChat()
     @subscriptions.add atom.commands.add 'atom-workspace', 'AtomPair:invite over slack': => @inviteOverSlack()
     @subscriptions.add atom.commands.add 'atom-workspace', 'AtomPair:custom-paste': => @customPaste()


Basic HTTP Client

Basic HTTP Client

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/mjpuser/riak-client.git/'


updated host api to html2haml-attributes.herokuapp.com

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/jaunkst/atom-html2haml.git/'


Missing `break` statement when encountering an unmatched scope end tag

--- src/tokenized-buffer.coffee
+++ src/tokenized-buffer.coffee
@@ -381,6 +381,7 @@
                 filePath: @buffer.getPath()
                 fileContents: @buffer.getText()
               }
+            break
     scopes

   indentLevelForRow: (bufferRow) ->


Reinstate ad manager init

Reinstate ad manager init


Repository test: use test repo

Repository test: use test repo

--- test/test.repository.coffee
+++ test/test.repository.coffee
@@ -4,40 +4,35 @@
 fixtures = require "./fixtures"

 describe "Repository", ->
-	describe "Using the project repo...", ->
+	describe "Using the test repo...", ->
 		repo = null
 		it "opens correctly", (done) ->
-			gitteh.openRepository fixtures.projectRepo.path, (err, _repo) ->
+			gitteh.openRepository fixtures.testRepo.path, (err, _repo) ->
 				repo = _repo
 				repo.should.be.an.instanceof gitteh.Repository
 				done()
 		describe "#bare", ->
-			it "should be false for this repo", ->
-				repo.bare.should.be.false
+			it "should be true for this repo", ->
+				repo.bare.should.be.true
 			it "should be immutable", ->
 				repo.bare = 123
-				repo.bare.should.be.false
+				repo.bare.should.be.true
 				delete repo.path
-				repo.bare.should.be.false
+				repo.bare.should.be.true
 		describe "#path", ->
-			it "should point to #{fixtures.projectRepo.gitPath}", ->
-				repo.path.should.equal fixtures.projectRepo.gitPath
+			it "should point to #{fixtures.testRepo.path}", ->
+				repo.path.should.equal fixtures.testRepo.path
 			it "should be immutable", ->
 				repo.path = "foo"
-				repo.path.should.equal fixtures.projectRepo.gitPath
+				repo.path.should.equal fixtures.testRepo.path
 				delete repo.path
-				repo.path.should.equal fixtures.projectRepo.gitPath
+				repo.path.should.equal fixtures.testRepo.path
 		describe "#workingDirectory", ->
-			it "should point to #{fixtures.projectRepo.path}", ->
-				repo.workingDirectory.should.equal fixtures.projectRepo.path
-			it "should be immutable", ->
-				repo.path = "foo"
-				repo.workingDirectory.should.equal fixtures.projectRepo.path
-				delete repo.path
-				repo.workingDirectory.should.equal fixtures.projectRepo.path
+			it "should be null", ->
+				should.not.exist repo.workingDirectory
 		describe "#exists()", ->
 			it "should return true for first commit in repo :)", (done) ->
-				repo.exists "1f4425ce2a14f21b96b9c8dde5bcfd3733467b14", (err, exists) ->
+				repo.exists fixtures.testRepo.firstCommit.id, (err, exists) ->
 					exists.should.be.true
 					done()
 			it "should reject invalid oids", ->
@@ -52,42 +47,42 @@
 				).should.throw()
 		describe "#object()", ->
 			it "works for full OID", (done) ->
-				repo.object "1f4425ce2a14f21b96b9c8dde5bcfd3733467b14", (err, obj) ->
+				repo.object fixtures.testRepo.secondCommit.id, (err, obj) ->
 					should.not.exist err
 					obj.should.be.an.instanceof gitteh.Commit
 					done()
 			it "works for shortened OID", (done) ->
-				repo.object "1f4425ce2a", (err, obj) ->
+				repo.object fixtures.testRepo.secondCommit.id[..8], (err, obj) ->
 					should.not.exist err
 					obj.should.be.an.instanceof gitteh.Commit
 					done()
 		describe "#commit()", ->
 			it "works", (done) ->
-				repo.commit "1f4425ce2a14f21b96b9c8dde5bcfd3733467b14", (err, obj) ->
+				repo.commit fixtures.testRepo.secondCommit.id, (err, obj) ->
 					should.not.exist err
 					obj.should.be.an.instanceof gitteh.Commit
 					done()
 			it "fails for objects that aren't a commit", (done) ->
-				repo.commit fixtures.projectRepo.secondCommit.wscriptBlob, (err, obj) ->
+				repo.commit fixtures.testRepo.secondCommit.readmeBlob, (err, obj) ->
 					should.exist err
 					done()
 		describe "#tree()", ->
 			it "works", (done) ->
-				repo.tree fixtures.projectRepo.secondCommit.tree, (err, obj) ->
+				repo.tree fixtures.testRepo.secondCommit.tree, (err, obj) ->
 					should.not.exist err
 					obj.should.be.an.instanceof gitteh.Tree
 					done()
 			it "fails for objects that aren't a tree", (done) ->
-				repo.tree fixtures.projectRepo.secondCommit.id, (err, obj) ->
+				repo.tree fixtures.testRepo.secondCommit.id, (err, obj) ->
 					should.exist err
 					done()
 		describe "#blob()", ->
 			it "works", (done) ->
-				repo.blob fixtures.projectRepo.secondCommit.wscriptBlob, (err, obj) ->
+				repo.blob fixtures.testRepo.secondCommit.readmeBlob, (err, obj) ->
 					should.not.exist err
 					obj.should.be.an.instanceof gitteh.Blob
 					done()
 			it "fails for objects that aren't a blob", (done) ->
-				repo.blob fixtures.projectRepo.secondCommit.id, (err, obj) ->
+				repo.blob fixtures.testRepo.secondCommit.id, (err, obj) ->
 					should.exist err
 					done()


Comitted missing unit test file

Comitted missing unit test file

error: pathspec 'test/dotted-key.coffee' did not match any file(s) known to git

--- test/dotted-key.coffee
+++ test/dotted-key.coffee
@@ -0,0 +1,59 @@
+chai        = require "chai"
+objectUtils = require "../lib/utils.js"
+
+describe( "Object value retrieval", () ->
+    describe( "#getValue()", () ->
+        it( "Should get the value", () ->
+            testObject =  {
+                foo:
+                    bar: true
+            }
+
+            chai.expect( objectUtils.getValue( "foo.bar", testObject ) ).to.eql( true )
+        )
+    )
+
+    describe( "#getValue()", () ->
+        it( "Should get the value", () ->
+            testObjectWithDottedKey =  {
+                "foo.cheese":
+                    bar: true
+            }
+
+            chai.expect( objectUtils.getValue( "foo%2Echeese.bar", testObjectWithDottedKey ) ).to.eql( true )
+        )
+    )
+
+    describe( "#createValue()", () ->
+        it( "Should create the value", () ->
+            testCreate = {}
+
+            objectUtils.getAndCreate( "foo%2Echeese.bar", testCreate )
+
+            chai.expect( testCreate[ "foo.cheese" ].bar ).to.eql( {} )
+        )
+    )
+
+
+    describe( "#setValue()", () ->
+        it( "Should set the value", () ->
+            testSet =
+                "foo.cheese":
+                    bar: "yes"
+
+            objectUtils.setValue( "foo%2Echeese.bar", testSet, 1 )
+
+            chai.expect( testSet[ "foo.cheese" ].bar ).to.eql( 1 )
+        )
+    )
+
+    describe( "#setAndCreateValue()", () ->
+        it( "Should create and set the value", () ->
+            testCreateSet = {}
+
+            objectUtils.setValue( "foo%2Echeese.bar", testCreateSet, 1 )
+
+            chai.expect( testCreateSet[ "foo.cheese" ].bar ).to.eql( 1 )
+        )
+    )
+)


catch stray clicks and resizes (e.g. orientation change)

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/UCSFMemoryAndAging/tabcat.git/'


able to mention review comment

able to mention review comment

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/kutsuzawa/gitnotification.git/'


Avoid unhandled promise rejection warning

--- spec/integration/helpers/start-atom.coffee
+++ spec/integration/helpers/start-atom.coffee
@@ -95,7 +95,7 @@
     "--url-base=/wd/hub"
   ])

-  chromedriverExit = new Promise (resolve, reject) ->
+  chromedriverExit = new Promise (resolve) ->
     errorCode = null
     logs = []
     chromedriver.on "exit", (code, signal) ->
@@ -103,10 +103,7 @@
     chromedriver.stderr.on "data", (log) ->
       logs.push(log.toString())
     chromedriver.stderr.on "close", ->
-      if errorCode?
-        reject("Chromedriver failed. Code: #{errorCode}. Logs: #{logs.join("\n")}")
-      else
-        resolve()
+      resolve({errorCode, logs})

   waitsFor("webdriver to finish", (done) ->
     finish = once ->
@@ -114,15 +111,18 @@
         .end()
         .then(-> chromedriver.kill())
         .then(chromedriverExit.then(
-          done,
-          (message) ->
-            jasmine.getEnv().currentSpec.fail(message)
+          ({errorCode, logs}) ->
+            if errorCode?
+              jasmine.getEnv().currentSpec.fail """
+                Chromedriver exited with code #{errorCode}.
+                Logs:\n#{logs.join("\n")}
+              """
             done()))

     client = buildAtomClient(args, env)

-    client.on "error", ({err, body}) ->
-      jasmine.getEnv().currentSpec.fail(err ? body.value.message)
+    client.on "error", ({body}) ->
+      jasmine.getEnv().currentSpec.fail(body)
       finish()

     fn(client.init()).then(finish)


avatararea: accountpopup simplified

avatararea: accountpopup simplified

error: pathspec 'client/app/lib/avatararea/accountpopup.coffee' did not match any file(s) known to git

--- client/app/lib/avatararea/accountpopup.coffee
+++ client/app/lib/avatararea/accountpopup.coffee
@@ -0,0 +1,116 @@
+kd                        = require 'kd'
+AvatarPopup               = require './avatarpopup'
+CustomLinkView            = require '../customlinkview'
+HelpSupportModal          = require '../commonviews/helpsupportmodal'
+trackEvent                = require 'app/util/trackEvent'
+
+module.exports = class AccountPopup extends AvatarPopup
+
+  constructor: (options = {}, data) ->
+
+    options.cssClass = kd.utils.curry 'account', options.cssClass
+
+    super options, data
+
+    { groupsController } = kd.singletons
+
+    @avatarPopupContent.addSubView new CustomLinkView
+      title      : 'Upgrade plan'
+      href       : '/Pricing'
+      cssClass   : 'bottom-separator'
+      click      : @bound 'goToPricing'
+
+    @avatarPopupContent.addSubView new CustomLinkView
+      title      : 'Koding University'
+      href       : 'http://learn.koding.com'
+      target     : '_blank'
+
+    @avatarPopupContent.addSubView new CustomLinkView
+      title      : 'Contact support'
+      cssClass   : 'bottom-separator support'
+      click      : @bound 'goToSupport'
+
+    @avatarPopupContent.addSubView new CustomLinkView
+      title      : 'Account Settings'
+      href       : '/Account'
+      attributes : testpath : 'AccountSettingsLink'
+      cssClass   : 'bottom-separator'
+      click      : @bound 'goToAccountSettings'
+
+    @avatarPopupContent.addSubView dashboardLink = new CustomLinkView
+      title    : 'Group Dashboard'
+      href     : '/Dashboard'
+      cssClass : 'bottom hidden'
+      click    : @bound 'goToDashboard'
+
+    @avatarPopupContent.addSubView adminLink = new CustomLinkView
+      title    : 'Team Settings'
+      href     : '/Admin'
+      cssClass : 'bottom hidden'
+      click    : @bound 'goToTeamSettings'
+
+    @avatarPopupContent.addSubView new CustomLinkView
+      title      : 'Logout'
+      href       : '/Logout'
+      attributes : testpath : 'logout-link'
+
+    # FIXME:
+    groupsController.ready ->
+      group = groupsController.getCurrentGroup()
+      group.canEditGroup (err, success) ->
+        return  unless success
+        dashboardLink.show()
+        adminLink.show()
+
+
+
+  hide:->
+
+    super
+
+    @emit 'AvatarPopupShouldBeHidden'
+
+
+  goToPricing: (event) ->
+
+    kd.utils.stopDOMEvent event
+    kd.singletons.router.handleRoute '/Pricing'
+    @hide()
+
+    trackEvent 'Account upgrade plan, click',
+      category : 'userInteraction'
+      action   : 'clicks'
+      label    : 'settingsUpgradePlan'
+
+
+  goToSupport: (event) ->
+
+    kd.utils.stopDOMEvent event
+    new HelpSupportModal
+    @hide()
+
+    trackEvent 'Contact support, click',
+      category : 'userInteraction'
+      action   : 'formsubmits'
+      label    : 'contactKodingSupport'
+
+
+  goToAccountSettings: (event) ->
+
+    kd.utils.stopDOMEvent event
+    kd.singletons.router.handleRoute '/Account'
+    @hide()
+
+
+  goToDashboard: (event) ->
+
+    kd.utils.stopDOMEvent event
+    kd.singletons.router.handleRoute "/Dashboard"
+    @hide()
+
+
+  goToTeamSettings: (event) =>
+
+    kd.utils.stopDOMEvent event
+    kd.singletons.router.handleRoute "/Admin"
+    @hide()


Tests: Fix HLS Segmenter tests

Tests: Fix HLS Segmenter tests

These tests are pretty funky to reason through due to the way that timing
impacts them. For now, fix our start_ts to the start of a segment, so that we
can easily compute how many segments should be returned in each scenario.

--- test/hls_segmenter.coffee
+++ test/hls_segmenter.coffee
@@ -31,18 +31,12 @@
     chunk_duration      = 1000
     segment_duration    = 10000

-    start_ts = new Date(1415290170623)
-    #start_ts = new Date()
-
-    # If our start_ts falls exactly on a segment start, we need to give a bump
-    # to expected segment counts where we're going backward and forward
-
-    seg_bonus = 0
-    start_sec = Math.floor( Number(start_ts) / 1000 ) * 1000
-    if Math.floor( start_sec / segment_duration ) * segment_duration == start_sec
-        seg_bonus = 1
-
-    console.log "Start ts is ", start_ts, seg_bonus
+    start_ts = new Date()
+
+    # to make life easy to reason about, we'll put start_ts on a segment start.
+    start_ts = new Date( Math.round(start_ts / segment_duration) * segment_duration )
+
+    console.log "Start ts is ", start_ts

     #----------

@@ -74,7 +68,7 @@
                     segments.push s

             injector.once "finish", ->
-                expect(segments.length).to.eql 3
+                expect(segments.length).to.be.eql 3
                 expect( Number(segments[1].ts) - Number(segments[0].ts) ).to.eql segment_duration

                 done()
@@ -101,7 +95,7 @@
                     segments.push s

             injector.once "finish", ->
-                expect(segments.length).to.eql 3
+                expect(segments.length).to.be.eql 3
                 expect( Number(segments[0].ts) - Number(segments[1].ts) ).to.eql segment_duration

                 done()
@@ -110,15 +104,13 @@
                 generator.end()

         it "emits mixed segments when given mixed data", (done) ->
-            expected_segs = 5 + seg_bonus
-
             segments = []
             injector.on "readable", ->
                 while s = injector.read()
                     segments.push s

             injector.once "finish", ->
-                expect(segments.length).to.eql expected_segs
+                expect(segments).to.have.length.within 6,7

                 # sort by ts
                 segments = _(segments).sortBy (s) -> Number(s.ts)
@@ -161,7 +153,10 @@
             injector.pipe(finalizer)

             finalizer.on "finish", ->
-                expect( finalizer.segmentSeq ).to.eql 2
+                # even though three segments worth of data gets pushed into
+                # the injector, it currently doesn't know how to trigger the
+                # emit of its first segment into the finalizer.
+                expect( finalizer.segmentSeq ).to.be.eql 2
                 expect( finalizer.discontinuitySeq ).to.eql 0
                 expect( finalizer.segments ).to.have.length 2
                 expect( finalizer.segments[0].id ).to.eql 0
@@ -171,15 +166,11 @@
             generator.forward 31, -> generator.end()

         it "creates a discontinuity when given a gap", (done) ->
-            # if our start aligned, we don't get the truncated segment that
-            # would have otherwise been emitted
-            expected_seq = 3 - seg_bonus
-
             finalizer = new HLSSegmenter.Finalizer (new Logger {})
             injector.pipe(finalizer)

             finalizer.on "finish", ->
-                expect( finalizer.segmentSeq ).to.eql expected_seq
+                expect( finalizer.segmentSeq ).to.be.eql 3
                 expect( finalizer.discontinuitySeq ).to.eql 1

                 expect( finalizer.segments[ 0 ].discontinuitySeq ).to.eql 0
@@ -187,8 +178,8 @@

                 done()

-            generator.forward 20, -> generator.skip_forward 10, ->
-                generator.forward 10, -> generator.end()
+            generator.forward 30, -> generator.skip_forward 15, ->
+                generator.forward 11, -> generator.end()

         it "will use a segment map to assign sequence numbers", (done) ->
             f_seg = injector._createSegment start_ts
@@ -196,8 +187,7 @@
             seq = 5
             seg_map = {}
             for i in [0..2]
-                seg_map[ Number(f_seg.ts) + i*segment_duration ] = seq
-                seq += 1
+                seg_map[ Number(f_seg.ts) + i*segment_duration ] = seq + i

             finalizer = new HLSSegmenter.Finalizer (new Logger {}),
                 segmentSeq:         8
@@ -208,11 +198,14 @@
             injector.pipe(finalizer)

             finalizer.on "finish", ->
-                expect(finalizer.segments).to.have.length 4
-                expect(finalizer.segments[0].id).to.eql 5
-                expect(finalizer.segments[1].id).to.eql 6
-                expect(finalizer.segments[2].id).to.eql 7
-                expect(finalizer.segments[3].id).to.eql 8
+                expect(finalizer.segments).to.have.length.within 4,5
+
+                if finalizer.segments.length == 4
+                    expect(finalizer.segments[ finalizer.segments.length - 4 ].id).to.eql 5
+
+                expect(finalizer.segments[ finalizer.segments.length - 3 ].id).to.eql 6
+                expect(finalizer.segments[ finalizer.segments.length - 2 ].id).to.eql 7
+                expect(finalizer.segments[ finalizer.segments.length - 1 ].id).to.eql 8

                 done()

@@ -239,12 +232,13 @@
                 expect(finalizer.segments).to.have.length 4

                 for seg in finalizer.segments
-                    if Number(seg.ts) == start_sec
-                        expect(seg.id).to.eql 8
-                    else
+                    if seg.id < 8
                         map_id = seg_map[ Number( seg.ts ) ]
                         expect(map_id).to.not.be.undefined
                         expect(seg.id).to.eql map_id
+
+                    else
+                        expect(seg.id).to.eql 8

                 done()

@@ -389,8 +383,9 @@

             rewind.hls_segmenter.once "_finalizer", ->
                 setTimeout ->
-                    expect(injector_pushes).to.eql 5
-                    expect(rewind.hls_segmenter.finalizer.segments).to.have.length 5
+
+                    expect(injector_pushes).to.be.within 4,5
+                    expect(rewind.hls_segmenter.finalizer.segments).to.have.length.within 4,5
                     done()
                 , 200

@@ -425,7 +420,7 @@
                         # snapshot we exported, since the Injector doesn't see
                         # that the last segment should be finalized (no data
                         # pushed beyond the end_ts)
-                        expect(snap2.segments).to.have.length 11
+                        expect(snap2.segments).to.have.length snap1.segments.length - 1

                         done()


kill iOS simulator harder

kill iOS simulator harder

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/AppGyver/steroids.git/'


Simplify code.

Simplify code.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/gmist/five-studio2.git/'


Start on a generic tooltipped class

Start on a generic tooltipped class

error: pathspec 'app/controllers/tooltipped.coffee' did not match any file(s) known to git

--- app/controllers/tooltipped.coffee
+++ app/controllers/tooltipped.coffee
@@ -0,0 +1,54 @@
+attach = require 'zootorial/lib/attach'
+$ = require 'jqueryify'
+
+log = -> console?.log? arguments...
+
+class Tooltipped
+  @fromDOM: (el) ->
+    el = $(el)
+    popup = el.parents().last().find el.attr 'data-popup'
+    log {el, popup}
+    position = el.attr('data-popup-position') || ''
+    [attachAt, attachTo] = position.split /\s*\,\s*/
+    attachAt ?= @::attachAt
+    attachTo ?= @::attachTo
+    new @ {el, popup, attachAt, attachTo}
+
+  el: null
+  popup: null
+  attachAt: 'center bottom'
+  attachTo: 'center top'
+  attachMargin: 0
+  classDelay: 0
+
+  constructor: (params = {}) ->
+    @[key] = value for own key, value of params when key of @
+
+    @el.on 'click', @onClick
+
+    @popup.addClass 'hidden'
+    @popup.remove()
+
+    $(document).on 'click', @onDocumentClick
+
+  onClick: (e) =>
+    @toggle()
+
+  onDocumentClick: ({target}) =>
+    @close() unless $(target).parents().andSelf().is @el
+
+  toggle: ->
+    if @el.hasClass 'open' then @close() else @open()
+
+  open: ->
+    @el.addClass 'open'
+    @popup.appendTo 'body'
+    attach @popup, @attachAt.split(/\s/), @el, @attachTo.split(/\s/), margin: @attachMargin
+    setTimeout $.proxy(@popup, 'removeClass', 'hidden'), @classDelay
+
+  close: ->
+    @el.removeClass 'open'
+    @popup.addClass 'hidden'
+    setTimeout $.proxy(@popup, 'remove'), @classDelay
+
+module.exports = Tooltipped


snapshot motion level options added

snapshot motion level options added


removed TODO

removed TODO

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/patleb/admineer.git/'


Add custom selection keybinding

Add custom selection keybinding

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/danielgavrilov/dotfiles.git/'


Bug fix in sparkline directive

Bug fix in sparkline directive

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/MicrosmartSA/ubiquity-ui.git/'


Remove dead code

Remove dead code

--- plugins/hipchat/index.coffee
+++ plugins/hipchat/index.coffee
@@ -41,7 +41,7 @@
       color: config.color || "yellow"

     # Send the request
-    response = if config.authToken.length == 40
+    if config.authToken.length == 40
       @request
         .post(getApiUrl(config, "v2/room/#{config.roomId}/notification"))
         .set("Content-Type", "application/json")


:art: Cleanup

:art: Cleanup

/bin/sh: 1: Syntax error: "(" unexpected


add current user loaded logic to close double session issue (for now)

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/companytools/ember-cli-dunlop.git/'


Nicer use of spawn

Nicer use of spawn

--- src/docker-utils.coffee
+++ src/docker-utils.coffee
@@ -88,7 +88,7 @@
 		return [ rsyncDiff, imageConfig, imgSrc ]
 	.spread (rsyncDiff, imageConfig, imgSrc) ->
 		new Promise (resolve, reject) ->
-			dockersync = spawn('/app/src/dockersync.sh', [ imgSrc, imgDest, JSON.stringify(imageConfig) ], stdio: [ 'pipe', 'pipe', 'pipe' ])
+			dockersync = spawn('/app/src/dockersync.sh', [ imgSrc, imgDest, JSON.stringify(imageConfig) ], stdio: 'pipe')
 			.on 'error', reject
 			.on 'exit', (code, signal) ->
 				if code in DELTA_OUT_OF_SYNC_CODES


Use subscribe for window focus listener

Use subscribe for window focus listener

--- src/fuzzy-finder.coffee
+++ src/fuzzy-finder.coffee
@@ -21,7 +21,7 @@

   initialize: (@rootView) ->
     super
-    $(window).on 'focus', => @projectPaths = null
+    @subscribe $(window), 'focus', => @projectPaths = null
     @observeConfig 'fuzzy-finder.ignoredNames', (ignoredNames) =>
       @projectPaths = null


Activity: modify submit button to work with latency compensation

--- client/Social/Activity/views/inputwidget.coffee
+++ client/Social/Activity/views/inputwidget.coffee
@@ -29,7 +29,7 @@
       title       : "SEND"
       cssClass    : "solid green small"
       loader      : yes
-      callback    : @bound "submit"
+      callback    : => @submit @input.getValue()

     @buttonBar    = new KDCustomHTMLView
       cssClass    : "widget-button-bar"


Add dropdown li component

Add dropdown li component

[#98173630]

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/netguru/review.git/'


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/engine_selector.coffee
+++ src/engine_selector.coffee
@@ -59,7 +59,8 @@
   @param {String} selector
   @returns {Array} An array of the objects found
   ###
-  each: (selector, fn)
+  each: (selector, fn) ->
+

   find: (selector) ->
     results = []


Added boolean filters.

Added boolean filters.

error: pathspec 'src/filters/boolean.coffee' did not match any file(s) known to git

--- src/filters/boolean.coffee
+++ src/filters/boolean.coffee
@@ -0,0 +1,19 @@
+##
+##
+## Takes in a value and returns "true" or "false" based on its boolean value. The true and false
+## strings can be customized.
+module = angular.module("Mac")
+
+module.filter "boolean", ->
+  (boolean, trueString = "true", falseString = "false") ->
+    if boolean then trueString else falseString
+
+# Similar to the boolean filter, but you only need to provide a true string.
+module.filter "true", ->
+  (boolean, trueString = "true") ->
+    if boolean then trueString else ""
+
+# Similar to the boolean filter, but you only need to provide a false string.
+module.filter "false", ->
+  (boolean, falseString = "false") ->
+    if boolean then "" else falseString


implement Developer menubar

implement Developer menubar

error: pathspec 'app/scripts/menus.coffee' did not match any file(s) known to git

--- app/scripts/menus.coffee
+++ app/scripts/menus.coffee
@@ -0,0 +1,43 @@
+# nw.gui requires it to be named require
+require = window.requireNode
+gui = require('nw.gui')
+win = gui.Window.get()
+menubar = new gui.Menu(type: 'menubar')
+menubar.createMacBuiltin('Daemon')
+debugMenu = new gui.Menu()
+
+debugMenu.append new gui.MenuItem(
+  label: "Reload"
+  click: -> win.reload()
+  key: "r"
+  modifiers: "cmd"
+  )
+
+debugMenu.append new gui.MenuItem(
+  label: "Reload and Clear Cache"
+  click: -> win.reloadIgnoringCache()
+  key: "r"
+  modifiers: "cmd-shift"
+  )
+
+debugMenu.append new gui.MenuItem(
+  label: "Toggle Kiosk Mode"
+  click: -> win.toggleKioskMode()
+  key: "f"
+  modifiers: "cmd-shift"
+  )
+
+debugMenu.append new gui.MenuItem type: 'separator'
+
+debugMenu.append new gui.MenuItem(
+  label: "Developer Tools"
+  click: -> win.showDevTools()
+  key: "i"
+  modifiers: "cmd-alt"
+  )
+
+menubar.append new gui.MenuItem(
+  label: 'Developer'
+  submenu: debugMenu
+  )
+win.menu = menubar


Don't specify noVideo if the beatmapset doesn't contain a video

--- resources/assets/coffee/react/beatmapset-page/header.coffee
+++ resources/assets/coffee/react/beatmapset-page/header.coffee
@@ -174,7 +174,7 @@
                 else
                   @downloadButton
                     key: 'default'
-                    href: laroute.route 'beatmapsets.download', beatmapset: @props.beatmapset.id, noVideo: 1
+                    href: laroute.route 'beatmapsets.download', beatmapset: @props.beatmapset.id

                 @downloadButton
                   key: 'direct'


go improvements

go improvements

--- atom.symlink/config.cson
+++ atom.symlink/config.cson
@@ -6,13 +6,13 @@
     showIndentGuide: true
     showInvisibles: true
     scrollPastEnd: true
+    projectHome: "~/Code/"
   core:
     hideGitIgnoredFiles: true
     autoHideMenuBar: true
-  "exception-reporting":
-    userId: "eb68b94c-a76b-64f4-46e7-bd087cf1c98f"
   welcome:
     showOnStartup: false
   linter: {}
-  "atom-beautify":
-    _analyticsUserId: "3dfda927-6973-4e63-abf4-4da87de58f7a"
+  "go-plus":
+    goPath: "~/Code/Go"
+  "go-rename": {}


Add atom keybindings

Add atom keybindings

error: pathspec 'atom.symlink/keymap.cson' did not match any file(s) known to git

--- atom.symlink/keymap.cson
+++ atom.symlink/keymap.cson
@@ -0,0 +1,2 @@
+'.editor':
+  'cmd-alt-l': 'editor:auto-indent'


removed usage of groupinvitationview from dashboard.index file

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/andrewjcasal/koding.git/'


bug fix

bug fix

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/bubblegroup/bubblebot.git/'


Activity serving page for activity and topics.

error: pathspec 'server/lib/crawler/staticpages/feed.coffee' did not match any file(s) known to git

--- server/lib/crawler/staticpages/feed.coffee
+++ server/lib/crawler/staticpages/feed.coffee
@@ -0,0 +1,200 @@
+{argv}                               = require 'optimist'
+{uri}                                = require('koding-config-manager').load("main.#{argv.c}")
+{ daisy }                            = require "bongo"
+{ Relationship }                     = require 'jraphical'
+{ createActivityContent, decorateComment } = require '../helpers'
+
+{
+  isLoggedIn
+  error_404
+  error_500
+} = require '../../server/helpers'
+
+ITEMSPERPAGE = 20
+
+module.exports = (bongo, page, contentType, callback)=>
+  {JName, JAccount, JStatusUpdate, JTag} = bongo.models
+  skip = 0
+  if page > 0
+    skip = (page - 1) * 5
+
+
+  options = {
+    limit : ITEMSPERPAGE
+    skip  : skip
+    sort: 'meta.createdAt': -1
+  }
+
+  if contentType is "Activity"
+    model = JStatusUpdate
+  else if contentType is "Topics"
+    model = JTag
+  else
+    return callback new Error "Unknown content type.", null
+
+  pageContent = ""
+  model.count {}, (error, count)=>
+    return callback error, null if error or not count
+    model.some {}, options, (err, contents)=>
+      return callback new Error "Parameter error", null  if contents.length is 0
+
+      queue = [0..contents.length - 1].map (index)=>=>
+        queue.pageContent or= ""
+
+        content = contents[index]
+
+        if contentType is "Activity"
+          appendDecoratedStatusUpdate JAccount, content, queue
+        else if contentType is "Topics"
+          appendDecoratedTopic content, queue
+        else queue.next()
+      queue.push =>
+        schemaorgTagsOpening = getSchemaOpeningTags contentType
+        schemaorgTagsClosing = getSchemaClosingTags contentType
+
+        content = schemaorgTagsOpening + queue.pageContent + schemaorgTagsClosing
+
+        pagination = getPagination page, count, contentType
+        fullPage = putContentIntoFullPage content, pagination
+        return callback null, fullPage
+      daisy queue
+
+appendDecoratedStatusUpdate = (JAccount, newstatusupdate, queue)=>
+  if typeof newstatusupdate.fetchRelativeComments is "function"
+    newstatusupdate?.fetchRelativeComments? limit:3, after:"", (error, comments)=>
+      commentQueue = [0..comments.length].map (index)=>=>
+        comment = comments[index]
+        if comment?
+          # Get comments authors, put comment info into commentSummaries
+          decorateComment JAccount, comment, (error, commentSummary)=>
+            commentQueue.next() if error
+            commentQueue.commentSummaries or= []
+            if commentSummary.body
+              commentQueue.commentSummaries.push commentSummary
+            commentQueue.next()
+        else commentQueue.next()
+      commentQueue.push =>
+        createActivityContent JAccount, newstatusupdate, commentQueue.commentSummaries, no, (error, content)=>
+          commentQueue.next() if error
+          queue.pageContent = queue.pageContent + content
+          queue.next()
+      commentQueue.push => queue.next()
+      daisy commentQueue
+  else
+    createActivityContent JAccount, newstatusupdate, {}, no, (error, content)=>
+      queue.pageContent = queue.pageContent + content
+
+getPagination = (currentPage, numberOfItems, contentType)->
+  # This is the number of adjacent link around current page.
+  # E.g. let current page be 9, then pagination will look like this:
+  # First Prev ... 4 5 6 7 8 9 10 11 12 13 14 ... Next Last
+  # (Except 3-dots, they are useless for bots.)
+  PAGERWINDOW = 5
+
+  numberOfPages = Math.ceil(numberOfItems / ITEMSPERPAGE)
+  firstLink = prevLink = nextLink = lastLink = ""
+
+  if currentPage > 1
+    firstLink = getSinglePageLink 1, contentType, "First"
+    prevLink  = getSinglePageLink (currentPage - 1), contentType, "Previous"
+
+  if currentPage < numberOfPages
+    lastLink  = getSinglePageLink numberOfPages, contentType, "Last"
+    nextLink  = getSinglePageLink (currentPage + 1), contentType, "Next"
+
+  pagination = firstLink + prevLink
+
+  start = 1
+  end = numberOfPages
+
+  start = currentPage - PAGERWINDOW  if currentPage > PAGERWINDOW
+
+  if currentPage + PAGERWINDOW < numberOfPages
+    end   = currentPage + PAGERWINDOW
+
+  [start..end].map (pageNumber)=>
+    pagination += getSinglePageLink pageNumber, contentType
+
+  pagination += nextLink
+  pagination += lastLink
+
+  return pagination
+
+
+getSinglePageLink = (pageNumber, contentType, linkText=pageNumber)->
+  # link = "#{linkText}  "
+  link = "#{linkText}  "
+  return link
+
+appendDecoratedTopic = (tag, queue)=>
+  queue.pageContent += createTagNode tag
+  queue.next()
+
+getSchemaOpeningTags = (contentType)=>
+  openingTags = ""
+  if contentType is "Activity"
+    openingTags =
+      """
+

+

+            <meta itemprop="mainContentOfPage" content="true"/>
+
Latest activities

+            <meta itemprop="itemListOrder" content="Descending" />
+      """
+  else if contentType is "Topics"
+    openingTags =
+      """
+

+          <meta itemprop="mainContentOfPage" content="true"/>
+
Latest topics

+          <meta itemprop="itemListOrder" content="Descending" />
+      """
+  return openingTags
+
+getSchemaClosingTags = (contentType)=>
+  closingTags = ""
+  if contentType is "Activity"
+    closingTags = "

"
+  else if contentType is "Topics"
+    closingTags = "
"
+  return closingTags
+
+createTagNode = (tag)->
+  tagContent = ""
+  if tag.title
+    tagContent +=
+    """
+

+        #{tag.title}
+

+    """
+  if tag?.counts?.followers?
+    tagContent += createFollowersCount tag.counts.followers
+    tagContent += createUserInteractionMeta tag.counts.followers
+  return tagContent
+
+createFollowersCount = (numberOfFollowers)->
+  return "#{numberOfFollowers} followers"
+
+createUserInteractionMeta = (numberOfFollowers)->
+  userInteractionMeta = "<meta itemprop=\"interactionCount\" content=\"UserComments:#{numberOfFollowers}\"/>"
+  return userInteractionMeta
+
+putContentIntoFullPage = (content, pagination)->
+  getGraphMeta  = require './graphmeta'
+  fullPage =
+    """
+      <!DOCTYPE html>
+
+
+        <title>Koding</title>
+        #{getGraphMeta()}
+
+
+          Koding

+          #{content}
+          #{pagination}
+
+
+    """
+  return fullPage


Add keymap for atom

Add keymap for atom

--- atom.symlink/keymap.cson
+++ atom.symlink/keymap.cson
@@ -0,0 +1,28 @@
+# Your keymap
+#
+# Atom keymaps work similarly to style sheets. Just as style sheets use
+# selectors to apply styles to elements, Atom keymaps use selectors to associate
+# keystrokes with events in specific contexts.
+#
+# You can create a new keybinding in this file by typing "key" and then hitting
+# tab.
+#
+# Here's an example taken from Atom's built-in keymap:
+#
+# 'atom-text-editor':
+#   'enter': 'editor:newline'
+#
+# 'atom-workspace':
+#   'ctrl-shift-p': 'core:move-up'
+#   'ctrl-p': 'core:move-down'
+#
+# You can find more information about keymaps in these guides:
+# * https://atom.io/docs/latest/using-atom-basic-customization#customizing-key-bindings
+# * https://atom.io/docs/latest/behind-atom-keymaps-in-depth
+#
+# This file uses CoffeeScript Object Notation (CSON).
+# If you are unfamiliar with CSON, you can read more about it here:
+# https://github.com/bevry/cson#what-is-cson
+
+'atom-text-editor:not([mini])':
+  'shift-cmd-c': 'editor:toggle-line-comments'


fixes

fixes


Bug fix for feeds with <20 items.

Bug fix for feeds with <20 items.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/Snitzle/hummingbird.git/'


Form Builder specific client-side code, for now to position icons to edit control on the grid cells on mouseover

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/tanbo800/orbeon-forms.git/'


fix: zero retries

fix: zero retries

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/keboola/kbc-ui-ex-db.git/'


Scrubber auto-pauses when dragging from ended position.

--- app/views/play/level/LevelPlaybackView.coffee
+++ app/views/play/level/LevelPlaybackView.coffee
@@ -334,7 +334,7 @@
       start: (event, ui) =>
         return if @shouldIgnore()
         @slideCount = 0
-        @wasPlaying = @playing
+        @wasPlaying = @playing and not $('#play-button').hasClass('ended')
         Backbone.Mediator.publish 'level:set-playing', {playing: false}
         Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'playback-scrub-start', volume: 0.5


Temporary remove the update notice

Temporary remove the update notice

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/tamino-martinius/colourco.de.git/'


added config flag to deactivate cache if needed

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/saijim/Multipleter.git/'


when check result ok true,then print echostr

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/jzwzz/wechat-sample.git/'


Update configuration

Update configuration

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/ehmicky/myos.git/'


Update configuration

Update configuration


Make sure that the first line of a paragraph is never by itself at the bottom of a page

--- lib/mixins/text.coffee
+++ lib/mixins/text.coffee
@@ -221,8 +221,10 @@
                 # we're no longer on the first line...
                 wrap.firstLine = false

-                # if we've reached the maximum height provided
-                if @y > maxY
+                # if we've reached the maximum height and make sure
+                # that the first line of a paragraph is never by itself
+                # at the bottom of a page
+                if @y > maxY or (wrap.lastLine and @y + @currentLineHeight(true) > maxY)
                     return unless @y >= @page.maxY()

                     # if we've reached the edge of the page,


add a perf spec

add a perf spec

error: pathspec 'test/perf/perf-specs/v2e-vs-flatmap.coffee' did not match any file(s) known to git

--- test/perf/perf-specs/v2e-vs-flatmap.coffee
+++ test/perf/perf-specs/v2e-vs-flatmap.coffee
@@ -0,0 +1,13 @@
+Kefir = require('../../../dist/kefir.js')
+
+require('../perf-helper.coffee').setupTest 'A: s.valuesToErrors(), B: s.flatMap(Kefir.constantError)', {
+  kefirA: (stream) -> stream.valuesToErrors()
+  kefirB: (stream) -> stream.flatMap(Kefir.constantError)
+}
+
+
+require('../perf-helper.coffee').setupTest 'A: s.valuesToErrors(fn), B: s.flatMap(fn)', {
+  kefirA: (stream) -> stream.valuesToErrors((x) -> {convert: true, error: 1})
+  kefirB: (stream) -> stream.flatMap((x) -> Kefir.constantError(1))
+}
+


Add esper translations

Add esper translations

--- app/locale/es-419.coffee
+++ app/locale/es-419.coffee
@@ -2331,81 +2331,81 @@
     email_taken: "Email ya utilizado"
     username_taken: "El nombre de usuario ya existe"

-#  esper:
-#    line_no: "Line $1: "
-#    uncaught: "Uncaught $1" # $1 will be an error type, eg "Uncaught SyntaxError"
-#    reference_error: "ReferenceError: "
-#    argument_error: "ArgumentError: "
-#    type_error: "TypeError: "
-#    syntax_error: "SyntaxError: "
-#    error: "Error: "
-#    x_not_a_function: "$1 is not a function"
-#    x_not_defined: "$1 is not defined"
-#    spelling_issues: "Look out for spelling issues: did you mean `$1` instead of `$2`?"
-#    capitalization_issues: "Look out for capitalization: `$1` should be `$2`."
-#    py_empty_block: "Empty $1. Put 4 spaces in front of statements inside the $2 statement."
-#    fx_missing_paren: "If you want to call `$1` as a function, you need `()`'s"
-#    unmatched_token: "Unmatched `$1`.  Every opening `$2` needs a closing `$3` to match it."
-#    unterminated_string: "Unterminated string. Add a matching `\"` at the end of your string."
-#    missing_semicolon: "Missing semicolon."
-#    missing_quotes: "Missing quotes. Try `$1`"
+  esper:
+    line_no: "Linea $1: "
+    uncaught: "$1 no detectado" # $1 will be an error type, eg "Uncaught SyntaxError"
+    reference_error: "ReferenciaErronea: "
+    argument_error: "ArgumentoErroneo: "
+    type_error: "TipoErroneo: "
+    syntax_error: "SintaxisErronea: "
+    error: "Error: "
+    x_not_a_function: "$1 no es una función"
+    x_not_defined: "$1 no está definido"
+    spelling_issues: "Corrige la ortografía: ¿quisiste decir `$1` en lugar de `$2`?"
+    capitalization_issues: "Cuidado con las mayúsculas: `$1` debe ser `$2`."
+    py_empty_block: "$1 vacío. Adelanta 4 espacios las declaraciones dentro del bloque $2."
+    fx_missing_paren: "Si deseas llamar `$1` como función, pon paréntesis `()` al final"
+    unmatched_token: "`$1` no coincide. Cada apertura de `$2` necesita un cierre de `$3` para coincidir."
+    unterminated_string: "Cadena sin terminar. Agrega `\"` al final de la cadena."
+    missing_semicolon: "Falta punto y coma."
+    missing_quotes: "Faltan comillas. Intenta `$1`"
 #    argument_type: "`$1`'s argument `$2` should have type `$3`, but got `$4`: `$5`."
 #    argument_type2: "`$1`'s argument `$2` should have type `$3`, but got `$4`."
-#    target_a_unit: "Target a unit."
-#    attack_capitalization: "Attack $1, not $2. (Capital letters are important.)"
-#    empty_while: "Empty while statement. Put 4 spaces in front of statements inside the while statement."
+    target_a_unit: "Apuntar a una unidad."
+    attack_capitalization: "Ataca a $1, no a $2. (Mayúsculas son importantes.)"
+    empty_while: "Sentencia while vacía. Adelanta 4 espacios las declaraciones dentro del bloque while."
 #    line_of_site: "`$1`'s argument `$2` has a problem. Is there an enemy within your line-of-sight yet?"
-#    need_a_after_while: "Need a `$1` after `$2`."
-#    too_much_indentation: "Too much indentation at the beginning of this line."
-#    missing_hero: "Missing `$1` keyword; should be `$2`."
-#    takes_no_arguments: "`$1` takes no arguments."
-#    no_one_named: "There's no one named \"$1\" to target."
-#    separated_by_comma: "Function calls paramaters must be seperated by `,`s"
-#    protected_property: "Can't read protected property: $1"
-#    need_parens_to_call: "If you want to call `$1` as function, you need `()`'s"
-#    expected_an_identifier: "Expected an identifier and instead saw '$1'."
-#    unexpected_identifier: "Unexpected identifier"
-#    unexpected_end_of: "Unexpected end of input"
-#    unnecessary_semicolon: "Unnecessary semicolon."
-#    unexpected_token_expected: "Unexpected token: expected $1 but found $2 while parsing $3"
-#    unexpected_token: "Unexpected token $1"
-#    unexpected_token2: "Unexpected token"
-#    unexpected_number: "Unexpected number"
-#    unexpected: "Unexpected '$1'."
-#    escape_pressed_code: "Escape pressed; code aborted."
-#    target_an_enemy: "Target an enemy by name, like `$1`, not the string `$2`."
-#    target_an_enemy_2: "Target an enemy by name, like $1."
-#    cannot_read_property: "Cannot read property '$1' of undefined"
-#    attempted_to_assign: "Attempted to assign to readonly property."
-#    unexpected_early_end: "Unexpected early end of program."
-#    you_need_a_string: "You need a string to build; one of $1"
-#    unable_to_get_property: "Unable to get property '$1' of undefined or null reference" # TODO: Do we translate undefined/null?
-#    code_never_finished_its: "Code never finished. It's either really slow or has an infinite loop."
-#    unclosed_string: "Unclosed string."
-#    unmatched: "Unmatched '$1'."
-#    error_you_said_achoo: "You said: $1, but the password is: $2. (Capital letters are important.)"
-#    indentation_error_unindent_does: "Indentation Error: unindent does not match any outer indentation level"
-#    indentation_error: "Indentation error."
-#    need_a_on_the: "Need a `:` on the end of the line following `$1`."
-#    attempt_to_call_undefined: "attempt to call '$1' (a nil value)"
-#    unterminated: "Unterminated `$1`"
-#    target_an_enemy_variable: "Target an $1 variable, not the string $2. (Try using $3.)"
-#    error_use_the_variable: "Use the variable name like `$1` instead of a string like `$2`"
-#    indentation_unindent_does_not: "Indentation unindent does not match any outer indentation level"
-#    unclosed_paren_in_function_arguments: "Unclosed $1 in function arguments."
-#    unexpected_end_of_input: "Unexpected end of input"
-#    there_is_no_enemy: "There is no `$1`. Use `$2` first." # Hints start here
-#    try_herofindnearestenemy: "Try `$1`"
-#    there_is_no_function: "There is no function `$1`, but `$2` has a method `$3`."
+    need_a_after_while: "Necesitas un `$1` después de `$2`."
+    too_much_indentation: "Demasiada indentación al inicio de esta línea."
+    missing_hero: "Falta la palabra clave `$1`; debe ser `$2`."
+    takes_no_arguments: "`$1` no acepta argumentos."
+    no_one_named: "No se puede apuntar a \"$1\" porque nadie se llama así."
+    separated_by_comma: "Al llamar una función los parámetros deben estar separados con `,`"
+    protected_property: "No se puede leer propiedad protegida: $1"
+    need_parens_to_call: "Si deseas llamar `$1` como función, pon paréntesis `()` al final"
+    expected_an_identifier: "Se esperaba un identificador y en su lugar se recibió '$1'."
+    unexpected_identifier: "Identificador inesperado"
+    unexpected_end_of: "Fin de entrada inesperado"
+    unnecessary_semicolon: "Punto y coma innecesario."
+    unexpected_token_expected: "Símbolo inesperado: se esperaba $1 pero se encontró $2 mientras se analizaba $3"
+    unexpected_token: "Símbolo $1 inesperado"
+    unexpected_token2: "Símbolo inesperado"
+    unexpected_number: "Número inesperado"
+    unexpected: "No se esperaba '$1'."
+    escape_pressed_code: "Escape presionado; código anulado."
+    target_an_enemy: "Apunta a un enemigo por su nombre, como `$1`, no la cadena `$2`."
+    target_an_enemy_2: "Apunta a un enemigo por su nombre, como $1."
+    cannot_read_property: "No se puede leer la propiedad '$1' de indefinido"
+    attempted_to_assign: "Se intentó asignar una propiedad de solo lectura."
+    unexpected_early_end: "Fin del programa antes de lo esperado."
+    you_need_a_string: "Necesitas una cadena para construir; una de $1"
+    unable_to_get_property: "No se puede obtener la propiedad '$1' de una referencia nula o indefinida" # TODO: Do we translate undefined/null?
+    code_never_finished_its: "El código no finalizo. Es demasiado lento o tiene un bucle infinito."
+    unclosed_string: "Cadena sin cerrar."
+    unmatched: "No coincide '$1'."
+    error_you_said_achoo: "Dijiste: $1, pero la contraseña es: $2. (Mayúsculas y minúsculas son importantes.)"
+    indentation_error_unindent_does: "Error de Indentación: no coincide con ningun nivel de indentación"
+    indentation_error: "Error de Indentación."
+    need_a_on_the: "Necesitas un `:` al final de la linea seguido de `$1`."
+    attempt_to_call_undefined: "se intento llamar '$1' (un valor nulo)"
+    unterminated: "`$1` sin terminar"
+    target_an_enemy_variable: "Apunta a la variable $1, y no al string $2. (Intenta usar $3.)"
+    error_use_the_variable: "Usa el nombre de la variable como `$1` en lugar de la cadena como `$2`"
+    indentation_unindent_does_not: "Desindentación no coincide con ningún nivel de indentación"
+    unclosed_paren_in_function_arguments: "No se cerró $1 en los argumentos de la función."
+    unexpected_end_of_input: "Fin de entrada inesperado"
+    there_is_no_enemy: "No hay `$1`. Primero utiliza `$2`." # Hints start here
+    try_herofindnearestenemy: "Intenta `$1`"
+    there_is_no_function: "No hay ninguna función `$1`, pero `$2` tiene el método `$3`."
 #    attacks_argument_enemy_has: "`$1`'s argument `$2` has a problem."
-#    is_there_an_enemy: "Is there an enemy within your line-of-sight yet?"
-#    target_is_null_is: "Target is $1. Is there always a target to attack? (Use $2?)"
-#    hero_has_no_method: "`$1` has no method `$2`."
-#    there_is_a_problem: "There is a problem with your code."
-#    did_you_mean: "Did you mean $1? You do not have an item equipped with that skill."
-#    missing_a_quotation_mark: "Missing a quotation mark. "
-#    missing_var_use_var: "Missing `$1`. Use `$2` to make a new variable."
-#    you_do_not_have: "You do not have an item equipped with the $1 skill."
-#    put_each_command_on: "Put each command on a separate line"
-#    are_you_missing_a: "Are you missing a '$1' after '$2'? "
-#    your_parentheses_must_match: "Your parentheses must match."
+    is_there_an_enemy: "¿Aún hay algún enemigo en tu linea de visión?"
+    target_is_null_is: "El objetivo es $1. ¿Siempre hay un blanco para atacar? (Usa $2?)"
+    hero_has_no_method: "`$1` no tiene el método `$2`."
+    there_is_a_problem: "Hay un problema con tu código."
+    did_you_mean: "¿Quisiste decir $1? No tienes equipado un item con esa habilidad."
+    missing_a_quotation_mark: "Falta una commilla. "
+    missing_var_use_var: "Falta `$1`. Utiliza `$2` para hacer una nueva variable."
+    you_do_not_have: "No tienes equipado un item con la habilidad $1."
+    put_each_command_on: "Pon cada comando en lineas separadas"
+    are_you_missing_a: "¿Te falta un '$1' despues de '$2'? "
+    your_parentheses_must_match: "Los paréntesis deben coincidir."


Add config for Atom

Add config for Atom

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/fooforge/dotfiles.git/'


Viewport object

Viewport object

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/zagushka/ui-scroll.git/'