Add the 2nd week of training

Add the 2nd week of training

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

--- scripts/training2nd.coffee
+++ scripts/training2nd.coffee
@@ -0,0 +1,34 @@
+# Description:
+#   The 2nd day of Training - 研修2日目
+#
+# Commands:
+#   customer ご用件を伺いに来ました。
+#   customer Wordpressを立てたことを報告しに来ました。
+#   customer MovableTypeに変更したことを報告しに来ました。
+#   customer Wordpressに戻したことを報告しに来ました。
+#   customer 障害とその原因について報告しに来ました。{障害内容と原因}
+#   customer 復旧したことを報告しに来ました。
+
+module.exports = (robot) ->
+  robot.respond /ご用件を伺いに来ました。/i, (res) ->
+    res.reply "実は最近会社でもブログを使っている所が増えていると聞いてね。そこで当社もブログを使って、当社の良さを宣伝したいと思っているんだ。なので、早速なんだけど、Wordpressがいいらしいので、それをひとつ用意してくれるかね。"
+    res.send "「@boss お客様からWordpressを立ててほしいと頼まれました。」の形式です。"
+
+  robot.respond /Wordpressを立てたことを報告しに来ました。/i, (res) ->
+    res.reply "ありがたいのですが、昨日Wordpressでブログを書いてほしいと社員に伝えたら、MovableTypeの方がいいと言い出す社員がいましてね。そちらのが慣れているから楽だという話なんですよ。私としては書いてもらえば、どちらでもいいのでMovableTypeにしてもらえますか。"
+    res.send "「@boss お客様からMovableTypeに変更してほしいと頼まれました。」の形式です。"
+
+  robot.respond /MovableTypeに変更したことを報告しに来ました。/i, (res) ->
+    res.reply "いやー、変えてもらったところを申し訳ないんだけどね。やはりWordpressのがよさそうで、Wordpressにしてほしいんだよ。MovableTypeがいいと言っていた社員もブログを書くだけでサーバを運用    するわけじゃないから、口出さないように言っておいたよ。それでは、よろしく。"
+    res.send "「@boss お客様からWordpressに戻して100万PVに耐えられるようにしてほしいと頼まれました。」の形式です。"
+
+  robot.respond /Wordpressに戻したことを報告しに来ました。/i, (res) ->
+    res.reply "じゃあ、早速使ってみますよ。それと、せっかく書いたのに消えてしまってはいやだか、バックアップをとれるようにしておいてください。"
+    res.send "「@boss お客様からバックアップを取るように頼まれました。」の形式です。"
+
+  robot.respond /障害とその原因について報告しに来ました。.*/i, (res) ->
+    res.reply "そういうことですか。バックアップを取ってあるので、すぐ戻せますよね。すぐに取りかかってください。戻ったら、私に「復旧したことを報告しに来ました。」と言いに来てください。"
+
+  robot.respond /復旧したことを報告しに来ました。.*/i, (res) ->
+    res.reply "ご苦労様です。復旧したことですし、とりあえずよしとしましょう。ただ、こちらが気づく前に、そちらで気づかないようでは困りますね。あらかじめそちらで気づくような仕組みを作っておいてください。"
+    res.send "「@boss お客様から壊れたことを気づく仕組みを作ってほしいと頼まれました。」の形式です。"


Add user login button

Add user login button

error: pathspec 'src/user/login-button.cjsx' did not match any file(s) known to git

--- src/user/login-button.cjsx
+++ src/user/login-button.cjsx
@@ -0,0 +1,22 @@
+React = require 'react'
+
+User  = require './model'
+
+UserLoginButton = React.createClass
+
+  PropTypes:
+    onAttemptLogin: React.PropTypes.func.isRequired
+
+  componentDidMount: ->
+    User.channel.on("change", @onUserChange)
+  componentWillUnmount: ->
+    User.channel.off("change", @onUserChange)
+
+  onUserChange: ->
+    @forceUpdate()
+
+  render: ->
+    return null if User.isLoggedIn()
+    <button onClick={@props.onAttemptLogin}>Login Now</button>
+
+module.exports = UserLoginButton


add id as a directive attribute returned on cropme:done to identify element

--- scripts/directives/cropme.coffee
+++ scripts/directives/cropme.coffee
@@ -59,7 +59,7 @@
 	"""
 	restrict: "E"
 	priority: 99 # it needs to run after the attributes are interpolated
-	scope:
+	scope:
 		width: "=?"
 		destinationWidth: "="
 		height: "=?"
@@ -70,6 +70,7 @@
 		src: "@?"
 		sendOriginal: "@?"
 		sendCropped: "@?"
+		id: "@?"
 	link: (scope, element, attributes) ->
 		scope.dropText = "Drop picture here"
 		scope.state = "step-1"
@@ -127,7 +128,7 @@
 				return scope.dropError = "Wrong file type, please select an image."
 			scope.dropError = ""
 			reader = new FileReader
-			reader.onload = (e) ->
+			reader.onload = (e) ->
 				scope.$apply -> loadImage e.target.result
 			reader.readAsDataURL(file);
 		loadImage = (src) ->
@@ -157,12 +158,12 @@
 			if src isnt scope.imgSrc
 				scope.imgSrc = src
 				scope.imgLoaded = false
-
+
 		moveCropZone = (coords) ->
 			scope.xCropZone = coords.x - elOffset.left - scope.widthCropZone / 2
 			scope.yCropZone = coords.y - elOffset.top - scope.heightCropZone / 2
 			checkBounds()
-		moveBorders =
+		moveBorders =
 			top: (coords) ->
 				y = coords.y - elOffset.top
 				scope.heightCropZone += scope.yCropZone - y
@@ -291,10 +292,10 @@
 					width: scope.croppedWidth
 				result.croppedImage = blobArray[0]  if blobArray[0]
 				result.originalImage = blobArray[1]  if blobArray[1]
-				$rootScope.$broadcast "cropme:done", result, "image/#{scope.type}"
+				$rootScope.$broadcast "cropme:done", result, "image/#{scope.type}", scope.id

 		scope.$on "cropme:cancel", scope.cancel
 		scope.$on "cropme:ok", scope.ok
 		scope.$watch "src",  -> loadImage scope.src
-
+
 		loadImage scope.src


server: only return always on vms for /payments/customers

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/'


Temporary server fix before @aenario's work land

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/clochix/cozy-emails.git/'


chore (Test) Make clear the takePicture test is supposed to fail on simulator

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/supersonic.git/'


Optionnal callback

Optionnal callback

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/metidia/dynoga.git/'


Added Google Safebrowsing API - usage: hubot gsafe <url>

error: pathspec 'src/scripts/google-safebrowsing.coffee' did not match any file(s) known to git

--- src/scripts/google-safebrowsing.coffee
+++ src/scripts/google-safebrowsing.coffee
@@ -0,0 +1,40 @@
+# Description:
+#   Get Website Report from Google Safebrowsing (https://developers.google.com/safe-browsing)
+#
+# Dependencies:
+#   None
+#
+# Configuration:
+#   GOOGLE_SAFEBROWSING_API_KEY - Sign up at https://developers.google.com/safe-browsing/key_signup
+#
+# Commands:
+#   hubot gsafe <url> - Gets Google Safebrowsing Report for URL
+#
+# Author:
+#   A. Gianotto - @snipe
+
+GOOGLE_SAFEBROWSING_API_KEY = process.env.GOOGLE_SAFEBROWSING_API_KEY
+
+module.exports = (robot) ->
+  robot.respond /gsafe (.*)/i, (msg) ->
+
+    if GOOGLE_SAFEBROWSING_API_KEY?
+
+      gsafe_term = msg.match[1].toLowerCase()
+
+      api_url = "https://sb-ssl.google.com"
+      request_url = api_url
+      request_url += "/safebrowsing/api/lookup"
+      request_url += "?client=api&apikey=#{GOOGLE_SAFEBROWSING_API_KEY}&appver=1.5&pver=3.1&"
+      request_url += "url=#{encodeURIComponent gsafe_term}"
+
+      robot.http(request_url)
+        .get() (err, res, body) ->
+
+          if res.statusCode is 200
+            msg.send "[SUSPICIOUS] The URL #{gsafe_term} is listed as #{body} in Google Safebrowsing. More info: at http://www.google.com/safebrowsing/diagnostic?site=#{encodeURIComponent gsafe_term}"
+          else
+             msg.send "[CLEAN] The URL is NOT curently listed as suspicious in Google Safebrowsing. More info: at http://www.google.com/safebrowsing/diagnostic?site=#{encodeURIComponent gsafe_term}"
+
+    else
+    	msg.send "Error: Google SafeBrowsing API key not configured. Get one at https://developers.google.com/safe-browsing/key_signup"


fix task dependencies

fix task dependencies

--- gulp/dist.coffee
+++ gulp/dist.coffee
@@ -30,7 +30,7 @@
     .pipe($.size())
     .pipe(gulp.dest("dist"))

-gulp.task "dist-images", ->
+gulp.task "dist-images", ["clean"], ->
   gulp.src("app/images/**/*")
     .pipe($.plumber(errorHandler: $.notify.onError("<%= error.stack %>")))
     .pipe($.cache($.imagemin(
@@ -41,7 +41,7 @@
     .pipe($.size())
     .pipe(gulp.dest("dist/images"))

-gulp.task "dist-fonts", ->
+gulp.task "dist-fonts", ["clean"], ->
   gulp.src(mainBowerFiles())
     .pipe($.plumber(errorHandler: $.notify.onError("<%= error.stack %>")))
     .pipe($.filter("**/*.{eot,svg,ttf,woff}"))


test (View) Transition stream without hooks completes immediately

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/ag-module-router.git/'


add index tests for range comprehensions

--- test/comprehensions.coffee
+++ test/comprehensions.coffee
@@ -24,13 +24,13 @@

   test 'filtered comprehensions', ->
     list = [0..5]
-    filtered = (a for a in list when a & 1)
-    arrayEq filtered, [1, 3, 5]
-    filtered = (a for a in list when a < 4)
-    arrayEq filtered, [0..3]
+    arrayEq [1, 3, 5], (a for a in list when a & 1)
+    arrayEq [0..3], (a for a in list when a < 4)

   test '#285: filtered comprehensions over ranges', ->
-    filtered = (a for a in [0..5] when a & 1)
-    arrayEq filtered, [1, 3, 5]
-    filtered = (a for a in [0..5] when a < 4)
-    arrayEq filtered, [0..3]
+    arrayEq [1, 3, 5], (a for a in [0..5] when a & 1)
+    arrayEq [0..3], (a for a in [0..5] when a < 4)
+
+  test 'comprehension over range with index', ->
+    arrayEq [0..3], (k for v, k in [5..8])
+    arrayEq [5..8], (v for v, k in [5..8])


improved user spec

improved user spec

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/namineundorf/athene.git/'


let searching with space

let searching with space

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/VoiSmart/Rocket.Chat.git/'


add group toggle

add group toggle

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/'


Modules now load on package activation

Modules now load on package activation

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/aki77/atomatigit.git/'


Escape htmlentities for text format.

Escape htmlentities for text format.

--- core/htdocs_source/src/pods/oxivalue-format/component.coffee
+++ core/htdocs_source/src/pods/oxivalue-format/component.coffee
@@ -34,7 +34,7 @@
           else
             "---"
         datetime: (v) -> moment().utc(v).format("YYYY-MM-DD HH:mm:ss UTC")
-        text: (v) -> v
+        text: (v) -> Em.$('
').text(v).html()
         code: (v) -> "#{v.replace(/(\r\n|\n|\r)/gm,"
")}"
         raw: (v) -> v
         defhash: (v) -> "
#{(for k, w of v then "
#{k}

#{w}
").join ""}
"


:memo: Update documentation and labels

:memo: Update documentation and labels


make screen static shorter

make screen static shorter

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/robey/carrot16.git/'


event listener page check

event listener page check

--- resources/assets/coffee/landing-page/landing-graph.coffee
+++ resources/assets/coffee/landing-page/landing-graph.coffee
@@ -16,127 +16,134 @@
 # along with osu!web.  If not, see <http://www.gnu.org/licenses/>.
 ###

-# Define margins
-margin =
-  top: 40
-  right: 0
-  bottom: 0
-  left: 0
-width = parseInt(d3.select('.js-landing-graph').style('width')) - (margin.left) - (margin.right)
-height = parseInt(d3.select('.js-landing-graph').style('height')) - (margin.top) - (margin.bottom)
-# Define peak circle
-peakR = 5
-# Define date parser
-parseDate = d3.time.format('%Y-%m-%d %H:%M:%S').parse
-xScale = d3.time.scale().range([
-  0
-  width
-])
-yScale = d3.scale.linear().range([
-  height
-  0
-])
-# Peak text indicator point
-maxElem = null
-# Define area
-area = d3.svg.area().interpolate('basis')
-  .x (d) ->
-    xScale d.date
-  .y0(height).y1 (d) ->
-    yScale d.users_osu
-# Define the graph
-svg = null
-textLength = 0
+landingGraphWrapper = document.getElementsByClassName('js-landing-graph')
+landingGraphInit = document.getElementsByClassName('js-landing-graph-initialized')

-modelStats = (data) ->
-  # Define svg canvas
-  svg = d3.select '.js-landing-graph'
-    .append 'svg'
-    .attr 'width', width + margin.left + margin.right
-    .attr 'height', height + margin.top + margin.bottom
-    .append 'g'
-    .attr 'transform', 'translate(' + margin.left + ',' + margin.top + ')'
+if landingGraphWrapper[0]?
+  if !landingGraphInit[0]?
+    # Define margins
+    margin =
+      top: 40
+      right: 0
+      bottom: 0
+      left: 0
+    width = parseInt(d3.select('.js-landing-graph').style('width')) - (margin.left) - (margin.right)
+    height = parseInt(d3.select('.js-landing-graph').style('height')) - (margin.top) - (margin.bottom)
+    # Define peak circle
+    peakR = 5
+    # Define date parser
+    parseDate = d3.time.format('%Y-%m-%d %H:%M:%S').parse
+    xScale = d3.time.scale().range([
+      0
+      width
+    ])
+    yScale = d3.scale.linear().range([
+      height
+      0
+    ])
+    # Peak text indicator point
+    maxElem = null
+    # Define area
+    area = d3.svg.area().interpolate('basis')
+      .x (d) ->
+        xScale d.date
+      .y0(height).y1 (d) ->
+        yScale d.users_osu
+    # Define the graph
+    svg = null
+    textLength = 0

-  # Parsing data
-  data.forEach (d) ->
-    d.date = parseDate(d.date)
-    d.users_osu = +d.users_osu
+    modelStats = (data) ->
+      # Define svg canvas
+      svg = d3.select '.js-landing-graph'
+        .append 'svg'
+        .attr 'width', width + margin.left + margin.right
+        .attr 'height', height + margin.top + margin.bottom
+        .attr 'class', 'js-landing-graph-initialized'
+        .append 'g'
+        .attr 'transform', 'translate(' + margin.left + ',' + margin.top + ')'

-  # Establishing domain for x/y axes
-  xScale.domain d3.extent(data, (d) ->
-    d.date
-  )
-  yScale.domain [
-    0
-    d3.max(data, (d) ->
-      d.users_osu
-    )
-  ]
-  # Remove any existing paths
-  svg.selectAll 'path'
-    .remove
+      # Parsing data
+      data.forEach (d) ->
+        d.date = parseDate(d.date)
+        d.users_osu = +d.users_osu

-  # Appending groups
-  svg.append 'path'
-    .datum data
-    .attr 'class', 'landing-graph__area'
-    .attr 'd', area
+      # Establishing domain for x/y axes
+      xScale.domain d3.extent(data, (d) ->
+        d.date
+      )
+      yScale.domain [
+        0
+        d3.max(data, (d) ->
+          d.users_osu
+        )
+      ]
+      # Remove any existing paths
+      svg.selectAll 'path'
+        .remove

-  #Find the date for the max, from the end backward
-  i = data.length - 1
-  while i >= 0
-    if maxElem == null or data[i].users_osu > maxElem.users_osu
-      maxElem = data[i]
-    i--
+      # Appending groups
+      svg.append 'path'
+        .datum data
+        .attr 'class', 'landing-graph__area'
+        .attr 'd', area

-  text = svg.append 'text'
-    .attr 'class', 'landing-graph__text'
-    .text Lang.get('home.landing.peak', 'count': maxElem.users_osu.toLocaleString())
-    .attr 'y', -peakR * 2
+      #Find the date for the max, from the end backward
+      i = data.length - 1
+      while i >= 0
+        if maxElem == null or data[i].users_osu > maxElem.users_osu
+          maxElem = data[i]
+        i--

-  # Get the width of the element to determine angle offset
-  rightX = xScale(maxElem.date) + peakR * 2
-  textLength = text.node().getComputedTextLength()
-  if (textLength + rightX) > width
-    text.attr 'x', xScale(maxElem.date) - textLength - peakR * 2
-  else
-    text.attr 'x', rightX
+      text = svg.append 'text'
+        .attr 'class', 'landing-graph__text'
+        .text Lang.get('home.landing.peak', 'count': maxElem.users_osu.toLocaleString())
+        .attr 'y', -peakR * 2

-  peak = svg.append 'circle'
-    .attr 'class', 'landing-graph__circle'
-    .attr 'cy', 0
-    .attr 'cx', xScale(maxElem.date)
-    .attr 'r', peakR
+      # Get the width of the element to determine angle offset
+      rightX = xScale(maxElem.date) + peakR * 2
+      textLength = text.node().getComputedTextLength()
+      if (textLength + rightX) > width
+        text.attr 'x', xScale(maxElem.date) - textLength - peakR * 2
+      else
+        text.attr 'x', rightX

-resize = ->
-  width = parseInt(d3.select('.js-landing-graph').style('width')) - (margin.left) - (margin.right)
-  height = parseInt(d3.select('.js-landing-graph').style('height')) - (margin.top) - (margin.bottom)
-  d3.select '.js-landing-graph svg'
-    .attr 'width', width + margin.left + margin.right
-    .attr 'height', height + margin.top + margin.bottom
-  # Update the range of the scale with new width/height
-  xScale.range [
-    0
-    width
-  ]
-  yScale.range [
-    height
-    0
-  ]
-  # Force D3 to recalculate and update the line
-  svg.selectAll('path').attr 'd', area
+      peak = svg.append 'circle'
+        .attr 'class', 'landing-graph__circle'
+        .attr 'cy', 0
+        .attr 'cx', xScale(maxElem.date)
+        .attr 'r', peakR

-  rightX = xScale(maxElem.date) + peakR * 2
-  if (textLength + rightX) > width
-    svg.select('.landing-graph__text').attr 'x', xScale(maxElem.date) - textLength - peakR * 2
-  else
-    svg.select('.landing-graph__text').attr 'x', rightX
-
-  svg.select('.landing-graph__circle').attr 'cx', xScale(maxElem.date)
+    # Load the data
+    stats = osu.parseJson('json-stats')
+    modelStats stats

-# Load the data
-stats = osu.parseJson('json-stats')
-#Prevent redrawing on page back/foward
-if stats.length != 0 and d3.select('.js-landing-graph svg').empty()
-  modelStats stats
-d3.select(window).on 'resize', resize
+  landingResize = ->
+    width = parseInt(d3.select('.js-landing-graph').style('width')) - (margin.left) - (margin.right)
+    height = parseInt(d3.select('.js-landing-graph').style('height')) - (margin.top) - (margin.bottom)
+    d3.select '.js-landing-graph svg'
+      .attr 'width', width + margin.left + margin.right
+      .attr 'height', height + margin.top + margin.bottom
+    # Update the range of the scale with new width/height
+    xScale.range [
+      0
+      width
+    ]
+    yScale.range [
+      height
+      0
+    ]
+    # Force D3 to recalculate and update the line
+    svg.selectAll('path').attr 'd', area
+
+    rightX = xScale(maxElem.date) + peakR * 2
+    if (textLength + rightX) > width
+      svg.select('.landing-graph__text').attr 'x', xScale(maxElem.date) - textLength - peakR * 2
+    else
+      svg.select('.landing-graph__text').attr 'x', rightX
+
+    svg.select('.landing-graph__circle').attr 'cx', xScale(maxElem.date)
+
+$(window).on 'resize', ->
+  if landingGraphWrapper[0]?
+    landingResize()


fixed chunk regexp

fixed chunk regexp


metaprogram a source file

metaprogram a source file

error: pathspec 'inject.coffee.gen.coffee' did not match any file(s) known to git

--- inject.coffee.gen.coffee
+++ inject.coffee.gen.coffee
@@ -0,0 +1,47 @@
+code =
+  ''''
+  ((window, document)->
+    baseURL = document.getElementById("coffeeconsoleinject").src.replace("/inject.js", "")
+    window.COFFEECONSOLE =
+      contentWindow: window
+      contentDocument: document
+      baseURL: baseURL
+
+    if iframe = document.getElementById("coffeeconsole")
+      window.COFFEECONSOLE.console = iframe
+      document.getElementById("coffeeconsole").style.display = "block"
+    else
+      iframe = document.createElement("iframe")
+      window.COFFEECONSOLE.console = iframe
+      document.body.appendChild iframe
+      iframe.id = "coffeeconsole"
+      iframe.style.display = "block"
+      iframe.style.background = "#fff"
+      iframe.style.zIndex = "9999"
+      iframe.style.position = "absolute"
+      iframe.style.top = "0px"
+      iframe.style.left = "0px"
+      iframe.style.width = "100%"
+      iframe.style.height = "100%"
+      iframe.style.border = "0"
+      doc = iframe.contentDocument or iframe.contentWindow.document
+      doc.open()
+      doc.write DOCUMENT
+      doc.close()
+      iframe.contentWindow.onload = ->
+        @document.getElementById("exec").focus()
+        return
+    return
+  ) this, document
+#
+d =
+  ''''
+  "<!DOCTYPE html><meta charset=utf-8><title>Coffeeconsole!</title><meta id=meta name=viewport content=\"width=device-width,user-scalable=no,initial-scale=1\"><link rel=icon href=favicon.png type=image/png><link rel=apple-touch-icon href=favicon.png><meta name=apple-mobile-web-app-capable content=yes><meta name=apple-mobile-web-app-status-bar-style content=black><link rel=stylesheet href=\"#{baseURL}/console.css\">
<form><textarea autofocus id=exec spellcheck autocapitalize=off rows=1 autocorrect=off></textarea></form>

Fork Coffeeconsole on Github

"
+#
+fs = require 'fs'
+
+# fs.existsSync "" then
+
+# document
+
+console.log code.replace "DOCUMENT", d


add test for partner vat display

add test for partner vat display

Co-authored-by: Chung-yi Chi <7f8a8f7c67d84f433f98e349cd86f99a330c83d1@gmail.com>

error: pathspec 'src/desktop/apps/partner2/test/client/contact.test.coffee' did not match any file(s) known to git

--- src/desktop/apps/partner2/test/client/contact.test.coffee
+++ src/desktop/apps/partner2/test/client/contact.test.coffee
@@ -0,0 +1,40 @@
+_ = require 'underscore'
+Backbone = require 'backbone'
+sinon = require 'sinon'
+Partner = require '../../../../models/partner.coffee'
+Profile = require '../../../../models/profile.coffee'
+Contact = require '../../client/contact.coffee'
+benv = require 'benv'
+{ resolve } = require 'path'
+{ fabricate } = require 'antigravity'
+fixtures = require '../../../../test/helpers/fixtures.coffee'
+
+describe 'Contact page', ->
+
+  beforeEach (done) ->
+    benv.setup =>
+      benv.expose
+        $: benv.require 'jquery'
+      Backbone.$ = $
+      sinon.stub Backbone, 'sync'
+      benv.render resolve(__dirname, '../../templates/index.jade'), {
+        profile: new Profile fabricate 'partner_profile'
+        sd: { PROFILE: fabricate 'partner_profile' }
+        asset: (->)
+        params: {}
+      }, ->
+        done()
+
+  afterEach ->
+    Backbone.sync.restore()
+    benv.teardown()
+
+  describe '#renderAdditionalInfo', ->
+
+    it 'renders additional info', ->
+      view = new Contact
+        profile: new Profile fabricate 'partner_profile'
+        partner: new Partner fabricate 'partner', vat_number: "ABC123"
+        el: $('body')
+      view.renderAdditionalInfo()
+      $(view.el).html().should.containEql '
VAT ID #: ABC123
'


Import comment tests

Import comment tests

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

--- test/comment.coffee
+++ test/comment.coffee
@@ -0,0 +1,69 @@
+
+should = require 'should'
+parse = if process.env.CSV_COV then require '../lib-cov' else require '../src'
+
+describe 'comment', ->
+
+  it 'skip line starting by # by default', (next) ->
+    parse """
+    # skip this
+    "ABC","45"
+    "DEF","23"
+    # and this
+    "GHI","94"
+    # as well as that
+    """, comment: '#', (err, data) ->
+      data.should.eql [
+        [ 'ABC','45' ]
+        [ 'DEF','23' ]
+        [ 'GHI','94' ]
+      ]
+      next()
+
+  it 'doent apply inside quotes', (next) ->
+    parse """
+      "ABC","45"
+      "D#noEF","23"#yes
+      "GHI","94"
+      """, comment: '#', (err, data) ->
+      data.should.eql [
+        [ 'ABC','45' ]
+        [ 'D#noEF','23' ]
+        [ 'GHI','94' ]
+      ]
+      next()
+
+  it 'is cancel if empty', (next) ->
+    parse """
+    abc,#,def
+    1,2,3
+    """, comment: '', (err, data) ->
+      data.should.eql [
+        [ 'abc','#','def' ]
+        [ '1','2', '3' ]
+      ]
+      next()
+
+  it 'is cancel by default', (next) ->
+    parse """
+    abc,#,def
+    1,2,3
+    """, (err, data) ->
+      data.should.eql [
+        [ 'abc','#','def' ]
+        [ '1','2', '3' ]
+      ]
+      next()
+    # csv()
+    # .from.string( """
+    #   abc,#,def
+    #   1,2,3
+    #   """ )
+    # .to.string (result) ->
+    #   result.should.eql """
+    #   abc,#,def
+    #   1,2,3
+    #   """
+    #   next()
+
+


tests for `baseFileName` helper for files with only coffee-script extensions as the file name.

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/maowug/coffeescript.git/'


Test Rackspace Deployment

Test Rackspace Deployment

--- test.coffee
+++ test.coffee
@@ -1 +0,0 @@
-console.log test


(- fix) Tweak the reactor scheduling mechanism

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/JeffreyCA/illacceptanything.git/'


add mustache

add mustache

error: pathspec 'data/points/mustache.coffee' did not match any file(s) known to git

--- data/points/mustache.coffee
+++ data/points/mustache.coffee
@@ -0,0 +1,7 @@
+id: "mustache"
+title: "Mustache"
+function: [ "template" ]
+relevance: [ "handbars", "hogan-js" ]
+desc: "Logic-less风格的模板引擎，前后端均可使用，支持众多语言。"
+reference:
+  "Mustache Manual": "http://mustache.github.io/mustache.5.html"


Attach, show and hide pane item views with native DOM APIs

We continue to invoke SpacePen attach hooks on any shim wrappers
for backward compatibility, but SpacePen wrappers are no longer required
for attoch/hide/show as they were previously. Next: removal.

--- src/pane-element.coffee
+++ src/pane-element.coffee
@@ -1,5 +1,5 @@
 {CompositeDisposable} = require 'event-kit'
-{$} = require './space-pen-extensions'
+{$, callAttachHooks, callRemoveHooks} = require './space-pen-extensions'
 PaneView = require './pane-view'

 class PaneElement extends HTMLElement
@@ -8,6 +8,8 @@
   createdCallback: ->
     @attached = false
     @subscriptions = new CompositeDisposable
+    @inlineDisplayStyles = new WeakMap
+
     @initializeContent()
     @subscribeToDOMEvents()
     @createSpacePenShim()
@@ -81,12 +83,32 @@
   activeItemChanged: (item) ->
     return unless item?

-    $itemViews = $(@itemViews)
-    view = @model.getView(item).__spacePenView
-    otherView.hide() for otherView in $itemViews.children().not(view).views()
-    $itemViews.append(view) unless view.parent().is($itemViews)
-    view.show() if @attached
-    view.focus() if @hasFocus()
+    hasFocus = @hasFocus()
+    itemView = @model.getView(item)
+
+    for child in @itemViews.children
+      if child is itemView
+        @showItemView(child) if @attached
+      else
+        @hideItemView(child)
+
+    unless @itemViews.contains(itemView)
+      @itemViews.appendChild(itemView)
+      callAttachHooks(itemView)
+
+    itemView.focus() if hasFocus
+
+  showItemView: (itemView) ->
+    inlineDisplayStyle = @inlineDisplayStyles.get(itemView)
+    if inlineDisplayStyle?
+      itemView.style.display = inlineDisplayStyle
+    else
+      itemView.style.display = ''
+
+  hideItemView: (itemView) ->
+    inlineDisplayStyle = itemView.style.display
+    @inlineDisplayStyles.set(itemView, inlineDisplayStyle) if inlineDisplayStyle?
+    itemView.style.display = 'none'

   itemRemoved: ({item, index, destroyed}) ->
     if item instanceof $


don't focus on poplist text input if mobile device

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/artsyca/emberui.git/'


use on/off for binding events

use on/off for binding events


add http post say listener

add http post say listener

error: pathspec 'src/scripts/http-post-say.coffee' did not match any file(s) known to git

--- src/scripts/http-post-say.coffee
+++ src/scripts/http-post-say.coffee
@@ -0,0 +1,40 @@
+# Description:
+#   "Accepts POST data and broadcasts it"
+#
+# Dependencies:
+#   None
+#
+# Configuration:
+#   None
+#
+# Commands:
+#   None
+#
+# URLs:
+#   POST /hubot/say
+#     message = <message>
+#     room = <room>
+#
+#   curl -X POST http://localhost:8080/hubot/say -d message=lala -d room='#dev'
+#
+# Author:
+#   insom
+#   luxflux
+
+module.exports = (robot) ->
+  robot.router.post "/hubot/say", (req, res) ->
+
+    room = req.body.room
+    message = req.body.message
+
+    robot.logger.info "Message '#{message}' received for room #{room}"
+
+    user = robot.adapter.userForId 'broadcast'
+    user.room = room
+    user.type = 'groupchat'
+
+    if message
+      robot.send user, "#{message}"
+
+    res.writeHead 200, {'Content-Type': 'text/plain'}
+    res.end 'Thanks\n'


Add keymap.cson

Add keymap.cson

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

--- dotfiles/.atom/keymap.cson
+++ dotfiles/.atom/keymap.cson
@@ -0,0 +1,7 @@
+'atom-text-editor.vim-mode-plus.normal-mode':
+  ':': 'vim-mode-plus-ex-mode:open'
+  '!': 'vim-mode-plus-ex-mode:toggle-setting'
+
+'body atom-text-editor.vim-mode-plus.autocomplete-active':
+  'tab': 'core:move-down'
+  'shift-tab': 'core:move-up'


Set view_base to 'list' in syndication timbit

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/Postmedia/timbits-example.git/'


Fix bug related with searching

Fix bug related with searching

When the searched series does not belong to the current active tab, it
was supposed to show the #all tab but it didn't work. This commit fixes
the bug.

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/clee704/NaverWebtoonFeeds.git/'


clio-21582 CR comments addressed

clio-21582 CR comments addressed

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/seanhealy/lib-themisui.git/'


Fix lint error.

Fix lint error.

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/RobotSnacks/stout-server.git/'


Fix slug creation for languages other than English

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/patricklindsay/integral.git/'


remake examples

remake examples

error: pathspec 'scan.coffee' did not match any file(s) known to git


Update Atom version

Update Atom version

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/fuzza/dotfiles.git/'


Specify a base for parseInt

Specify a base for parseInt

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/people.git/'


Added f-ing-weather script

Added f-ing-weather script

error: pathspec 'src/scripts/f-ing-weather.coffee' did not match any file(s) known to git

--- src/scripts/f-ing-weather.coffee
+++ src/scripts/f-ing-weather.coffee
@@ -0,0 +1,32 @@
+# Description:
+#   Returns the weather from thefuckingweather.com
+#
+# Dependencies:
+#   None
+#
+# Configuration:
+#   None
+#
+# Commands:
+#   hubot what's the weather for <city> - Get the weather for a location
+#   hubot what's the weather for <zip> - Get the weather for a zipcode
+#
+# Author:
+#   aaronott
+
+weather = (msg, query, cb) ->
+  msg.http('http://thefuckingweather.com/')
+    .query(where: query)
+    .header('User-Agent', 'Mozilla/5.0')
+    .get() (err, res, body) ->
+      temp = body.match(/(\d+)/)?[1] || ""
+      remark = body.match(/
(.*)</)?[1] || "remark not found"
+      flavor = body.match(/
(.*)</)?[1] || "flavor not found"
+      cb(temp, remark, flavor)
+
+module.exports = (robot) ->
+  robot.respond /(what's|what is) the weather for (.*)/i, (msg) ->
+    city = msg.match[2] || "Ithaca, NY"
+    weather msg, city, (temp, remark, flavor) ->
+      out = temp + " degrees " + remark + " " + flavor
+      msg.send out


revert lazy loading

revert lazy loading

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/tscholz/knipser.git/'


hubot: distance <src> <dest>

hubot: distance <src> <dest>

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/sr/operator.git/'


home/utilities/apiaccess: readibility improvement

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/'


ModalItem: Generic item for both workspaces and machines


Added more male knight names for #53

Added more male knight names for #53

--- app/lib/world/names.coffee
+++ app/lib/world/names.coffee
@@ -841,6 +841,7 @@
     'Altair'
     'Arthur'
     'Bertrand'
+    'Bronn'
     'Bruce'
     'Drake'
     'Duran'
@@ -849,6 +850,7 @@
     'Hank'
     'Hunfray'
     'Jeph'
+    'Jorah'
     'Lancelot'
     'Mace'
     'Neville'


added famous computer scientist names for #53

--- app/lib/world/names.coffee
+++ app/lib/world/names.coffee
@@ -287,6 +287,7 @@
     'Durfkor'
     'Fendrel'
     'Gawain'
+    'Hamming'
     'Hector'
     'Hershell'
     'Hingle'
@@ -300,6 +301,7 @@
     'Thad'
     'Tybalt'
     'Victor'
+    'Winkler'
     'Yorik'
     'Yusef'
   ]
@@ -340,6 +342,7 @@
     'Gemma'
     'Ivy'
     'Jensen'
+    'Katniss'
     'Keturah'
     'Kim'
     'Korra'
@@ -353,6 +356,7 @@
     'Omar'
     'Orly'
     'Phoebe'
+    'Prim'
     'Rosaline'
     'Rowan'
     'Tansy'
@@ -384,6 +388,7 @@
     'Sharp Shooter'
     'Slyvos'
     'Vican'
+    'Warshall'
   ]
   'Ogre Munchkin M': [
     'Blob'
@@ -391,6 +396,7 @@
     'Dobo'
     'Draff'
     'Gert'
+    'Godel'
     'Goreball'
     'Gort'
     'Kog'
@@ -423,7 +429,9 @@
   ]
   'Ogre Peon M': [
     'Ba Bo'
+    'Bubbage'
     'Durbo'
+    'Jaro'
     'Kurger'
     'Mudwich'
     'Toe Pod'
@@ -440,6 +448,7 @@
   'Ogre M': [
     'Axe Ox'
     'Belch'
+    'Brusentsov'
     'Dronck'
     'Gorlog'
     'Grumus'
@@ -465,6 +474,7 @@
     'Gar\'ah'
     'Glonc'
     'Holkam'
+    'Kriskull'
     'Mak\'rah'
     'Marghurk'
     'Marnag'
@@ -477,6 +487,7 @@
     'Borgag'
     'Boz'
     'Burobb'
+    'Dijkstro'
     'Grognar'
     'Grul\'thock'
     'Grumoll'
@@ -495,6 +506,7 @@
   'Ogre Fangrider': [
     'Arizard'
     'Bortrok'
+    'Boruvka'
     'Doralt'
     'Dreek'
     'Flarsho'
@@ -559,6 +571,7 @@
   'Griffin Rider': [
     'Aeoldan'
     'Bestarius'
+    'Cristofide'
     'Letholdus'
   ]
   'Potion Master': [
@@ -573,6 +586,7 @@
     'Paracelsus'
     'Snake'
     'Vanders'
+    'Warnsdorff'
     'Zander'
   ]
   'Librarian': [
@@ -585,6 +599,7 @@
   ]
   'Equestrian': [
     'Beauty'
+    'Lovelace'
     'Mirial'
     'Neely'
     'Reynaldo'
@@ -596,6 +611,7 @@
     'Alphonse'
     'Altair'
     'Arthur'
+    'Bertrand'
     'Bruce'
     'Drake'
     'Duran'
@@ -608,6 +624,7 @@
     'Neville'
     'Shug'
     'Tharin'
+    'Vint'
     'Wain'
   ]
   'Captain': [
@@ -620,6 +637,7 @@
     'Isa'
     'Jane'
     'Jarin'
+    'Karp'
     'Katana'
     'Leona'
     'Lia'
@@ -631,6 +649,7 @@
   ]
   'Ninja': [
     'Amara'
+    'Kosaraju'
     'Minato'
     'Naruto'
     'Sakura'
@@ -640,7 +659,9 @@
   ]
   'Sorcerer': [
     'Beazer'
+    'Claude'
     'Gandalf'
+    'Kleene'
     'Pender'
     'Jezebel'
   ]
@@ -654,18 +675,22 @@
   'Sand Yak': [
     'Arngotho'
     'Falthror'
+    'Girvan'
     'Langthok'
     'Ofgar'
     'Randall'
   ]
   'Ogre Scout M': [
     'Frandar'
+    'Karnaugh'
     'Lanthon'
+    'Tarjan'
     'Yorgalfen'
   ]
   'Ogre Scout F': [
     'Freesa'
     'Ganju'
+    'Hopper'
     'Ralthora'
   ]
   'Skeleton': [


Fix image selection for records which were added dynamically


Dangerously set html for problem descriptions.

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/picoCTF/picoCTF-web.git/'


clean-up

clean-up

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/'


new state

new state

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/ivangabriele/atom-tfs.git/'


Added aria-owns attribute to eui-select

Added aria-owns attribute to eui-select

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/artsyca/emberui.git/'


No more error modal

No more error modal

--- SingularityUI/app/application.coffee
+++ SingularityUI/app/application.coffee
@@ -72,14 +72,13 @@

             if jqxhr.status is 502
                 Messenger().post "
A request failed because Singularity is deploying. Things should resolve in a few seconds so just hang tight...
"
-                return
-
-            if jqxhr.statusText is 'timeout'
+            else if jqxhr.statusText is 'timeout'
                 Messenger().post "
A #{ jqxhr.statusText } error occurred while accessing:

#{ url }
"
-                return
-
-            vex.dialog.alert "
A #{ jqxhr.statusText } error occurred when trying to access:

#{ url }

The request had status code #{ jqxhr.status }.

Here's the full jqxhr object:

#{ utils.htmlEncode utils.stringJSON jqxhr }
"
-
+            else
+                console.error "AJAX Error response"
+                console.error jqxhr
+                Messenger().post "
An error occurred when trying to access:

#{ url }

Check JS console for response.
"
+
     show: (view) ->
         if @page.children.length
             @page.replaceChild view.el, @page.children[0]


Fixing Issue #250

Fixing Issue #250

--- app/modules/vm/index.coffee
+++ app/modules/vm/index.coffee
@@ -36,18 +36,16 @@

     # Provides a fibonacci behaviour for stats refresh on failure
     $scope.refreshStatControl = refreshStatControl = {
-      baseStatInterval: 5000
+      baseStatInterval: 2000
       timeout: null
       running: false
+      attempt: 0

       start: () ->
         return if this.running
         this.running = true
         this._reset()
-        $scope.$on('$destroy', () =>
-          this.stop()
-        )
-        $scope.refreshStats($scope.VM.UUID)
+        $scope.$on('$destroy', () => this.stop())
         return this._trig(Date.now())
       _trig: (t1) ->
         if this.running
@@ -64,18 +62,20 @@

           .catch (err) =>
             if !this.running || $scope.VM.power_state isnt 'Running' || $scope.isVMWorking($scope.VM)
-              this.stop()
+              return this.stop()
             else
+              if this.attempt >= 2
+                return this.stop()
+              this.attempt++
               this._next()
-              this._trig(t2)
-              if this.running
-                throw err
+              return this._trig(t2)
       _reset: () ->
         this.terms = [1,1]
+        this.attempt = 0
       _next: () ->
         this.terms = [this.terms[1], this.terms[0] + this.terms[1]]
-      _factor: (p) ->
-        return this.terms[if p then 0 else 1]
+      _factor: (previous) ->
+        return this.terms[if previous then 0 else 1]
       stop: () ->
         if this.timeout
           $timeout.cancel(this.timeout)


debugging

debugging

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/pervino/solidus_designs.git/'


remove highlight from popup when animating out


Add new ProductResource

Add new ProductResource

error: pathspec 'app/assets/javascripts/admin/resources/resources/product_resource.js.coffee' did not match any file(s) known to git

--- app/assets/javascripts/admin/resources/resources/product_resource.js.coffee
+++ app/assets/javascripts/admin/resources/resources/product_resource.js.coffee
@@ -0,0 +1,6 @@
+angular.module("admin.resources").factory 'ProductResource', ($resource) ->
+  $resource('/admin/product/:id/:action.json', {}, {
+    'index':
+      url: '/api/products/bulk_products.json'
+      method: 'GET'
+  })


Call the callback rather than execute it so it passes this as expected

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/'


Fix up Config doc string

Fix up Config doc string

--- src/config.coffee
+++ src/config.coffee
@@ -15,11 +15,11 @@
 # ## Getting and setting config settings
 #
 # ```coffee
-#  # When no value has been set, `::get` returns the setting's default value
-#  atom.config.get('my-package.myKey') # -> 'defaultValue'
-#
-#  atom.config.set('my-package.myKey', 'value')
-#  atom.config.get('my-package.myKey') # -> 'value'
+# # With no value set, `::get` returns the setting's default value
+# atom.config.get('my-package.myKey') # -> 'defaultValue'
+#
+# atom.config.set('my-package.myKey', 'value')
+# atom.config.get('my-package.myKey') # -> 'value'
 # ```
 #
 # You may want to watch for changes. Use {::observe} to catch changes to the setting.
@@ -27,11 +27,11 @@
 # ```coffee
 # atom.config.set('my-package.myKey', 'value')
 # atom.config.observe 'my-package.myKey', (newValue) ->
-#   # `observe` calls your callback immediately and every time the value is changed
+#   # `observe` calls immediately and every time the value is changed
 #   console.log 'My configuration changed:', newValue
 # ```
 #
-# If you'd like to get a notification only when the value changes, use {::onDidChange}.
+# If you want a notification only when the value changes, use {::onDidChange}.
 #
 # ```coffee
 # atom.config.onDidChange 'my-package.myKey', (newValue) ->
@@ -41,27 +41,27 @@
 # ### Value Coercion
 #
 # Config settings each have a type specified by way of a
-# [schema](json-schema.org). Let's say we have an integer setting that only
-# allows numbers greater than 0:
-#
-# ```coffee
-#  # When no value has been set, `::get` returns the setting's default value
-#  atom.config.get('my-package.anInt') # -> 12
-#
-#  # The string will be coerced to the integer 123
-#  atom.config.set('my-package.anInt', '123')
-#  atom.config.get('my-package.anInt') # -> 123
-#
-#  # The string will be coerced to an integer, but it must be greater than 0, so is set to 1
-#  atom.config.set('my-package.anInt', '-20')
-#  atom.config.get('my-package.anInt') # -> 1
-# ```
-#
-# ## Defining config settings for your package
-#
-# You specify a schema under a `config` key
-#
-# ```coffeescript
+# [schema](json-schema.org). For example we might an integer setting that only
+# allows integers greater than `0`:
+#
+# ```coffee
+# # When no value has been set, `::get` returns the setting's default value
+# atom.config.get('my-package.anInt') # -> 12
+#
+# # The string will be coerced to the integer 123
+# atom.config.set('my-package.anInt', '123')
+# atom.config.get('my-package.anInt') # -> 123
+#
+# # The string will be coerced to an integer, but it must be greater than 0, so is set to 1
+# atom.config.set('my-package.anInt', '-20')
+# atom.config.get('my-package.anInt') # -> 1
+# ```
+#
+# ## Defining settings for your package
+#
+# Specify a schema under a `config` key in your package main.
+#
+# ```coffee
 # module.exports =
 #   # Your config schema
 #   config:
@@ -74,9 +74,12 @@
 #   # ...
 # ```
 #
+# See [Creating a Package](https://atom.io/docs/latest/creating-a-package) for
+# more info.
+#
 # ## Config Schemas
 #
-# We use [json schema][json-schema] which allows you to specify your value, its
+# We use [json schema](json-schema.org) which allows you to specify your value, its
 # default, the type it should be, etc. A simple example:
 #
 # ```coffee
@@ -110,14 +113,22 @@
 #
 # ### Supported Types
 #
-# * __string__ Values must be a string
-#   ```coffee
-#   config:
-#     someSetting:
-#       type: 'string'
-#       default: 'hello'
-#   ```
-# * __integer__ Values will be coerced into integer. Supports the (optional) `minimum` and `maximum` keys.
+# #### string
+#
+# Values must be a string.
+#
+# ```coffee
+# config:
+#   someSetting:
+#     type: 'string'
+#     default: 'hello'
+# ```
+#
+# #### integer
+#
+# Values will be coerced into integer. Supports the (optional) `minimum` and
+# `maximum` keys.
+#
 #   ```coffee
 #   config:
 #     someSetting:
@@ -126,50 +137,71 @@
 #       minimum: 1
 #       maximum: 11
 #   ```
-# * __number__ Values will be coerced into a number, including real numbers. Supports the (optional) `minimum` and `maximum` keys.
-#   ```coffee
-#   config:
-#     someSetting:
-#       type: 'number'
-#       default: 5.3
+#
+# #### number
+#
+# Values will be coerced into a number, including real numbers. Supports the
+# (optional) `minimum` and `maximum` keys.
+#
+# ```coffee
+# config:
+#   someSetting:
+#     type: 'number'
+#     default: 5.3
+#     minimum: 1.5
+#     maximum: 11.5
+# ```
+#
+# #### boolean
+#
+# Values will be coerced into a Boolean. `'true'` and `'t'` will be coerced into
+# `true`. Numbers, arrays, objects, and anything else will be coerced via
+# `!!value`.
+#
+# ```coffee
+# config:
+#   someSetting:
+#     type: 'boolean'
+#     default: false
+# ```
+#
+# #### array
+#
+# Value must be an Array. The types of the values can be specified by a
+# subschema in the `items` key.
+#
+# ```coffee
+# config:
+#   someSetting:
+#     type: 'array'
+#     default: [1, 2, 3]
+#     items:
+#       type: 'integer'
 #       minimum: 1.5
 #       maximum: 11.5
-#   ```
-# * __boolean__ Values will be coerced into a Boolean
-#   ```coffee
-#   config:
-#     someSetting:
-#       type: 'boolean'
-#       default: false
-#   ```
-# * __array__ Value must be an Array. The types of the values can be specified by a subschema in the `items` key.
-#   ```coffee
-#   config:
-#     someSetting:
-#       type: 'array'
-#       default: [1, 2, 3]
-#       items:
+# ```
+#
+# #### object
+#
+# Value must be an object. This allows you to nest config options. Sub options
+# must be under a `properties key`
+#
+# ```coffee
+# config:
+#   someSetting:
+#     type: 'object'
+#     properties:
+#       myChildIntOption:
 #         type: 'integer'
 #         minimum: 1.5
 #         maximum: 11.5
-#   ```
-# * __object__ Value must be an object. This allows you to nest config options. Sub options must be under a `properties key`
-#   ```coffee
-#   config:
-#     someSetting:
-#       type: 'object'
-#       properties:
-#         myChildIntOption:
-#           type: 'integer'
-#           minimum: 1.5
-#           maximum: 11.5
-#   ```
+# ```
 #
 # ### Other Supported Keys
 #
 # #### enum
 #
-# All schemas support an `enum` key. The enum key lets you specify all values
+# All types support an `enum` key. The enum key lets you specify all values
 # that the config setting can possibly be. `enum` _must_ be an array of values
 # of your specified type.
 #
@@ -197,9 +229,9 @@
 # #### title and description
 #
 # The settings view will use the `title` and `description` keys display your
-# option in a readable way. By default the settings view humanizes your config
-# key, so `someSetting` becomes `Some Setting`. In some cases, this is confusing
-# for users, and a more descriptive title is useful.
+# config setting in a readable way. By default the settings view humanizes your
+# config key, so `someSetting` becomes `Some Setting`. In some cases, this is
+# confusing for users, and a more descriptive title is useful.
 #
 # Descriptions will be displayed below the title in the settings view.
 #


Updated session schema for session aggregation

--- server/levels/sessions/level_session_schema.coffee
+++ server/levels/sessions/level_session_schema.coffee
@@ -100,9 +100,12 @@
                   type: 'object'
                 source:
                   type: 'string'
-
-  # TODO: specify this more
+
+# TODO: specify this more
   code:
+    type: 'object'
+
+  submittedCode:
     type: 'object'

   teamSpells:
@@ -134,6 +137,38 @@
     default: false
     index:true

+  matches:
+    type: 'array'
+    items:
+      type: 'object'
+      properties:
+        date: c.date
+          title: 'Time'
+        metrics:
+          type: 'object'
+          properties:
+            rank:
+              type: 'number'
+        opponents:
+          type: 'array'
+          items:
+            type: 'object'
+            properties:
+              id:
+                type: ['object', 'string']
+              codeSubmitDate: c.date
+                title: 'Submitted'
+              metrics:
+                type: 'object'
+                properties:
+                  rank:
+                    type: 'number'
+
+
+
+
+
+
 c.extendBasicProperties LevelSessionSchema, 'level.session'
 c.extendPermissionsProperties LevelSessionSchema, 'level.session'


collaboration: add realtime helpers

collaboration: add realtime helpers


Strange build failure... using spaces instead of tabs now.

--- lib/register.coffee
+++ lib/register.coffee
@@ -23,7 +23,7 @@

     device.token ?= generateToken()
     device.discoverWhitelist ?= [device.owner] if device.owner
-	device.configureWhitelist ?= [device.owner] if device.owner
+    device.configureWhitelist ?= [device.owner] if device.owner

     debug 'about to update device', device
     oldUpdateDevice newDevice.uuid, device, (error, savedDevice) =>


Initial start on an interpreter

Initial start on an interpreter

error: pathspec 'whip.coffee' did not match any file(s) known to git

--- whip.coffee
+++ whip.coffee
@@ -0,0 +1,100 @@
+#!/usr/bin/env coffee
+# This is heavily inspired by the Little Lisp Interpreter by Mary Rose Cook
+
+special =
+  lambda: (input, context) ->
+    (lambda_args...) ->
+      lambda_scope = input[1].reduce (acc, x, i) ->
+        acc[x.value] = lambda_args[i]
+        acc
+
+      interpret input[2], new Context(lambda_scope, context)
+
+library =
+  first: (x) -> x[0]
+  rest: (x) -> x[1..]
+  print: (x) ->
+    console.log x
+    x
+
+tokenize = (input) ->
+  input.split('"')
+    .map((x, i) ->
+      if i % 2 is 0 # not in string
+        x.replace(/\(/g, ' ( ')
+          .replace /\)/g, ' ) '
+      else
+        x.replace /\s/g, "!%!"
+    )
+    .join('"')
+    .trim()
+    .split(/\s+/)
+    .map (x) -> x.replace(/!%!/g, " ")
+
+parenthesize = (input, list) ->
+  if list is undefined
+    parenthesize input, []
+  else
+    token = input.shift()
+    switch token
+      when undefined
+        list.pop()
+      when '('
+        list.push parenthesize input, []
+        parenthesize input, list
+      when ')'
+        list
+      else
+        parenthesize input, list.concat categorize token
+
+categorize = (input) ->
+  if not isNaN parseFloat input
+    {
+      type: 'literal'
+      value: parseFloat input
+    }
+  else if input[0] is '"' and input[-1..] is '"'
+    {
+      type: 'literal'
+      value: input.slice 1, -1
+    }
+  else
+    {
+      type: 'identifier'
+      value: input
+    }
+
+parse = (input) ->
+  parenthesize tokenize input
+
+class Context
+  constructor: (scope, parent) ->
+    @scope = scope
+    @parent = parent
+    return
+
+  get: (ident) ->
+    if ident of @scope
+      @scope[ident]
+    else if @parent isnt undefined
+      @parent.get ident
+
+interpret = (input, context) ->
+  if context is undefined
+    interpret input, new Context(library)
+  else if input instanceof Array
+    interpret_list input, context
+  else if input.type is 'identifier'
+    context.get input.value
+  else
+    input.value
+
+interpret_list = (input, context) ->
+  if input[0].value in special
+    special[input[0].value] input, context
+  else
+    list = input.map (x) -> interpret x, context
+    if list[0] instanceof Function
+      list[0].apply undefined, list[1..]
+    else
+      list


Fix syntax highlighting

Fix syntax highlighting

--- src/editor.coffee
+++ src/editor.coffee
@@ -28,9 +28,9 @@
 # be called with all current editor instances and also when any editor is
 # created in the future.
 #
-# ```coffeescript
-#   atom.workspace.eachEditor (editor) ->
-#     editor.insertText('Hello World')
+# ```coffee
+# atom.workspace.eachEditor (editor) ->
+#   editor.insertText('Hello World')
 # ```
 #
 # ## Buffer vs. Screen Coordinates


Sometimes there might not be a selection.

--- src/editor.coffee
+++ src/editor.coffee
@@ -1305,7 +1305,7 @@
   addSelectionForBufferRange: (bufferRange, options={}) ->
     @markBufferRange(bufferRange, _.defaults(@getSelectionMarkerAttributes(), options))
     selection = @getLastSelection()
-    selection.autoscroll() if @manageScrollPosition
+    selection?.autoscroll() if @manageScrollPosition
     selection

   # Public: Set the selected range in buffer coordinates. If there are multiple


Adding application test

Adding application test

error: pathspec 'tests/jasmine/client/unit/lib/sideNav.coffee' did not match any file(s) known to git

--- tests/jasmine/client/unit/lib/sideNav.coffee
+++ tests/jasmine/client/unit/lib/sideNav.coffee
@@ -0,0 +1,5 @@
+describe 'App | Client | Lib | SideNav', ->
+	'use strict';
+
+	it 'should exist', ->
+		expect(SideNav).toBeDefined()


add IE conditionals test

add IE conditionals test

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

--- test/ieConditionals.coffee
+++ test/ieConditionals.coffee
@@ -0,0 +1,7 @@
+cc = require '../lib/coffeecup'
+
+describe 'IE conditionals', ->
+  describe " ie 'gte IE8', -> link href: 'ie.css', rel: 'stylesheet'", ->
+    it 'should render <!--[if gte IE8]><link href="ie.css" rel="stylesheet" /><![endif]-->', ->
+      h = -> ie 'gte IE8', -> link href: 'ie.css', rel: 'stylesheet'
+      cc.render(h).should.equal '<!--[if gte IE8]><link href="ie.css" rel="stylesheet" /><![endif]-->'


Prevent disabling filters when sorting [#90083872]


help tag id creation was moved into the ExamObject class

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/NightingaleStudio/exam.js.git/'


Remove waste file

Remove waste 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/kjirou/monsters-flow.git/'


Fixed issue while save cloud recordings

Fixed issue while save cloud recordings

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/'


experience bij

experience bij

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

--- src/scripts/bij.coffee
+++ src/scripts/bij.coffee
@@ -0,0 +1,6 @@
+# EXPERIENCE BIJ
+#
+
+module.exports = (robot) ->
+  robot.hear /bij/i, (msg) ->
+    msg.send "EXPERIENCE BIJ!"


Adding modifier endpoints

Adding modifier endpoints

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

--- src/features/modifier.coffee
+++ src/features/modifier.coffee
@@ -0,0 +1,30 @@
+	`// @if TARGET=='nodejs'
+	`
+	class Modifier
+
+		constructor: (@m) ->
+
+		Get: (product, modifier, callback, error) ->
+
+			return @m.Request 'products/'+product+'/modifiers/'+modifier, 'GET', null, callback, error
+
+		Create: (product, data, callback, error) ->
+
+			return @m.Request 'products/'+product+'/modifiers', 'POST', data, callback, error
+
+		Update: (product, modifier, data, callback, error) ->
+
+			return @m.Request 'products/'+product+'/modifiers/'+modifier, 'PUT', data, callback, error
+
+		Fields: (product, modifier = 0, callback, error) ->
+
+			uri  = 'products/'+product+'/modifiers/'+ if modifier != 0 then modifier+'/fields' else 'fields'
+
+			return @m.Request uri, 'GET', null, callback, error
+
+		Update: (product, modifier, callback, error) ->
+
+			return @m.Request 'products/'+product+'/modifiers/'+modifier, 'DELETE', null, callback, error
+
+	`// @endif
+	`


new line store

new line store

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/BethyDiakabananas/MBTA-Tweets-Site.git/'


добавил вложенную сортировку дерева

добавил вложенную сортировку дерева

error: pathspec 'app/assets/javascripts/redde-admin/nestedSortable.js.coffee' did not match any file(s) known to git

--- app/assets/javascripts/redde-admin/nestedSortable.js.coffee
+++ app/assets/javascripts/redde-admin/nestedSortable.js.coffee
@@ -0,0 +1,24 @@
+#= require jquery-ui/sortable
+#= require ./jquery.mjs.nestedSortable.js
+
+$ ->
+  $('ol.sortable').nestedSortable
+    disableNesting: 'no-nest'
+    forcePlaceholderSize: true
+    handle: 'div'
+    helper: 'clone'
+    items: 'li'
+    maxLevels: 2
+    opacity: .6
+    placeholder: 'placeholder'
+    revert: 250
+    rootID: 'root'
+    tabSize: 25
+    tolerance: 'pointer'
+    toleranceElement: '> div'
+    update: ->
+      serialized = $(this).nestedSortable('serialize')
+      $.ajax
+        method: 'POST'
+        url: location.pathname + '/sort'
+        data: serialized


Current project does not show up in the list anymore

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/douggr/atom-project-manager.git/'


Disabled authentication for now

Disabled authentication for now

--- server/routes/mail.coffee
+++ server/routes/mail.coffee
@@ -31,6 +31,7 @@

 isRequestFromDesignatedCronHandler = (req, res) ->
   if req.ip isnt config.mail.cronHandlerPublicIP and req.ip isnt config.mail.cronHandlerPrivateIP
+    console.log "RECEIVED REQUEST FROM IP #{req.ip}(headers indicate #{req.headers['x-forwarded-for']}"
     console.log "UNAUTHORIZED ATTEMPT TO SEND TRANSACTIONAL LADDER EMAIL THROUGH CRON MAIL HANDLER"
     res.send("You aren't authorized to perform that action. Only the specified Cron handler may perform that action.")
     res.end()
@@ -41,7 +42,7 @@
 handleLadderUpdate = (req, res) ->
   log.info("Going to see about sending ladder update emails.")
   requestIsFromDesignatedCronHandler = isRequestFromDesignatedCronHandler req, res
-  unless requestIsFromDesignatedCronHandler then return
+  #unless requestIsFromDesignatedCronHandler then return

   res.send('Great work, Captain Cron! I can take it from here.')
   res.end()


Added tests for blank/null/undefined/missing/empty values

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

--- test/blank.coffee
+++ test/blank.coffee
@@ -0,0 +1,44 @@
+# Requires
+require "coffee-script"
+assert = require('assert')
+_ = require "underscore"
+require("../src/underscore-query")(_)
+
+_collection =  [
+  {title:"Home", colors:["red","yellow","blue"], likes:12, featured:true, content: "Dummy content about coffeescript", blank: null}
+  {title:"About", colors:["red"], likes:2, featured:true, content: "dummy content about javascript", blank: ''}
+  {title:"Contact", colors:["red","blue"], likes:20, content: "Dummy content about PHP", blank: undefined},
+  {title:"Careers", colors:["purple","white"], likes:10, content: "Dummy content about Careers"},  # blank simply omitted
+  {title:"Sponsors", colors:["green","gold"], likes:14, content: "Dummy content about Sponsors", blank: []}
+]
+
+create = -> _.clone(_collection)
+
+describe "Underscore Query Tests: Blanks", ->
+
+  it "Handles blank, null, and undefined values", ->
+
+    a = create()
+    result = _.query a, blank:null
+    assert.equal result.length, 1
+    assert.equal result[0].title, "Home"
+
+    result = _.query a, blank: ""
+    assert.equal result.length, 1
+    assert.equal result[0].title, "About"
+
+    result = _.query a, blank: undefined
+    assert.equal result.length, 2
+    assert.equal result[0].title, "Contact"
+    assert.equal result[1].title, "Careers"
+
+    result = _.query a, blank: []
+    assert.equal result.length, 1
+    assert.equal result[0].title, "Sponsors"
+
+    $blank = $cb: (attr) ->
+      attr is null or attr is `undefined` or attr is "" or (attr.length is 0)
+    result = _.query a, blank: $blank
+    assert.equal result.length, 5
+
+


social/notifiable: remove updateTemplateAndNotify

--- workers/social/lib/social/traits/notifiable.coffee
+++ workers/social/lib/social/traits/notifiable.coffee
@@ -33,25 +33,6 @@
           account.sendNotification 'InstanceChanged', opts

-  updateTemplateAndNotify: (options, change, callback) ->
-
-    { group } = options
-    id = @getId()
-
-    @update change, (err) ->
-
-      callback err
-      return  unless group
-
-      JGroup = require '../models/group'
-      JGroup.one { slug : group }, (err, group_) ->
-        return  if err or not group_
-
-        opts = { id, group, change, timestamp: Date.now() }
-        group_.sendNotification 'SetStackTemplateAccessLevel', opts
-
-
-
   removeAndNotify: (options, callback) ->

     { account, group, target } = options


fix distinct

fix distinct

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/andykent/river.git/'


Remove deprecated api call

Remove deprecated api call

Close #35

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/aki77/atomatigit.git/'


I'm stupid

I'm stupid

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/Mikuia/Mikuia.git/'


missing license header

missing license header

--- resources/assets/coffee/store-username-change.coffee
+++ resources/assets/coffee/store-username-change.coffee
@@ -1,3 +1,21 @@
+###
+#    Copyright 2015-2017 ppy Pty. Ltd.
+#
+#    This file is part of osu!web. osu!web is distributed with the hope of
+#    attracting more community contributions to the core ecosystem of osu!.
+#
+#    osu!web is free software: you can redistribute it and/or modify
+#    it under the terms of the Affero GNU General Public License version 3
+#    as published by the Free Software Foundation.
+#
+#    osu!web is distributed WITHOUT ANY WARRANTY; without even the implied
+#    warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#    See the GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with osu!web.  If not, see <http://www.gnu.org/licenses/>.
+###
+
 preventUsernameSubmission = ->
   StoreCart.setEnabled(false)
   $('#username-check-price').html ''


Remove redundancy in HUD.findModeKeydown

--- content_scripts/hud.coffee
+++ content_scripts/hud.coffee
@@ -74,17 +74,18 @@

   findModeKeydown: (event) ->
     window.scrollTo @findMode.scrollX, @findMode.scrollY if @findMode.options.returnToViewport
-    if event.keyCode == keyCodes.backspace || event.keyCode == keyCodes.deleteKey
-      @findMode.exit()
-      new PostFindMode if findModeQuery.hasResults
-    else if event.keyCode == keyCodes.enter
+    postExit = null
+
+    if event.keyCode == keyCodes.enter
       handleEnterForFindMode()
-      @findMode.exit()
-      new PostFindMode if findModeQuery.hasResults
     else if KeyboardUtils.isEscape event
-      @findMode.exit()
-      handleEscapeForFindMode()
-      new PostFindMode if findModeQuery.hasResults
+      # We don't want FindMode to handle the click events that handleEscapeForFindMode can generate, so we
+      # wait until the mode is closed before running it.
+      postExit = handleEscapeForFindMode
+
+    @findMode.exit()
+    postExit?()
+    new PostFindMode if findModeQuery.hasResults

   isReady: do ->
     ready = false


Refactors the tests.

Refactors the tests.

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/kevgo/modularity-rails.git/'


Disable auto-linking inside Katex

Disable auto-linking inside Katex

--- packages/rocketchat-autolinker/autolinker.coffee
+++ packages/rocketchat-autolinker/autolinker.coffee
@@ -19,13 +19,17 @@
 						return regUrls.test match.matchedText
 					return null

+			regNonAutoLink = /(```\w*[\n ]?[\s\S]*?```+?)|(`(?:[^`]+)`)/
+			if RocketChat.settings.get 'Katex_Enabled'
+				regNonAutoLink = /(```\w*[\n ]?[\s\S]*?```+?)|(`(?:[^`]+)`)|(\\\(\w*[\n ]?[\s\S]*?\\\)+?)/
+
 			# Separate text in code blocks and non code blocks
-			msgParts = message.html.split /(```\w*[\n ]?[\s\S]*?```+?)|(`(?:[^`]+)`)/
+			msgParts = message.html.split regNonAutoLink

 			for part, index in msgParts
 				if part?.length? > 0
 					# Verify if this part is code
-					codeMatch = part.match /(?:```(\w*)[\n ]?([\s\S]*?)```+?)|(?:`(?:[^`]+)`)/
+					codeMatch = part.match regNonAutoLink
 					if not codeMatch?
 						msgParts[index] = autolinker.link part


Fix login logo in subdir

Fix login logo in subdir

--- packages/rocketchat-ui-login/login/header.coffee
+++ packages/rocketchat-ui-login/login/header.coffee
@@ -1,5 +1,6 @@
 Template.loginHeader.helpers
 	logoUrl: ->
 		asset = RocketChat.settings.get('Assets_logo')
+		prefix = __meteor_runtime_config__.ROOT_URL_PATH_PREFIX || ''
 		if asset?
-			return asset.url or asset.defaultUrl
+			return prefix + (asset.url or asset.defaultUrl)


Refactor variable declaration pattern collection to repository

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/pyfisch/atom-language-rust.git/'


Add plugin field

Add plugin field

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/Hiroto-K/HkApps.git/'


adds current user mode;

adds current user mode;

error: pathspec 'models/current_user.coffee' did not match any file(s) known to git

--- models/current_user.coffee
+++ models/current_user.coffee
@@ -0,0 +1,17 @@
+#
+# Model for the current user
+#
+
+User = require "./user.coffee"
+sd = require("sharify").data
+
+module.exports = class User extends User
+
+  url: -> "#{sd.API_URL}/accounts"
+
+  sync: (method, model, options = {}) ->
+    options.data ?= {}
+    options.data.auth_token = @get 'access_token'
+    super
+
+  parse: (response) -> response.user


Avoid filling in text box with text 'null'

Happens in IE

--- resources/assets/coffee/forum-topic-reply.coffee
+++ resources/assets/coffee/forum-topic-reply.coffee
@@ -46,7 +46,7 @@
     return unless @available()

     @deleteState 'sticking'
-    @input[0].value = @getState 'text'
+    @input[0].value = @getState('text') || ''
     @activate() if @getState('active') == '1'


its not a button ok

its not a button ok

--- app/assets/javascripts/questionbox/all.coffee
+++ app/assets/javascripts/questionbox/all.coffee
@@ -25,7 +25,7 @@
 # hotkey for accessing this quickly
 $(document).on "keydown", (evt) ->
   if evt.keyCode == 77 and (evt.ctrlKey or evt.metaKey)
-    $('button[name=toggle-all-ask]').trigger 'click'
+    $('.btn[name=toggle-all-ask]').trigger 'click'

 # see GitHub issue #2
 ($ document).on "keydown", "textarea[name=qb-all-question]", (evt) ->


Adding raven logger

Adding raven logger

error: pathspec 'app/coffee/modules/common/raven-logger.coffee' did not match any file(s) known to git

--- app/coffee/modules/common/raven-logger.coffee
+++ app/coffee/modules/common/raven-logger.coffee
@@ -0,0 +1,41 @@
+###
+# Copyright (C) 2014 Andrey Antukh <niwi@niwi.be>
+# Copyright (C) 2014 Jesús Espino Garcia <jespinog@gmail.com>
+# Copyright (C) 2014 David Barragán Merino <bameda@dbarragan.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# File: modules/common/raven-logger.coffee
+###
+
+
+taiga = @.taiga
+
+module = angular.module("taigaCommon")
+
+ExceptionHandlerFactory = ($log, @config) ->
+    ravenConfig = @config.get("ravenConfig", null)
+    if ravenConfig
+      $log.debug "Using the RavenJS exception handler."
+      Raven.config(ravenConfig).install()
+      return (exception, cause) ->
+        $log.error.apply($log, arguments)
+        Raven.captureException(exception)
+
+    else
+      $log.debug "Using the default logging exception handler."
+      return (exception, cause) ->
+          $log.error.apply($log, arguments)
+
+module.factory("$exceptionHandler", ["$log", "$tgConfig", ExceptionHandlerFactory])


Added a script to migrate existing data to the recent update which introduced _deviceId object.

error: pathspec 'tools/update-deviceid.coffee' did not match any file(s) known to git

--- tools/update-deviceid.coffee
+++ tools/update-deviceid.coffee
@@ -0,0 +1,37 @@
+# This script will generate _deviceId struct for all devices in DB.
+# To be used in migrating existing data to the recent update which introduced _deviceId object.
+config = require '../config'
+mongodb = require 'mongodb'
+
+dbserver = new mongodb.Server(config.MONGODB_SOCKET, 0, {auto_reconnect: true})
+db = new mongodb.Db(config.DATABASE_NAME, dbserver, {native_parser: true, safe: true})
+
+query = {}
+
+projection = {
+  _id : true,
+  'InternetGatewayDevice.DeviceInfo' : true
+}
+
+db.open((err, db) ->
+  db.collection('devices', (err, collection) ->
+    cur = collection.find(query)
+    cur.each((err, doc) ->
+      if not doc?
+        db.close()
+        return
+      serialNumber = doc['InternetGatewayDevice']['DeviceInfo']['SerialNumber']['_value']
+      oui = doc['InternetGatewayDevice']['DeviceInfo']['ManufacturerOUI']['_value']
+      manufacturer = doc['InternetGatewayDevice']['DeviceInfo']['Manufacturer']['_value']
+      productClass = doc['InternetGatewayDevice']['DeviceInfo']['ProductClass']['_value']
+      id = doc['_id']
+      collection.update({_id : id}, {$set : {
+        '_deviceId._Manufacturer' : manufacturer,
+        '_deviceId._OUI' : oui,
+        '_deviceId._ProductClass' : productClass,
+        '_deviceId._SerialNumber' : serialNumber
+      }}, () ->
+      )
+    )
+  )
+)


implementing utility class for testing http-api with vows

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/leonidas/qa-dashboard.git/'


Remove editor property from line widget object

Signed-off-by: Sonmez Kartal <d2d15c3d37396a5f2a09f8b42cf5f27d43a3fbde@koding.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/andrewjcasal/koding.git/'


Special case reactionary in cache

Special case reactionary in cache

--- build/tasks/generate-module-cache-task.coffee
+++ build/tasks/generate-module-cache-task.coffee
@@ -27,6 +27,15 @@
           'vendor'
         ]

+    # Reactionary does not have an explicit react dependency
+    metadata._atomModuleCache.folders.push
+      paths: [
+        'node_modules/reactionary-atom-fork/lib'
+      ]
+      dependencies: {
+        'react-atom-fork': metadata.dependencies['react-atom-fork']
+      }
+
     validExtensions = ['.js', '.coffee', '.json', '.node']

     extensions = {}


Remove unused grunt task

Remove unused grunt task

--- build/tasks/publish-packages.coffee
+++ build/tasks/publish-packages.coffee
@@ -1,108 +0,0 @@
-async = require 'async'
-request = require 'request'
-
-# Configure and publish all packages in package.json to atom.io
-#
-# This task should be run whenever you want to be sure that atom.io contains
-# all the packages and versions referenced in Atom's package.json file.
-module.exports = (grunt) ->
-  {spawn} = require('./task-helpers')(grunt)
-
-  baseUrl = "https://atom.io/api/packages"
-
-  packageExists = (packageName, token, callback) ->
-    requestSettings =
-      url: "#{baseUrl}/#{packageName}"
-      json: true
-      headers:
-        authorization: token
-    request.get requestSettings, (error, response, body={}) ->
-      if error?
-        callback(error)
-      else
-        callback(null, response.statusCode is 404)
-
-  createPackage = (packageName, token, callback) ->
-    requestSettings =
-      url: baseUrl
-      json: true
-      headers:
-        authorization: token
-      method: 'POST'
-      body:
-        repository: "atom/#{packageName}"
-
-    request.get requestSettings, (error, response, body={}) ->
-      if error?
-        callback(error)
-      else if response.statusCode isnt 201
-        message = body.message ? body.error ? body
-        callback(new Error("Creating package failed: #{message}"))
-      else
-        callback()
-
-  createPackageVersion = (packageName, tag, token, callback) ->
-    requestSettings =
-      url: "#{baseUrl}/#{packageName}/versions"
-      json: true
-      method: 'POST'
-      headers:
-        authorization: token
-      body:
-        tag: tag
-
-    request.get requestSettings, (error, response, body={}) ->
-      if error?
-        callback(error)
-      else if response.statusCode isnt 201
-        message = body.message ? body.error ? body
-        if message is 'Version exists'
-          callback()
-        else
-          callback(new Error("Creating new version failed: #{message}"))
-      else
-        callback()
-
-  getToken = (callback) ->
-    if token = process.env.ATOM_ACCESS_TOKEN
-      callback(null, token)
-    else
-      spawn {cmd: 'security', args: ['-q', 'find-generic-password', '-ws', 'GitHub API Token']}, (error, result, code) ->
-        token = result.toString() unless error?
-        callback(error, token)
-
-  grunt.registerTask 'publish-packages', 'Publish all bundled packages', ->
-    done = @async()
-
-    getToken (error, token) ->
-      unless token
-        grunt.log.error('Token not found in keychain or ATOM_ACCESS_TOKEN environment variable')
-        done(false)
-
-      {packageDependencies} = grunt.file.readJSON('package.json') ? {}
-      tasks = []
-      for name, version of packageDependencies
-        do (name, version) ->
-          tasks.push (callback) ->
-            grunt.verbose.writeln("Publishing #{name}@#{version}")
-            tag = "v#{version}"
-            packageExists name, token, (error, exists) ->
-              if error?
-                callback(error)
-                return
-
-              if exists
-                createPackage name, token, (error) ->
-                  if error?
-                    callback(error)
-                  else
-                    createPackageVersion(name, tag, token, callback)
-              else
-                createPackageVersion(name, tag, token, callback)
-
-      async.waterfall tasks, (error) ->
-        if error?
-          grunt.log.error(error.message)
-          done(false)
-        else
-          done()


Fix dependency bug with Transform

Fix dependency bug with Transform

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/jamesotron/ember-enumerology.git/'


cloudwatch errors get logged to console

cloudwatch errors get logged to console

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/'


Update cs.coffee

Update cs.coffee

Fixed missing space.

--- app/locale/cs.coffee
+++ app/locale/cs.coffee
@@ -719,7 +719,7 @@
     diplomat_i18n_page_prefix: "Můžete začít překládat naše úrovně přejítím na naše"
     diplomat_i18n_page: "stránky překladů"
     diplomat_i18n_page_suffix: ", nebo naše prostředí a stránky na GitHub."
-    diplomat_join_pref_github: "Najděte soubor pro svůj jazyk"
+    diplomat_join_pref_github: "Najděte soubor pro svůj jazyk "
     diplomat_github_url: "na GitHub"
     diplomat_join_suf_github: ", upravte ho online a zašlete pull request. Také zaškrtněte toto políčko, abyste zůstali informováni o novém vývoji internacionalizace!"
     more_about_diplomat: "Dozvědět se více o tom, jak se stát Diplomatem"


Update /teachers copy

Update /teachers copy

--- app/locale/en.coffee
+++ app/locale/en.coffee
@@ -597,7 +597,7 @@
     intro_2: "No experience required!"
     free_title: "How much does it cost?"
     cost_china: "CodeCombat in China is free for the first five levels, after which it costs $9.99 USD per month for access to our other 140+ levels on our exclusive China servers."
-    free_1: "CodeCombat Basic is FREE! There are 80+ free levels which cover every concept."
+    free_1: "There are 80+ FREE levels which cover every concept." # {change}
     free_2: "A monthly subscription provides access to video tutorials and extra practice levels."
     teacher_subs_title: "Teachers get free subscriptions!"
     teacher_subs_1: "Please contact"


Updated i18n (part 1)

Updated i18n (part 1)

--- app/locale/en.coffee
+++ app/locale/en.coffee
@@ -158,6 +158,7 @@
     unwatch: "Unwatch"
     submit_patch: "Submit Patch"
     submit_changes: "Submit Changes"
+    save_changes: "Save Changes"

   general:
     and: "and"
@@ -609,6 +610,15 @@
     sub_includes_5: "7 new heroes with unique skills to master"
     sub_includes_6: "3500 bonus gems every month"
     sub_includes_7: "Private Clans"
+    monitor_progress_title: "How do I monitor student progress?"
+    monitor_progress_1: "Student progress can be monitored by creating a"
+    monitor_progress_2: "for your class."
+    monitor_progress_3: "To add a student, send them the invite link for your Clan, which is on the"
+    monitor_progress_4: "page."
+    monitor_progress_5: "After they join, you will see a summary of the student's progress on your Clan's page."
+    private_clans_1: "Private Clans provide increased privacy and detailed progress information for each student."
+    private_clans_2: "To create a private Clan, check the 'Make clan private' checkbox when creating a"
+    private_clans_3: "."
     who_for_title: "Who is CodeCombat for?"
     who_for_1: "We recommend CodeCombat for students aged 9 and up. No prior programming experience is needed."
     who_for_2: "We've designed CodeCombat to appeal to both boys and girls."
@@ -621,6 +631,12 @@
     how_much_2: "monthly subscription"
     how_much_3: "costs $9.99, and can be cancelled anytime."
     how_much_4: "Additionally, we provide discounts for larger groups:"
+    how_much_5: "We accept discounted one-time purchases and yearly subscription purchases for groups, such as a class or school.  Please contact"
+    how_much_6: "for more details."
+    more_info_title: "Where can I find more information?"
+    more_info_1: "Our"
+    more_info_2: "teachers forum"
+    more_info_3: "is a good place to connect with fellow educators who are using CodeCombat."
     sys_requirements_title: "System Requirements"
     sys_requirements_1: "A modern web browser. Newer versions of Chrome, Firefox, or Safari. Internet Explorer 9 or later."
     sys_requirements_2: "CodeCombat is not supported on iPad yet."
@@ -732,6 +748,34 @@
     social_gplus: "Join CodeCombat on Google+"
     social_hipchat: "Chat with us in the public CodeCombat HipChat room"
     contribute_to_the_project: "Contribute to the project"
+
+  clans:
+    clan: "Clan"
+    clans: "Clans"
+    new_name: "New clan name"
+    new_description: "New clan description"
+    make_private: "Make clan private"
+    subs_only: "subscribers only"
+    create_clan: "Create New Clan"
+    public_clans: "Public Clans"
+    my_clans: "My Clans"
+    clan_name: "Clan Name"
+    name: "Name"
+    chieftain: "Chieftain"
+    type: "Type"
+    edit_clan_name: "Edit Clan Name"
+    edit_clan_description: "Edit Clan Description"
+    edit_name: "edit name"
+    edit_description: "edit description"
+    private: "(private)"
+    summary: "Summary"
+    average_level: "Average Level"
+    average_achievements: "Average Achievements"
+    delete_clan: "Delete Clan"
+    leave_clan: "Leave Clan"
+    join_clan: "Join Clan"
+    invite_1: "Invite:"
+    invite_2: "*Invite players to this Clan by sending them this link."

   classes:
     archmage_title: "Archmage"
@@ -981,6 +1025,7 @@
     no_achievements: "No Achievements earned yet."
     favorite_prefix: "Favorite language is "
     favorite_postfix: "."
+    not_member_of_clans: "Not a member of any clans yet."

   achievements:
     last_earned: "Last Earned"
@@ -1086,6 +1131,7 @@
     user_remarks: "User Remarks"
     versions: "Versions"
     items: "Items"
+    hero: "Hero"
     heroes: "Heroes"
     achievement: "Achievement"
     clas: "CLAs"


Update fr.coffee

Update fr.coffee

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/trotod/codecombat.git/'


small fix

small fix

--- app/locale/ru.coffee
+++ app/locale/ru.coffee
@@ -162,7 +162,7 @@
     pending: "В ожидании"
     accepted: "Принято"
     rejected: "Отклонено"
-    withdrawn: "Отозвать"
+    withdrawn: "Отозвано"
     submitter: "Податель"
     submitted: "Представлено"
     commit_msg: "Сопроводительное сообщение"


i think i was just coding

i think i was just coding

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/jencka/2001-A-SPACE-SACRIFICE.git/'


Undo...

Undo...

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/vietarmis/sql-parser.git/'


scraperwiki.js version 2 - see #228

scraperwiki.js version 2 - see #228

error: pathspec 'shared/code/scraperwiki-2.coffee' did not match any file(s) known to git

--- shared/code/scraperwiki-2.coffee
+++ shared/code/scraperwiki-2.coffee
@@ -0,0 +1,252 @@
+###
+scraperwiki.js 2
+Copyright (c) 2013 ScraperWiki Limited
+ScraperWiki tool client library. See
+https://beta.scraperwiki.com/help
+
+jQuery is required.
+###
+
+scraperwiki = sw =
+  dataset: {}
+  tool: {}
+
+
+scraperwiki.box = window.location.pathname.split('/')[1]
+
+
+scraperwiki.alert = (title, message, level=0) ->
+  # [title] and [message] should be html strings. The first is displayed in bold.
+  # If [level] is a truthful value, the alert is printed in red.
+  $a = $('<div>').addClass('alert').prependTo('body')
+  $a.addClass('alert-error') if level
+  $a.html """<button type="button" class="close" data-dismiss="alert">×</button> <strong>#{title}</strong> #{message}"""
+
+
+scraperwiki.readSettings = ->
+  # returns dataset and tool settings from the current tool's URL hash
+  return null if window.location.hash is ''
+  hash = window.location.hash.substr(1)
+  try
+    settings = JSON.parse decodeURIComponent(hash)
+  catch e
+    return null
+  return settings
+
+
+scraperwiki.url = (arg) ->
+  # [arg] should either be a string (to redirect the browser),
+  # a callback function (which will be passed the current url),
+  # or undefined, in which case a jQuery deferred object is
+  # returned, on which you can call .done() and .always()
+  if typeof(arg) is 'string'
+    # they want to set the url (ie: redirect)
+    parent.scraperwiki.xdm.redirect(arg)
+  else
+    # they want to retrieve the current url
+    dfd = new jQuery.Deferred()
+    if typeof(arg) is 'function'
+      parent.scraperwiki.xdm.getURL arg
+    else
+      parent.scraperwiki.xdm.getURL dfd.resolve
+    return dfd.promise()
+
+
+scraperwiki.dataset.name = (arg) ->
+  # [arg] should either be a string (to set the dataset's name),
+  # a function (to get the dataset's current name, and pass it
+  # to the callback function),
+  # or undefined, in which case we get the dataset's current name
+  # and pass it to a jQuery deferred object.
+  if typeof(arg) is 'string'
+    parent.scraperwiki.xdm.rename(scraperwiki.box, arg)
+  else
+    dfd = new jQuery.Deferred()
+    if typeof(arg) is 'function'
+      arg null, scraperwiki.readSettings().target.displayName
+    else
+      dfd.resolve scraperwiki.readSettings().target.displayName
+    return dfd.promise()
+
+
+scraperwiki.dataset.sql = (sql, success, error) ->
+  # execute a SQL query on the main dataset.
+  # [success] and [error] callbacks are optional,
+  # since this returns a jQuery deferred object on which
+  # you can chain .done() and .fail() handlers.
+  settings = scraperwiki.readSettings()
+  boxSettings = settings.target ? settings.source
+  options =
+    url: "#{boxSettings.url}/sql/"
+    type: "GET"
+    dataType: "json"
+    data:
+      q: sql
+  if success?
+    options.success = success
+  if error?
+    options.error = error
+  $.ajax options
+
+
+scraperwiki.dataset.sql.meta = (success, error) ->
+  # get info about the main dataset's SQL database.
+  # [success] and [error] callbacks are optional,
+  # since this returns a jQuery deferred object on which
+  # you can chain .done() and .fail() handlers.
+  settings = scraperwiki.readSettings()
+  boxSettings = settings.target ? settings.source
+  options =
+    url: "#{boxSettings.url}/sql/meta"
+    type: "GET"
+    dataType: "json"
+  if success?
+    options.success = success
+  if error?
+    options.error = error
+  $.ajax options
+
+
+scraperwiki.dataset.installTool = (toolName, query) ->
+  # installs the specified tool into the current dataset,
+  # passing it the optional [query] in scraperwiki.readSettings().sqlQuery
+  parent.scraperwiki.xdm.pushSQL(query, toolName)
+
+
+scraperwiki.tool.name = (arg) ->
+  # [arg] should either be a string (to set the tool's name),
+  # a function (to get the tool's current name, and pass it
+  # to the callback function),
+  # or undefined, in which case we get the tool's current name
+  # and pass it to a jQuery deferred object.
+  if typeof(arg) is 'string'
+    # we can't currently rename a tool; only a dataset!!
+    # parent.scraperwiki.xdm.rename(scraperwiki.box, arg)
+  else
+    # we can't currently get the tool's current name,
+    # so we return a placeholder.
+    dfd = new jQuery.Deferred()
+    if typeof(arg) is 'function'
+      arg 'under construction', null
+    else
+      dfd.reject 'under construction'
+    return dfd.promise()
+
+
+scraperwiki.tool.sql = (sql, success, error) ->
+  # execute a SQL query on the tool's own internal database.
+  # [success] and [error] callbacks are optional,
+  # since this returns a jQuery deferred object on which
+  # you can chain .done() and .fail() handlers.
+  settings = scraperwiki.readSettings()
+  options =
+    url: "#{settings.source.url}/sql/"
+    type: "GET"
+    dataType: "json"
+    data:
+      q: sql
+  if success?
+    options.success = success
+  if error?
+    options.error = error
+  $.ajax options
+
+
+scraperwiki.tool.sql.meta = (success, error) ->
+  # get info about this tool's internal SQL database.
+  # [success] and [error] callbacks are optional,
+  # since this returns a jQuery deferred object on which
+  # you can chain .done() and .fail() handlers.
+  settings = scraperwiki.readSettings()
+  options =
+    url: "#{settings.source.url}/sql/meta"
+    type: "GET"
+    dataType: "json"
+  if success?
+    options.success = success
+  if error?
+    options.error = error
+  $.ajax options
+
+
+scraperwiki.tool.exec = (cmd, success, error) ->
+  # Execute a unix command inside this tool's box.
+  # [success] and [error] callbacks are optional,
+  # since this returns a jQuery deferred object on which
+  # you can chain .done() and .fail() handlers.
+  settings = scraperwiki.readSettings()
+  options =
+    url: "#{window.location.protocol}//#{window.location.host}/#{scraperwiki.box}/exec"
+    type: "POST"
+    dataType: "text"
+    data:
+      apikey: settings.source.apikey
+      cmd: cmd
+  if success?
+    options.success = success
+  if error?
+    options.error = error
+  $.ajax options
+
+
+scraperwiki.shellEscape = (command) ->
+  # useful for making variables "safe" for inclusion in exec commands.
+  "'#{command.replace(/'/g,"'\"'\"'")}'"
+
+
+
+
+# HERE BE DEPRECATED FUNCTIONS:
+
+
+scraperwiki.tool.pushSql = scraperwiki.dataset.installTool
+scraperwiki.tool.rename = scraperwiki.dataset.name
+scraperwiki.tool.getUrl = scraperwiki.tool.redirect = scraperwiki.url
+
+
+scraperwiki.sql = (sql, success, error) ->
+  settings = scraperwiki.readSettings()
+  # Points to the dataset box, when used from either the dataset or a view.
+  boxSettings = settings.target ? settings.source
+  options =
+    url: "#{boxSettings.url}/sql/"
+    type: "GET"
+    dataType: "json"
+    data:
+      q: sql
+  if success?
+    options.success = success
+  if error?
+    options.error = error
+  $.ajax options
+
+
+scraperwiki.sql.meta = (success, error) ->
+  settings = scraperwiki.readSettings()
+  # Points to the dataset box, when used from either the dataset or a view.
+  boxSettings = settings.target ? settings.source
+  options =
+    url: "#{boxSettings.url}/sql/meta"
+    type: "GET"
+    dataType: "json"
+  if success?
+    options.success = success
+  if error?
+    options.error = error
+  $.ajax options
+
+
+scraperwiki.exec = (cmd, success, error) ->
+  settings = scraperwiki.readSettings()
+  options =
+    url: "#{window.location.protocol}//#{window.location.host}/#{scraperwiki.box}/exec"
+    type: "POST"
+    dataType: "text"
+    data:
+      apikey: settings.source.apikey
+      cmd: cmd
+  if success?
+    options.success = success
+  if error?
+    options.error = error
+  $.ajax options


translator.coffee was added

translator.coffee was added

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/NightingaleStudio/exam.js.git/'


added giLocalStorage service

added giLocalStorage service

error: pathspec 'client/services/localStorage.coffee' did not match any file(s) known to git

--- client/services/localStorage.coffee
+++ client/services/localStorage.coffee
@@ -0,0 +1,16 @@
+angular.module('gi.util').factory 'giLocalStorage'
+, ['$window'
+, ($window) ->
+  get: (key) ->
+    if $window.localStorage[key]
+      cart = angular.fromJson($window.localStorage[key])
+      return JSON.parse(cart)
+    false
+
+  set: (key, val) ->
+    if not val?
+      $window.localStorage.removeItem(key)
+    else
+      $window.localStorage[key] = angular.toJson(val)
+    $window.localStorage[key]
+]