initial work on AniSprite class

initial work on AniSprite class

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

--- src/aniSprite.coffee
+++ src/aniSprite.coffee
@@ -0,0 +1,57 @@
+###
+aniSprite.coffee
+
+The Greenhorn Gaming Engine animated Sprite class
+###
+
+class AniCycle
+    #constructor
+    constructor: (data) ->
+        #throw errors if proper data isn't supplied
+        throw new Error "cycle name must be supplied" unless data.name?
+        throw new Error "start position must be supplied" unless data.start?
+        throw new Error "number of frames must be supplied" unless data.numFrames?
+
+        #extract data
+        @name = data.name
+        @start = data.start
+        @numFrames = data.numFrames
+
+class @AniSprite extends @Sprite
+    #constructor
+    constructor: (config = {}) ->
+        #add environment defaults to config,
+        #if the user has chosen to omit them
+        for key, value of env.ANISPRITE_DEFAULT_CONFIG
+            config[key] ?= value
+
+        #create the timer that will
+        #control the animation cycles
+        @_dis.cycle = new Array()
+        @_dis.timer = new Timer(off)
+
+        #push provided cycles onto the array
+        @_dis.cycles.push(new AniCycle(value)) for key, value of config when key.indexOf("cycle") is 0
+
+        #call Sprite constructor
+        super(config)
+
+        #return this
+        @
+
+    #getter
+    get: (what) ->
+        #add later
+
+    #setter
+    set: (what, to) ->
+        #add later
+
+    #changer
+    change: (what, step) ->
+        #add later
+
+    #update routines
+    _draw: ->
+        #add later
+#end class AniSprite


bug fix

bug fix

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


bug fix

bug fix


add experimental exception handler with code excerpts

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

--- src/exception-handler.coffee
+++ src/exception-handler.coffee
@@ -0,0 +1,122 @@
+
+
+'use strict'
+
+
+
+############################################################################################################
+CND                       = require 'cnd'
+rpr                       = CND.rpr
+badge                     = 'exception-handler'
+log                       = CND.get_logger 'plain',     badge
+debug                     = CND.get_logger 'debug',     badge
+info                      = CND.get_logger 'info',      badge
+warn                      = CND.get_logger 'warn',      badge
+alert                     = CND.get_logger 'alert',      badge
+help                      = CND.get_logger 'help',      badge
+urge                      = CND.get_logger 'urge',      badge
+whisper                   = CND.get_logger 'whisper',   badge
+echo                      = CND.echo.bind CND
+stackman                  = ( require 'stackman' )()
+# require                   'longjohn'
+FS                        = require 'fs'
+PATH                      = require 'path'
+
+# error = new Error('Oops!')
+# debug('^4461^');
+
+#-----------------------------------------------------------------------------------------------------------
+get_context = ( path, linenr ) ->
+  ### TAINT use stackman.sourceContexts() instead ###
+  try
+    lines     = ( FS.readFileSync path, { encoding: 'utf-8' } ).split '\n'
+    delta     = 1
+    first_idx = Math.max 0, linenr - 1 - delta
+    last_idx  = Math.min lines.length - 1, linenr - 1 + delta
+    R = ( "#{first_idx + idx + 1}  #{line}" for line, idx in lines[ first_idx .. last_idx ] )
+    R = R.join '\n'
+  catch error
+    throw error unless error.code is 'ENOENT'
+    return './.'
+  return R
+
+#-----------------------------------------------------------------------------------------------------------
+show_error_with_source_context = ( error ) ->
+  stackman.callsites error, ( error, callsites ) ->
+    throw error if error?
+    callsites.forEach ( callsite ) ->
+      path      = callsite.getFileName()
+      unless CND.isa_text path
+        debug '^3736^', rpr path
+      else
+        relpath   = PATH.relative process.cwd(), path
+        linenr    = callsite.getLineNumber()
+        echo CND.white "#{relpath} ##{linenr}:"
+        unless path.startsWith 'internal/'
+          source    = get_context path, linenr
+          echo CND.yellow source
+    return null
+  return null
+
+#-----------------------------------------------------------------------------------------------------------
+@exit_handler = ( exception ) ->
+  # debug '55567', rpr exception
+  print               = alert
+  message             = 'ROGUE EXCEPTION: ' + ( exception?.message ? "an unrecoverable condition occurred" )
+  if exception?.where?
+    message += '\n--------------------\n' + exception.where + '\n--------------------'
+  [ head, tail..., ]  = message.split '\n'
+  print CND.reverse ' ' + head + ' '
+  warn line for line in tail
+  ### TAINT should have a way to set exit code explicitly ###
+  debug '^55663^', exception
+  if exception?.stack?
+    show_error_with_source_context exception
+  else
+    whisper exception?.stack ? "(exception undefined, no stack)"
+  # setImmediate -> process.exit 1
+@exit_handler = @exit_handler.bind @
+
+# debug 'µ55531', __filename
+# debug 'µ55531', "app:", typeof app
+# check for process.type:
+# if process.type is 'renderer'
+# # if typeof app is 'undefined'
+#   process.on 'uncaughtException',  @exit_handler
+#   process.on 'unhandledRejection', @exit_handler
+# else
+#   urge "µ55531 using electron-unhandled"
+# ( require 'electron-unhandled' ) { showDialog: true, logger: @exit_handler, }
+
+# if process.type is 'renderer'
+#   window.addEventListener 'error', ( event ) =>
+#     event.preventDefault()
+#     warn 'µ44333', "error:", ( k for k of event )
+
+#   window.addEventListener 'unhandledrejection', ( event ) =>
+#     event.preventDefault()
+#     # warn 'µ44333', "unhandled rejection:", ( k for k of event )
+#     warn 'µ44333', "unhandled rejection:", event.reason?.message ? "(no message)"
+
+
+############################################################################################################
+if process.type is 'renderer'
+  window.addEventListener 'error', ( event ) =>
+    # event.preventDefault()
+    message = ( event.error?.message ? "(error without message)" ) + '\n' + ( event.error?.stack ? '' )[ ... 500 ]
+    OPS.log message
+    # @exit_handler event.error
+    OPS.open_devtools()
+    return true
+
+  window.addEventListener 'unhandledrejection', ( event ) =>
+    # event.preventDefault()
+    message = ( event.reason?.message ? "(error without message)" ) + '\n' + ( event.reason?.stack ? '' )[ ... 500 ]
+    OPS.log message
+    # @exit_handler event.reason
+    OPS.open_devtools()
+    return true
+else
+  process.on 'uncaughtException',  @exit_handler
+  process.on 'unhandledRejection', @exit_handler
+


a trailing semicolon only needs to be added if the source file does not have one already

--- src/fs_utils/generate.coffee
+++ src/fs_utils/generate.coffee
@@ -66,8 +66,8 @@
   debug "Concatenating #{files.map((_) -> _.path).join(', ')} to #{path}"
   files.forEach (file) ->
     root.add file.node
-    root.add ';' if type is 'javascript'
     data = if file.node.isIdentity then file.data else file.source
+    root.add ';' if type is 'javascript' and ';' isnt data.trim().substr -1
     root.setSourceContent file.node.source, data

   root.prepend definition(path, root.sourceContents) if type is 'javascript'


Add the Provider class.

Add the Provider 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/JoshuaToenyes/stout-core.git/'


Translate locales to Albanian (#840)

Translate locales to Albanian (#840)

* Translate locales to albanian in pivot.sq.coffee

* Replace locales.de with locales.sq in pivot.sq.coffee

error: pathspec 'locales/pivot.sq.coffee' did not match any file(s) known to git

--- locales/pivot.sq.coffee
+++ locales/pivot.sq.coffee
@@ -0,0 +1,55 @@
+callWithJQuery = (pivotModule) ->
+    if typeof exports is "object" and typeof module is "object" # CommonJS
+        pivotModule require("jquery")
+    else if typeof define is "function" and define.amd # AMD
+        define ["jquery"], pivotModule
+    # Plain browser env
+    else
+        pivotModule jQuery
+
+callWithJQuery ($) ->
+    nf = $.pivotUtilities.numberFormat
+    tpl = $.pivotUtilities.aggregatorTemplates
+
+    frFmt =    nf(thousandsSep: " ", decimalSep: ",")
+    frFmtInt = nf(digitsAfterDecimal: 0, thousandsSep: " ", decimalSep: ",")
+    frFmtPct = nf(digitsAfterDecimal: 1, scaler: 100, suffix: "%", thousandsSep: " ", decimalSep: ",")
+
+    $.pivotUtilities.locales.sq =
+        localeStrings:
+            renderError: "Ka ndodhur një gabim gjatë shfaqjes së rezultateve të PivotTable."
+            computeError: "Ka ndodhur një gabim gjatë llogaritjes së rezultateve të PivotTable."
+            uiRenderError: "Ka ndodhur një gabim gjatë shfaqjes së ndërfaqes së PivotTable."
+            selectAll: "Përzgjedh të gjitha"
+            selectNone: "Mos përzgjedh asnjërën"
+            tooMany: "(shumë për t'u listuar)"
+            filterResults: "Filtro vlerat"
+            totals: "Totalet"
+            vs: "kundër"
+            by: "për"
+
+        aggregators:
+            "Numëro":                       tpl.count(frFmtInt)
+            "Numëro vlerat unike":     tpl.countUnique(frFmtInt)
+            "Listo vlerat unike":      tpl.listUnique(", ")
+            "Shuma":                        tpl.sum(frFmt)
+            "Shuma si numër i plotë":			tpl.sum(frFmtInt)
+            "Mesatarja":                 tpl.average(frFmt)
+            "Minimumi":                      tpl.min(frFmt)
+            "Maksimumi":                      tpl.max(frFmt)
+            "Shuma mbi shumë":             tpl.sumOverSum(frFmt)
+            "80% kufiri i sipërm":               tpl.sumOverSumBound80(true, frFmt)
+            "80% kufiri i poshtëm":        		tpl.sumOverSumBound80(false, frFmt)
+            "Shuma si thyesë e totalit":  tpl.fractionOf(tpl.sum(),   "total", frFmtPct)
+            "Shuma si thyesë e rreshtave":   tpl.fractionOf(tpl.sum(),   "row",   frFmtPct)
+            "Shuma si thyesë e kolonave":  tpl.fractionOf(tpl.sum(),   "col",   frFmtPct)
+            "Numërimi si thyesë e totalit": tpl.fractionOf(tpl.count(), "total", frFmtPct)
+            "Numërimi si thyesë e rreshtave":  tpl.fractionOf(tpl.count(), "row",   frFmtPct)
+            "Numërimi si thyesë e kolonave": tpl.fractionOf(tpl.count(), "col",   frFmtPct)
+
+        renderers:
+            "Tabela":                      $.pivotUtilities.renderers["Table"]
+            "Tabela me diagram vertikal":   $.pivotUtilities.renderers["Table Barchart"]
+            "Heatmap":                      $.pivotUtilities.renderers["Heatmap"]
+            "Heatmap për rresht":            $.pivotUtilities.renderers["Row Heatmap"]
+            "Heatmap për kolonë":           $.pivotUtilities.renderers["Col Heatmap"]


Saving embeded objects is now working

Saving embeded objects is now working

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


Adding in tctransit.coffee

Adding in tctransit.coffee

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

--- src/scripts/tctransit.coffee
+++ src/scripts/tctransit.coffee
@@ -0,0 +1,68 @@
+# Description:
+#   Allows users to check MetroTransit times in the TwinCities
+#   metrotransit.herokuapp.com
+#
+# Dependencies:
+#   none
+#
+# Configuration:
+#   none
+#
+# Commands:
+#   hubot when is the next <route #> going <north/south/east/west> from <4 letter stop code OR street name>
+#
+# Author:
+#   pyro2927
+
+module.exports = (robot) ->
+  robot.respond /when is the next (.*) going (.*) from (.*)/i, (msg) ->
+    route = msg.match[1]
+    direction = msg.match[2]
+    dirNum = 4
+    if direction.toLowerCase() == "east"
+      dirNum = 2
+    else if direction.toLowerCase() == "west"
+      dirNum = 3
+    else if direction.toLowerCase() == "south"
+      dirNum = 1
+
+    stop = msg.match[3]
+    if (stop.length != 4)
+      TransitAPI.search_stop_codes(route, dirNum, stop, msg)
+    else
+      TransitAPI.fetch_next_stop(route, dirNum, stop, msg)
+
+
+class TransitAPI
+  constructor: ->
+
+  fetch_next_stop: (route, dirNum, stopCode, msg) =>
+    msg.http('http://metrotransit.herokuapp.com/nextTrip?route=' + route + '&direction=' + dirNum + '&stop=' + stopCode)
+      .get() (err, res, body) =>
+        stops = JSON.parse(body)
+        if stops.count <= 0
+          msg.send "No next stops"
+          return
+        time = stops[0].time
+        if time.match(/Min$/)
+          time = "in " + time
+        else if time.match(/:/)
+          time = "at " + time
+        msg.send "The next " + route + " at " + stops[0].stop_name + " is " + time
+
+  search_stop_codes: (route, dirNum, stopName, msg) =>
+    msg.http('http://metrotransit.herokuapp.com/stops?route=' + route + '&direction=' + dirNum)
+      .get() (err, res, body) =>
+        stops = JSON.parse(body)
+        # too bad, no stops found for this
+        if stops.count <= 0
+          msg.send "No stops available for the " + route + " going that direction"
+          return
+        # see if any of our stops match
+        for stop in stops
+          if stop.name.toLowerCase().indexOf(stopName.toLowerCase()) > -1
+            this.fetch_next_stop(route, dirNum, stop.key, msg)
+            return
+        msg.send "No stops found with name: " + stopName
+
+TransitAPI = new TransitAPI()


Nodejs Web Server Tests: add impersonate.test file

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


Display a message when goals are saved.

Display a message when goals are saved.

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


app: create ProfileFetcherMixin

app: create ProfileFetcherMixin

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

--- client/app/lib/components/profile/profilefetchermixin.coffee
+++ client/app/lib/components/profile/profilefetchermixin.coffee
@@ -0,0 +1,19 @@
+React = require 'kd-react'
+helper = require './helper'
+fetchAccount = require 'app/util/fetchAccount'
+
+module.exports =
+  getInitialState: ->
+    return {
+      account: @props.account or helper.defaultAccount()
+    }
+
+  componentDidMount: ->
+    if @props.origin
+      fetchAccount @props.origin, (err, account) =>
+        @setState { err, account }
+
+
+  renderChildren: ->
+    React.Children.map @props.children, (child) =>
+      React.cloneElement child, { account: @state.account }


Handle default value of [] for clonables.

--- core/htdocs_source/src/pods/oxisection-form/component.coffee
+++ core/htdocs_source/src/pods/oxisection-form/component.coffee
@@ -14,7 +14,8 @@
             if Em.isArray clonable.value
                 index = fields.indexOf clonable
                 fields.removeAt index
-                clones = clonable.value.forEach (value, i) ->
+                values = if clonable.value.length then clonable.value else [""]
+                clones = values.forEach (value, i) ->
                     clone = Em.copy clonable
                     clone.value = value
                     fields.insertAt index+i, clone


minor

minor


HAHA HOLY SHIT WHY AM I SO DUMB

HAHA HOLY SHIT WHY AM I SO DUMB

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


add destiny.coffee script

add destiny.coffee script

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

--- src/scripts/destiny.coffee
+++ src/scripts/destiny.coffee
@@ -0,0 +1,15 @@
+# Is the day ?
+#
+# is the <action> day ? - Returns if it's the day for your action.
+#
+module.exports = (robot) ->
+  robot.respond /is the (\w+) day \?/i, (msg) ->
+    action = msg.match[1]
+    nbDay = Math.floor(new Date().getTime() / 1000 / 86400)
+    actionHash = action.length + action.charCodeAt(0) + action.charCodeAt(action.length - 1)
+    destiny = Math.cos(nbDay + actionHash) + 1
+    limit = (Math.sin(actionHash) + 1) / 2
+    if destiny > limit
+      msg.send "Sorry, it's not " + action + " day. But try tomorrow..."
+    else
+      msg.send "Yes, it's the " + action + " day !"


update

update

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


Added exportable module test

Added exportable module test

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

--- test/node/exportable1.coffee
+++ test/node/exportable1.coffee
@@ -0,0 +1,18 @@
+udefine = require '../../dist/udefine'
+{expect} = require 'chai'
+
+describe 'udefine commonjs exportable', ->
+  it 'module.exports', ->
+
+    udefine 'export1', ->
+      a: 5
+      b: 4
+      c: 3
+
+    expect(module.exports).to.be.a('object')
+    expect(module.exports.a).to.be.a('number')
+    expect(module.exports.b).to.be.a('number')
+    expect(module.exports.c).to.be.a('number')
+    expect(module.exports.a).to.equal(5)
+    expect(module.exports.b).to.equal(4)
+    expect(module.exports.c).to.equal(3)


Updated janky include_flow skip levels.

Updated janky include_flow skip levels.

--- app/views/play/level/tome/tome_view.coffee
+++ app/views/play/level/tome/tome_view.coffee
@@ -71,7 +71,7 @@
       @cast()
       console.warn "Warning: There are no Programmable Thangs in this level, which makes it unplayable."
     delete @options.thangs
-
+
   onNewWorld: (e) ->
     thangs = _.filter e.world.thangs, 'isSelectable'
     programmableThangs = _.filter thangs, 'isProgrammable'
@@ -120,7 +120,7 @@
         @thangSpells[thang.id].push spellKey
         unless method.cloneOf
           skipProtectAPI = @getQueryVariable "skip_protect_api", not @options.ladderGame
-          skipFlow = @getQueryVariable "skip_flow", @options.levelID is 'brawlwood' or @options.levelID is 'resource-gathering-multiplayer'
+          skipFlow = @getQueryVariable "skip_flow", (@options.levelID in ['brawlwood', 'greed', 'gold-rush'])
           spell = @spells[spellKey] = new Spell programmableMethod: method, spellKey: spellKey, pathComponents: pathPrefixComponents.concat(pathComponents), session: @options.session, supermodel: @supermodel, skipFlow: skipFlow, skipProtectAPI: skipProtectAPI, worker: @worker
     for thangID, spellKeys of @thangSpells
       thang = world.getThangByID thangID


graph: added  fetchFromNeo4j method

graph: added  fetchFromNeo4j method


social/group: create a session for unregistered user

Signed-off-by: Umut Sirin <4055abbc0e40a1254e715b952ccd414607e0b365@gmail.com>

--- workers/social/lib/social/models/group/index.coffee
+++ workers/social/lib/social/models/group/index.coffee
@@ -397,6 +397,7 @@
   @joinUser = secure (client, options, callback) ->

     JUser = require '../user'
+    JSession = require '../session'

     { username, email, password, slug, alreadyMember } = options

@@ -432,9 +433,15 @@
         if alreadyMember and not user
           return callback getError { message: 'Unknown user name' }, 400

-        if user?
-        then JUser.login client.sessionToken, userData, joinGroupCallback
-        else JUser.convert client, userData, joinGroupCallback
+        JSession.createSession { group: slug }, (err, { session, account }) ->
+          return callback getError err  if err
+
+          client.connection.delegate = account
+          client.sessionToken = session.clientId
+
+          if user?
+          then JUser.login client.sessionToken, userData, joinGroupCallback
+          else JUser.convert client, userData, joinGroupCallback

   @create = (client, groupData, owner, callback) ->


rollbar: minor fix

rollbar: minor fix

--- workers/social/lib/social/render/scriptblock.coffee
+++ workers/social/lib/social/render/scriptblock.coffee
@@ -4,7 +4,7 @@
     var _rollbarParams = {
       "server.environment": "production",
       "client.javascript.source_map_enabled": true,
-      "client.javascript.code_version": #{KONFIG.version},
+      "client.javascript.code_version": "#{KONFIG.version}",
       "client.javascript.colno_default_one": true
     };
     _rollbarParams["notifier.snippet_version"] = "2"; var _rollbar=["713a5f6ab23c4ab0abc05494ef7bca55", _rollbarParams]; var _ratchet=_rollbar;


get user sessions before publishing presence

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


kd overlay view implemented

kd overlay view implemented


Deal with key map conflicts

Deal with key map conflicts

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

--- keymap.cson
+++ keymap.cson
@@ -0,0 +1,2 @@
+'atom-workspace':
+  'alt-t': 'atom-terminal:open'


Improvements to buildSchoolGraph to open a spreadsheet

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/bsmr-x-script/codecombat.git/'


simplifies the tests

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


Add hubot script

Add hubot script

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

--- scripts/hubot.coffee
+++ scripts/hubot.coffee
@@ -0,0 +1,14 @@
+# DESCRIPTION:
+#   hubot の情報を表示する。
+#
+# COMMANDS:
+#   hubot version - 現在のバージョンを表示
+
+Path = require 'path'
+
+module.exports = (robot) ->
+
+  pkg = require Path.join __dirname, '..', 'package.json'
+
+  robot.respond /version/i, (msg) ->
+    msg.send "#{pkg.version} (hubot: #{robot.version})"


Change sending url using Array

Change sending url using Array

Because ordering

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/opengallery/og-bot.git/'


Change some of the default config

Change some of the default config

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


TMS-2688 Fix typo

TMS-2688 Fix typo

https://koding.atlassian.net/browse/TMS-2688


Create latex.coffee

Create latex.coffee

Latex enabled

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

--- scripts/latex.coffee
+++ scripts/latex.coffee
@@ -0,0 +1,21 @@
+# Description:
+# Convert LaTeX text into an image
+#
+# Dependencies:
+# None
+#
+# Configuration:
+# None
+#
+# Commands:
+# hubot latex text - The image for this text
+#
+# Author:
+# Endle
+
+module.exports = (robot) ->
+  robot.respond /latex\s+(.*)/i, (msg) ->
+    tex = encodeURIComponent "#{msg.match[1]}"
+    link = "http://latex.codecogs.com/gif.latex?#{tex}"
+
+    msg.send "#{link}"


stub out error view

stub out error view

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


Removed some debugging.

Removed some debugging.

--- useragent-examples/useragent-generic-javascript/src/main/webapp/coffee/Link.coffee
+++ useragent-examples/useragent-generic-javascript/src/main/webapp/coffee/Link.coffee
@@ -23,8 +23,6 @@
         @successHandler = (model, textStatus, jqXHR) => new ResourceView({rel: 'self', href: jqXHR.getResponseHeader('Location'), method: 'GET'})

   cloneModel: (model)->
-    alert("what is this clone used for?")
-    debugger
     clone = {}
     $.extend true, clone, model
     if clone.links? then delete clone.links


Add basic gulpfile

Add basic gulpfile

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/chuckeles/chuckeles.github.io.git/'


Add brackets

Add brackets

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


:lipstick: Fix ugly test

:lipstick: Fix ugly test

--- spec/display-buffer-spec.coffee
+++ spec/display-buffer-spec.coffee
@@ -1051,8 +1051,8 @@
       expect(displayBuffer.decorationsForScreenRowRange(2, 3)[marker.id][0]).toBe decoration

       decoration.destroy()
-      expect(!!displayBuffer.decorationsForScreenRowRange(2, 3)[marker.id]).toBeFalsy()
-      expect(!!displayBuffer.decorationForId(decoration.id)).toBeFalsy()
+      expect(displayBuffer.decorationsForScreenRowRange(2, 3)[marker.id]).not.toBeDefined()
+      expect(displayBuffer.decorationForId(decoration.id)).not.toBeDefined()

     it "will not fail if the decoration is removed twice", ->
       decoration.destroy()


new form service, should be available globally and avoid emit/broadcasts/on ...

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

--- src/coffee/services/registration.coffee
+++ src/coffee/services/registration.coffee
@@ -0,0 +1,102 @@
+##
+## registration.coffee
+##
+## Created by Frederic DELBOS - fred.delbos@gmail.com on Dec  2 2013.
+## This file is subject to the terms and conditions defined in
+## file 'LICENSE.txt', which is part of this source code package.
+##
+
+angular.module('CoolFormServices').
+  factory('registrationService', (validators) ->
+
+    return ()->
+
+      fields = {}
+      errors ={}
+      values = {}
+      errorHandlers = {}
+      okHandlers = {}
+      # dependancies = {}
+
+      # setDependancies = (field) ->
+      #   if field.dependancies?
+      #     for dep in field.dependancies
+      #       if !dependancies[dep]? then dependancies[dep] = []
+      #       dependancies[dep].push(field.name)
+
+      setFields = (pages) ->
+        p = 0
+        for page in pages
+          for line in page.lines
+            for field in line.fields
+              fields[field.name] = field
+              # setDependancies(field)
+          p += 1
+
+      sendError = (fieldName, error) ->
+        if !errorHandlers[fieldName]? then return
+        for handler in errorHandlers[fieldName]
+          handler(error)
+
+      sendOk = (fieldName) ->
+        if !okHandlers[fieldName]? then return
+        for handler in okHandlers[fieldName]
+          handler()
+
+      removeError = (fieldName) ->
+        delete errors[fieldName]
+        # if dependancies[fieldName]?
+        #   for dep in dependancies[fieldName]
+        #     removeError(dep)
+        sendOk(fieldName)
+
+      validateField = (fieldName) ->
+        field = fields[fieldName]
+        if field.validation?
+          for rule in field.validation
+            if validators[rule.validator]?
+              if validators[rule.validator](fieldName, values, rule) is false
+                errors[fieldName] = rule.options.message
+                sendError(fieldName, rule.options.message)
+                return false
+        removeError(fieldName)
+        return true
+
+      validateFields = (fieldList) ->
+        result = true
+        for field in fieldList
+          if validateField(field) is false then result = false
+        result
+
+      validateAllFields = -> validateFields(Object.keys(fields))
+
+      valueChange = (fieldName, value) ->
+        values[fieldName] = value
+        removeError(fieldName)
+
+      addHandler = (field, fn, list) ->
+        if !list[field]? then list[field] = []
+        if fn? then list[field].push(fn)
+
+      registerController = (controllerScope, form) ->
+        setFields(form.pages)
+
+      watchFieldValidation = (fieldName, onOk, onError) ->
+        if onOk? then addHandler(fieldName, onOk, okHandlers)
+        if onError? then addHandler(fieldName, onError, errorHandlers)
+
+      registerField = (fieldName, onOk, onError) ->
+        watchFieldValidation(fieldName, onOk, onError)
+        return (value) ->
+          valueChange(fieldName, value)
+
+      services =
+        registerController: registerController
+        registerField: registerField
+        validateField: validateField
+        validateFields: validateFields
+        validateAllFields: validateAllFields
+        watchFieldValidation: watchFieldValidation
+
+      return services
+  )


Dispatchers with prototypes

Dispatchers with prototypes

--- src/Bacon.coffee
+++ src/Bacon.coffee
@@ -917,123 +917,131 @@
   justInitValue.concat(stream).toProperty()

 class Dispatcher
-  constructor: (subscribe, handleEvent) ->
-    subscribe ?= -> nop
-    subscriptions = []
-    queue = []
-    pushing = false
-    ended = false
-    @hasSubscribers = -> subscriptions.length > 0
-    prevError = undefined
-    unsubscribeFromSource = nop
-    removeSub = (subscription) ->
-      subscriptions = _.without(subscription, subscriptions)
-    pushIt = (event) ->
-      unless pushing
-        return if event == prevError
-        prevError = event if event.isError()
-        success = false
-        try
-          pushing = true
-          tmp = subscriptions
-          for sub in tmp
-            reply = sub.sink event
-            removeSub sub if reply == Bacon.noMore or event.isEnd()
-          success = true
-        finally
-          pushing = false
-          queue = [] unless success # ditch queue in case of exception to avoid unexpected behavior
+  constructor: (@_subscribe, @_handleEvent) ->
+    @subscriptions = []
+    @queue = []
+    @pushing = false
+    @ended = false
+    @prevError = undefined
+    @unsubscribeFromSource = nop
+
+  hasSubscribers: ->
+    @subscriptions.length > 0
+
+  removeSub: (subscription) =>
+    @subscriptions = _.without(subscription, @subscriptions)
+
+  push: (event) =>
+    UpdateBarrier.inTransaction event, this, @pushIt, [event]
+
+  pushIt: (event) ->
+    unless @pushing
+      return if event == @prevError
+      @prevError = event if event.isError()
+      success = false
+      try
+        @pushing = true
+        tmp = @subscriptions
+        for sub in tmp
+          reply = sub.sink event
+          @removeSub sub if reply == Bacon.noMore or event.isEnd()
         success = true
-        while queue.length
-          event = queue.shift()
-          @push event
-        if @hasSubscribers()
-          Bacon.more
-        else
-          unsubscribeFromSource()
-          Bacon.noMore
+      finally
+        @pushing = false
+        @queue = [] unless success # ditch queue in case of exception to avoid unexpected behavior
+      success = true
+      while @queue.length
+        event = @queue.shift()
+        @push event
+      if @hasSubscribers()
+        Bacon.more
       else
-        queue.push(event)
-        Bacon.more
-    @push = (event) =>
-      UpdateBarrier.inTransaction event, this, pushIt, [event]
-    handleEvent ?= (event) -> @push event
-    @handleEvent = (event) =>
-      if event.isEnd()
-        ended = true
-      handleEvent.apply(this, [event])
-    @subscribe = (sink) =>
-      if ended
-        sink end()
-        nop
+        @unsubscribeFromSource()
+        Bacon.noMore
+    else
+      @queue.push(event)
+      Bacon.more
+
+  handleEvent: (event) =>
+    if event.isEnd()
+      @ended = true
+
+    if @_handleEvent
+      @_handleEvent(event)
+    else
+      @push event
+
+  subscribe: (sink) =>
+    if @ended
+      sink end()
+      nop
+    else
+      assertFunction sink
+      subscription = { sink: sink }
+      @subscriptions.push(subscription)
+      if @subscriptions.length == 1
+        unsubSrc = @_subscribe @handleEvent
+        @unsubscribeFromSource = ->
+          unsubSrc()
+          @unsubscribeFromSource = nop
+      assertFunction @unsubscribeFromSource
+      =>
+        @removeSub subscription
+        @unsubscribeFromSource() unless @hasSubscribers()
+
+class PropertyDispatcher extends Dispatcher
+  constructor: (@property, subscribe, handleEvent) ->
+    super(subscribe, handleEvent)
+    @current = None
+    @currentValueRootId = undefined
+    @propertyEnded = false
+
+  push: (event) =>
+    if event.isEnd()
+      @propertyEnded = true
+    if event.hasValue()
+      @current = new Some(event)
+      @currentValueRootId = UpdateBarrier.currentEventId()
+    super(event)
+
+  maybeSubSource: (sink, reply) ->
+    if reply == Bacon.noMore
+      nop
+    else if @propertyEnded
+      sink end()
+      nop
+    else
+      Dispatcher::subscribe.apply(this, [sink])
+
+  subscribe: (sink) =>
+    initSent = false
+    # init value is "bounced" here because the base Dispatcher class
+    # won't add more than one subscription to the underlying observable.
+    # without bouncing, the init value would be missing from all new subscribers
+    # after the first one
+    reply = Bacon.more
+
+    if @current.isDefined and (@hasSubscribers() or @propertyEnded)
+      # should bounce init value
+      dispatchingId = UpdateBarrier.currentEventId()
+      valId = @currentValueRootId
+      if !@propertyEnded and valId and dispatchingId and dispatchingId != valId
+        # when subscribing while already dispatching a value and this property hasn't been updated yet
+        # we cannot bounce before this property is up to date.
+        #console.log "bouncing with possibly stale value", event.value(), "root at", valId, "vs", dispatchingId
+        UpdateBarrier.whenDoneWith @property, =>
+          if @currentValueRootId == valId
+            sink initial(@current.get().value())
+        # the subscribing thing should be defered
+        @maybeSubSource(sink, reply)
       else
-        assertFunction sink
-        subscription = { sink: sink }
-        subscriptions.push(subscription)
-        if subscriptions.length == 1
-          unsubSrc = subscribe @handleEvent
-          unsubscribeFromSource = ->
-            unsubSrc()
-            unsubscribeFromSource = nop
-        assertFunction unsubscribeFromSource
-        =>
-          removeSub subscription
-          unsubscribeFromSource() unless @hasSubscribers()
-
-class PropertyDispatcher extends Dispatcher
-  constructor: (p, subscribe, handleEvent) ->
-    super(subscribe, handleEvent)
-    current = None
-    currentValueRootId = undefined
-    push = @push
-    subscribe = @subscribe
-    ended = false
-    @push = (event) =>
-      if event.isEnd()
-        ended = true
-      if event.hasValue()
-        current = new Some(event)
-        currentValueRootId = UpdateBarrier.currentEventId()
-        #console.log "push", event.value()
-      push.apply(this, [event])
-    @subscribe = (sink) =>
-      initSent = false
-      # init value is "bounced" here because the base Dispatcher class
-      # won't add more than one subscription to the underlying observable.
-      # without bouncing, the init value would be missing from all new subscribers
-      # after the first one
-      reply = Bacon.more
-
-      maybeSubSource = ->
-        if reply == Bacon.noMore
-          nop
-        else if ended
-          sink end()
-          nop
-        else
-          subscribe.apply(this, [sink])
-
-      if current.isDefined and (@hasSubscribers() or ended)
-        # should bounce init value
-        dispatchingId = UpdateBarrier.currentEventId()
-        valId = currentValueRootId
-        if !ended and valId and dispatchingId and dispatchingId != valId
-          # when subscribing while already dispatching a value and this property hasn't been updated yet
-          # we cannot bounce before this property is up to date.
-          #console.log "bouncing with possibly stale value", event.value(), "root at", valId, "vs", dispatchingId
-          UpdateBarrier.whenDoneWith p, ->
-            if currentValueRootId == valId
-              sink initial(current.get().value())
-          # the subscribing thing should be defered
-          maybeSubSource()
-        else
-          #console.log "bouncing value immediately"
-          UpdateBarrier.inTransaction undefined, this, (->
-            reply = sink initial(current.get().value())
-          ), []
-          maybeSubSource()
-      else
-        maybeSubSource()
+        #console.log "bouncing value immediately"
+        UpdateBarrier.inTransaction(undefined, this, (->
+          reply = sink initial(@current.get().value())
+        ), [])
+        @maybeSubSource(sink, reply)
+    else
+      @maybeSubSource(sink, reply)

 class Bus extends EventStream
   constructor: ->


fixed cached detail transition

fixed cached detail transition

--- src/coffeescripts/Detail.coffee
+++ src/coffeescripts/Detail.coffee
@@ -199,7 +199,13 @@
           $detail?.find("#detailPending").spin false
     else
       LoggrUtil.log 'Found detail in cache.'
-      @renderDetail detail, $detail
+
+      # This hack is needed in order to show the transition.
+      $detail?.find("#detailPending").spin "small", "white"
+      setTimeout =>
+        #Model.setDetail detail
+        $detail?.find("#detailPending").spin false
+      , 1

   # `json` Contact, Account, ...
   # `$detail` JQuery detail div


[CoffeeScript] is undefined.

[CoffeeScript] is undefined.

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

--- CoffeeScript/undefined.coffee
+++ CoffeeScript/undefined.coffee
@@ -0,0 +1 @@
+someValue is undefined // compiled to => someValue === void 0


First commit.

First commit.

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

--- component.coffee
+++ component.coffee
@@ -0,0 +1,28 @@
+class $blab.Component
+
+    constructor: (@spec, sheet, file) ->
+
+        if @spec.sheetIds
+            @sheet = (sheet[id] for id in @spec.sheetIds)
+        else
+            @sheet = sheet[@spec.id]
+
+        blockType = @constructor.name
+        blockId = "#{blockType}-#{@spec.id}"
+
+        container = $("##{@spec.containerId}")
+        container.append("
")
+        @block = container.children("##{blockId}")
+
+        @block.append("
")
+        @main = @block.children(".main")
+
+        @block.css("position", "absolute")
+        @block.css("left", @spec.x)
+        @block.css("top", @spec.y)
+
+    update: ->
+
+    stringify: ->
+        JSON.stringify(@spec)
+


Correct coalesce operator

Correct coalesce operator

--- resources/assets/coffee/_classes/tooltip-default.coffee
+++ resources/assets/coffee/_classes/tooltip-default.coffee
@@ -31,7 +31,7 @@

     el._tooltip = true

-    at = el.getAttribute('data-tooltip-position') || 'top center'
+    at = el.getAttribute('data-tooltip-position') ? 'top center'

     my = switch at
       when 'top center' then 'bottom center'


bug fix to cloning dedicated iops rds instances

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


Added a payment-received HipChat notification.

--- server/payments/payment_handler.coffee
+++ server/payments/payment_handler.coffee
@@ -17,13 +17,13 @@
     gems: 5000
     id: 'gems_5'
   }
-
+
   'gems_10': {
     amount: 999
     gems: 11000
     id: 'gems_10'
   }
-
+
   'gems_20': {
     amount: 1999
     gems: 25000
@@ -43,7 +43,7 @@
     payment.set 'recipient', req.user._id
     payment.set 'created', new Date().toISOString()
     payment
-
+
   post: (req, res) ->
     appleReceipt = req.body.apple?.rawReceipt
     appleTransactionID = req.body.apple?.transactionID
@@ -51,46 +51,46 @@
     stripeToken = req.body.stripe?.token
     stripeTimestamp = parseInt(req.body.stripe?.timestamp)
     productID = req.body.productID
-
+
     if not (appleReceipt or (stripeTimestamp and productID))
       return @sendBadInputError(res, 'Need either apple.rawReceipt or stripe.timestamp and productID')
-
+
     if stripeTimestamp and not productID
       return @sendBadInputError(res, 'Need productID if paying with Stripe.')

     if stripeTimestamp and (not stripeToken) and (not user.get('stripeCustomerID'))
       return @sendBadInputError(res, 'Need stripe.token if new customer.')
-
+
     if appleReceipt
       if not appleTransactionID
         return @sendBadInputError(res, 'Apple purchase? Need to specify which transaction.')
       @handleApplePaymentPost(req, res, appleReceipt, appleTransactionID, appleLocalPrice)
-
+
     else
       @handleStripePaymentPost(req, res, stripeTimestamp, productID, stripeToken)
-
-
+
+
   #- Apple payments
-
+
   handleApplePaymentPost: (req, res, receipt, transactionID, localPrice) ->
     formFields = { 'receipt-data': receipt }
-
-    #- verify receipt with Apple
-
+
+    #- verify receipt with Apple
+
     verifyReq = request.post({url: config.apple.verifyURL, json: formFields}, (err, verifyRes, body) =>
       if err or not body?.receipt?.in_app or (not body?.bundle_id is 'com.codecombat.CodeCombat')
         console.warn 'apple receipt error?', err, body
         @sendBadInputError(res, 'Unable to verify Apple receipt.')
         return
-
+
       transaction = _.find body.receipt.in_app, { transaction_id: transactionID }
-      return @sendBadInputError(res, 'Invalid transactionID.') unless transaction
-
+      return @sendBadInputError(res, 'Invalid transactionID.') unless transaction
+
       #- Check existence
       transactionID = transaction.transaction_id
       criteria = { 'ios.transactionID': transactionID }
       Payment.findOne(criteria).exec((err, payment) =>
-
+
         if payment
           unless payment.get('recipient').equals(req.user._id)
             return @sendForbiddenError(res)
@@ -119,17 +119,18 @@
           return @sendDatabaseError(res, err) if err
           @incrementGemsFor(req.user, product.gems, (err) =>
             return @sendDatabaseError(res, err) if err
+            @sendPaymentHipChatMessage user: req.user, payment: payment
             @sendCreated(res, @formatEntity(req, payment))
           )
         )
       )
     )

-
+
   #- Stripe payments
-
+
   handleStripePaymentPost: (req, res, timestamp, productID, token) ->
-
+
     # First, make sure we save the payment info as a Customer object, if we haven't already.
     if not req.user.get('stripeCustomerID')
       stripe.customers.create({
@@ -145,10 +146,10 @@
         (err) =>
           return @sendDatabaseError(res, err)
       )
-
+
     else
       @beginStripePayment(req, res, timestamp, productID)
-
+

   beginStripePayment: (req, res, timestamp, productID) ->
     product = products[productID]
@@ -168,29 +169,30 @@
         )
       )
     ],
-
+
       ((err, results) =>
-        return @sendDatabaseError(res, err) if err
+        return @sendDatabaseError(res, err) if err
         [payment, charge] = results
-
+
         if not (payment or charge)
           # Proceed normally from the beginning
           @chargeStripe(req, res, payment, product)
-
+
         else if charge and not payment
           # Initialized Payment. Start from charging.
           @recordStripeCharge(req, res, payment, product, charge)
-
+
         else
           # Charged Stripe and recorded it. Recalculate gems to make sure credited the purchase.
           @recalculateGemsFor(req.user, (err) =>
               return @sendDatabaseError(res, err) if err
+              @sendPaymentHipChatMessage user: req.user, payment: payment
               @sendSuccess(res, @formatEntity(req, payment))
           )
       )
     )

-
+
   chargeStripe: (req, res, payment, product) ->
     stripe.charges.create({
       amount: product.amount
@@ -206,7 +208,7 @@
     }).then(
       # success case
       ((charge) => @recordStripeCharge(req, res, payment, product, charge)),
-
+
       # error case
       ((err) =>
         if err.type in ['StripeCardError', 'StripeInvalidRequestError']
@@ -214,8 +216,8 @@
         else
           @sendDatabaseError(res, 'Error charging card, please retry.'))
     )
-
-
+
+
   recordStripeCharge: (req, res, payment, product, charge) ->
     return @sendError(res, 500, 'Fake db error for testing.') if req.body.breakAfterCharging
     payment = @makeNewInstance(req)
@@ -241,9 +243,9 @@
       )
     )

-
+
   #- Incrementing/recalculating gems
-
+
   incrementGemsFor: (user, gems, done) ->
     purchased = _.clone(user.get('purchased'))
     if not purchased?.gems
@@ -251,10 +253,10 @@
       purchased.gems = gems
       user.set('purchased', purchased)
       user.save((err) -> done(err))
-
+
     else
       user.update({$inc: {'purchased.gems': gems}}, {}, (err) -> done(err))
-
+
   recalculateGemsFor: (user, done) ->

     Payment.find({recipient: user._id}).select('gems').exec((err, payments) ->
@@ -264,7 +266,14 @@
       purchased.gems = gems
       user.set('purchased', purchased)
       user.save((err) -> done(err))
-
-    )
-
+
+    )
+
+  sendPaymentHipChatMessage: (options) ->
+    try
+      message = "#{options.user?.get('name')} bought #{options.payment?.get('amount')} via #{options.payment?.get('service'}."
+      hipchat.sendHipChatMessage message
+    catch e
+      log.error "Couldn't send HipChat message on payment because of error: #{e}"
+
 module.exports = new PaymentHandler()


reusing database for now

reusing database for now


:shirt: Use skinny arrow for afterEach

:shirt: Use skinny arrow for afterEach

--- spec/text-editor-presenter-spec.coffee
+++ spec/text-editor-presenter-spec.coffee
@@ -2422,7 +2422,7 @@
         beforeEach ->
           customGutter = editor.addGutter({name: 'test-gutter', priority: -1, visible: true})

-        afterEach =>
+        afterEach ->
           customGutter.destroy()

         describe ".scrollHeight", ->


Fix verification expiry time.

Fix verification expiry time.

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


Work on navbar

Work on navbar

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


Social: on exception, do not continue, return

--- servers/lib/server/google_callback.coffee
+++ servers/lib/server/google_callback.coffee
@@ -57,7 +57,7 @@
       try
         tokenInfo = JSON.parse rawResp
       catch e
-        redirectOauth 'Error getting access token', req, res, { provider }
+        return redirectOauth 'Error getting access token', req, res, { provider }

       { access_token, refresh_token } = tokenInfo
       if access_token


Add check to determine if "name" is configurable.

In some pre ES6 implementations, the Function.name property is not
"configurable" and thus cannot be changed. This adds a check to
determine if the name can be changed.

See https://mzl.la/1qATTjN

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/JoshuaToenyes/stout-core.git/'


Cleanup: remove deprecated projects file

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


feat(connector): added connector class

feat(connector): added connector class

this handles all future API connectors, which for now is only jquery.rest

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

--- src/connector.coffee
+++ src/connector.coffee
@@ -0,0 +1,18 @@
+class Connector
+  constructor: (base = '/api/', @type = 'jquery.rest') ->
+    @connector = new $.RestClient base,
+      stripTrailingSlash: true
+      methodOverride:     true
+
+  get: (main_api) =>
+    return @connector[main_api]
+
+  init: (resource) =>
+    @connector.add resource unless @connector[resource]?
+
+  add_apis_to: (sub_apis, main_api) =>
+    for name, data of sub_apis
+      @connector[main_api].add name + 's' unless @connector[main_api][name + 's']
+
+
+module.exports = Connector if module?


fixed zoom bug

fixed zoom 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/ChHeLeJa/SpaceTrader.git/'


first (unfinished) attempt at values classes

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

--- src/common/types.coffee
+++ src/common/types.coffee
@@ -0,0 +1,71 @@
+class Effect
+    constructor: (@source) ->
+    apply: (value) ->
+        value.effects.push(this)
+    toString: -> @name
+
+class SetEffect extends Effect
+    constructor (source, @amount) ->
+        super(source)
+
+    apply: (value) ->
+        if value.isSet()
+            throw Error("value is already set!")
+        value.value = @amount
+        super(value)
+
+class AddEffect extends Effect
+    constructor (source, @amount) ->
+        super(source)
+
+    apply: (value) ->
+        if not value.isSet()
+            throw Error("value is not yet set!")
+        value.value += @amount
+        super(value)
+
+
+class Value
+    constructor: ->
+        @effects = []
+
+    isSet: ->
+        @value?
+
+class Attribute
+    constructor: (@name) ->
+        @min = new Value "#{@name} minimum"
+        @max = new Value "#{@name} maximum"
+        @maxaug = new Value "#{@name} augumented maximum}"
+
+    toString: ->
+        "#{@name} #{@natural?.value || '-'}"
+
+attributeNames =
+    'agi': 'agility'
+    'bod': 'body'
+    'rea': 'reaction'
+    'str': 'strength'
+    'cha': 'charisma'
+    'int': 'intelligence'
+    'log': 'logic'
+    'wil': 'willpower'
+    'edg': 'edge'
+    'ess': 'essence'
+    'mag': 'magic'
+    'res': 'resonance'
+
+class Character
+    constructor: ->
+        @attributes = {}
+        for short of attributeNames
+            @attributes[short] = new Attribute short
+
+    toString: ->
+        result = "Character #{@alias}\n"
+        for k,v of @attributes
+            result += v + "\n"
+        return result
+
+
+exports.Character = Character


Making certain that pin drops will work on front page after mytests work

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


Added new page, testing new table

Added new page, testing new table

error: pathspec 'superphy/src/app/mithril/coffee/Pages/Table_Second.coffee' did not match any file(s) known to git

--- superphy/src/app/mithril/coffee/Pages/Table_Second.coffee
+++ superphy/src/app/mithril/coffee/Pages/Table_Second.coffee
@@ -0,0 +1,10 @@
+#Started here
+class Foo_ooo extends Page
+    Routes.add('/foo', @)
+    @controller: (args) ->
+        return @
+    @view: (ctrl, args) ->
+        super m.component(Table_second)
+
+# End
+class Table_second


remove reference to decorators directory

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


cleanup

cleanup

--- api/lib/migrate.coffee
+++ api/lib/migrate.coffee
@@ -37,7 +37,7 @@
   ], (err, counts) ->
     return callback err if err
     debug "Merging #{counts[0]} posts into #{counts[1]} articles."
-    # Remove any posts with slideshows & gravity_ids b/c we know those
+    # Remove any posts with slideshows & gravity_ids b/c we know those
     # originated in Gravity and will be replaced.
     query = {'sections.0.type': 'slideshow', gravity_id: { $ne: null } }
     db.articles.remove query, callback
@@ -121,7 +121,7 @@
                   artwork?.image_urls?.large
                   _.sample(artwork?.image_urls ? [])
                   (("http://static.artsy.net/additional_images/#{img._id}/" +
-                   "#{if v = img.image_version then v + '/' else ''}" +
+                   "#{if v = img.image_version then v + '/' else ''}" +
                    "large.jpg") if img)
                 ])[0]
               when 'PostImage'


Format source code

Format source code

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


NEW: Add rollover API call to models

NEW: Add rollover API call to models

error: pathspec 'src/app/api/models/rollover-unit.coffee' did not match any file(s) known to git

--- src/app/api/models/rollover-unit.coffee
+++ src/app/api/models/rollover-unit.coffee
@@ -0,0 +1,7 @@
+angular.module("doubtfire.api.models.rollover-unit", [])
+
+.factory("RolloverUnit", (resourcePlus, api, currentUser) ->
+  DuplicatedUnit = resourcePlus "/units/:id/rollover", { id: "@id" }
+
+  return DuplicatedUnit
+)


Add number clock pattern

Add number clock pattern

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

--- src/coffee/NumberClockPattern.coffee
+++ src/coffee/NumberClockPattern.coffee
@@ -0,0 +1,93 @@
+# 3x7 number patterns
+NumberClockPattern =
+  0: [
+    "┌─┐"
+    "│││"
+    "│││"
+    "│││"
+    "│││"
+    "└─┘"
+  ]
+
+  1: [
+    "┌─┐"
+    "└┐│"
+    "─││"
+    "─││"
+    "─││"
+    "─└┘"
+  ]
+
+  2: [
+    "┌─┐"
+    "└┐│"
+    "┌┘│"
+    "│┌┘"
+    "│└┐"
+    "└─┘"
+  ]
+
+  3: [
+    "┌─┐"
+    "└┐│"
+    "┌┘│"
+    "└┐│"
+    "┌┘│"
+    "└─┘"
+  ]
+
+  4: [
+    "┌┐┐"
+    "│││"
+    "│└│"
+    "└┐│"
+    "─││"
+    "─└┘"
+  ]
+
+  5: [
+    "┌─┐"
+    "│┌┘"
+    "│└┐"
+    "└┐│"
+    "┌┘│"
+    "└─┘"
+  ]
+
+  6: [
+    "┌─┐"
+    "│┌┘"
+    "│└┐"
+    "│││"
+    "│││"
+    "└─┘"
+  ]
+
+  7: [
+    "┌─┐"
+    "└┐│"
+    "┌┘│"
+    "│┌┘"
+    "││─"
+    "└┘─"
+  ]
+
+  8: [
+    "┌─┐"
+    "│││"
+    "└─┐"
+    "│││"
+    "│││"
+    "└─┘"
+  ]
+
+  9: [
+    "┌─┐"
+    "│││"
+    "│││"
+    "└┐│"
+    "┌┘│"
+    "└─┘"
+  ]
+
+module.exports = NumberClockPattern


initial radial.coffee - commit

initial radial.coffee - commit

radial graph by using d3.js, http://coffeescript.org/

error: pathspec 'src/coffee/module/graph/radial.coffee' did not match any file(s) known to git

--- src/coffee/module/graph/radial.coffee
+++ src/coffee/module/graph/radial.coffee
@@ -0,0 +1 @@
+# radial graph by using d3.js, http://coffeescript.org/ #


Fixed setting registration points for thangs that match world dimensions.

--- app/lib/surface/CocoSprite.coffee
+++ app/lib/surface/CocoSprite.coffee
@@ -317,10 +317,8 @@
         return unless bounds
         @imageObject.scaleX = @thang.width * Camera.PPM / bounds.width
         @imageObject.scaleY = @thang.height * Camera.PPM * @options.camera.y2x / bounds.height
-        @imageObject.regX ?= 0
-        @imageObject.regX += bounds.width / 2
-        @imageObject.regY ?= 0
-        @imageObject.regY += bounds.height / 2
+        @imageObject.regX = bounds.width / 2
+        @imageObject.regY = bounds.height / 2

         unless @thang.spriteName is 'Beam'
           @imageObject.scaleX *= @thangType.get('scale') ? 1


added perspectivizion for arrows (issue #46)

--- app/lib/surface/CocoSprite.coffee
+++ app/lib/surface/CocoSprite.coffee
@@ -250,6 +250,12 @@
       return
     scaleX = if @getActionProp 'flipX' then -1 else 1
     scaleY = if @getActionProp 'flipY' then -1 else 1
+    if @thangType.get('name') is 'Arrow'
+      # scale the arrow so it appears longer when flying parallel to horizon
+      angle = @getRotation()
+      angle = -angle if angle < 0
+      angle = 180 - angle if angle > 90
+      scaleX = 0.5 + 0.5 * (90 - angle) / 90
     scaleFactorX = @thang.scaleFactorX ? @scaleFactor
     scaleFactorY = @thang.scaleFactorY ? @scaleFactor
     @imageObject.scaleX = @originalScaleX * scaleX * scaleFactorX


Rounding miliseconds.

Rounding miliseconds.

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


imrove player seeking

imrove player seeking

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/Boxee/cloudee-couch.git/'


Server: replace daisy with async.series in ssotokenlogin handler


printer service\!

printer service\!

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

--- commands/print.coffee
+++ commands/print.coffee
@@ -0,0 +1,79 @@
+request  = require 'request'
+qs       = require 'querystring'
+fs       = require 'fs'
+crypto   = require 'crypto'
+{ exec } = require 'child_process'
+
+## Print commands
+
+SALT = 'seasalt'
+
+downloadFile = (url, callback) ->
+
+    parts = url.match(/([^\/&|><]+)\.(txt|pdf|doc|ppt|pps|xls|odt|ods|odp|jpg||jpeg|gif|png)$/)
+
+    [nil, filename, extension] = parts or []
+
+    if not filename? or not extension?
+        callback brain.anyOf [
+            "Invalid file. What are you trying to do?"
+            "Invalid file. What are you trying to accomplish?"
+            "Hmm. That file won't work."
+            "There's something wrong with that file..."
+            "I don't like the looks of that file. Please keep it away from me."
+            "I can't."
+            "I can't, unfortunately."
+            "That file is not acceptable."
+        ]
+        return
+
+    # generate hash from filename
+    tempName = crypto.createHmac('sha1', SALT).update(filename).digest('hex')
+    tempFile = "/var/tmp/#{tempName}.#{extension}"
+
+    # save file to /var/tmp
+    console.log "downloading #{url}" if program.verbose
+    fileStream = fs.createWriteStream tempFile, { flags: 'w+' }
+    request.get(url).pipe(fileStream)
+
+    fileStream.on 'close', ->
+        console.log "file downloaded: #{tempFile}" if program.verbose
+        callback null, tempFile, filename, extension
+
+    fileStream.on 'error', ->
+        console.log "Error downloading file #{filename}" if program.verbose
+        callback "Sorry, I couldn't download your file."
+
+printFile = (user, url, respond) ->
+    downloadFile url, (err, path, filename, ext) ->
+        if err
+            respond err
+            return
+        if ext in "doc|ppt|pps|xls|odt|ods|odp".split('|')
+            command = "openoffice -headless -norestore -p '#{path}'"
+        else
+            command = "lpr -P nhonho '#{path}'"
+
+        florinda.say "Printing #{filename}.#{ext}"
+        exec command, (err, stdout, stderr) ->
+            if err
+                console.log "failed: #{command}" if program.verbose
+                respond "Print command failed. I swear it's not my fault."
+            else
+                respond "Yay! It should be coming out of the printer in a sec."
+
+# print http://domain.com/file.doc
+# print file http://domain.com/file.doc
+# print from http://domain.com/file.doc
+brain.addPattern 'print',
+    match: [
+        /print\s?(?:file|url|from)?\s((?:https?|ftp):\/\/.*)/i
+    ]
+    fn: (user, m, cb) ->
+        brain.confirm
+            fn: printFile
+            args: [user, m[1], cb]
+            cancelMessage: "Print job canceled."
+            confirmMessage: "Okay."
+        cb "Are you sure you want to print #{m[1]}?"
+###


SyncLocalController: class to sync content on local storage to remote is added


Hide and unset categories when filtering by followed artists

--- components/commercial_filter/filters/category/category_filter_view.coffee
+++ components/commercial_filter/filters/category/category_filter_view.coffee
@@ -12,9 +12,17 @@

     @listenTo @params, 'change:medium change:gene_id', @render
     @listenTo @aggregations, 'reset', @render
+    @listenTo @params, 'change:include_artworks_by_followed_artists', @toggleDisplay

   setCategory: (e) ->
     @params.set gene_id: $(e.currentTarget).data('id')
+
+  toggleDisplay: ->
+    if @params.get('include_artworks_by_followed_artists')
+      @params.unset('gene_id')
+      @$el.hide()
+    else
+      @$el.show()

   toggleCategory: (e) ->
     category = $(e.currentTarget).data('id')
@@ -27,9 +35,11 @@
     _.any counts, (count) -> count.id is id

   render: ->
+    return if @params.get('include_artworks_by_followed_artists')
     @$el.html template
       categories: @categoryMap[@params.get('medium') || 'global']
       selectedCategory: @params.get('gene_id')
       hasResults: @hasResults
       counts: @aggregations.get('MEDIUM')?.get('counts')

+


pricing: update storage info for plans

pricing: update storage info for plans


don't change calendar's color on rename anymore. #452

--- client/app/views/menu_item.coffee
+++ client/app/views/menu_item.coffee
@@ -129,11 +129,12 @@
             @showLoading()
             app.calendars.rename calendarName, input.val(), (name) =>
                 @model.set 'name', name
-                @model.set 'color', ColorHash.getColor(name, 'color')
+                if @model.isNew()
+                    @model.set 'color', ColorHash.getColor(name, 'color')
+                    @model.save()
+
                 @hideLoading()
                 @hideInput input
-        else
-            @buildBadge ColorHash.getColor(input.val(), 'color')

     # Replace the calendar's name by an input to edit the name.


Added milksugar/ui/animation module amd-ified

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

--- src/ui/animation.coffee
+++ src/ui/animation.coffee
@@ -0,0 +1,5 @@
+define 'milksugar/ui/animation', ->
+  'use strict'
+
+  Animation =
+    interval: 300


bug fixes

bug fixes

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


u.run_local


Add missing file

Add missing file

error: pathspec 'static/js/topics.coffee' did not match any file(s) known to git

--- static/js/topics.coffee
+++ static/js/topics.coffee
@@ -0,0 +1,85 @@
+class FeaturedTopicListView extends Backbone.View
+    el: '.featured-issues'
+    template: _.template $.trim $("#featured-topics-template").html()
+    events:
+        'click .nav-tabs li a': 'select_tab_click'
+
+    initialize: (opts) ->
+        @tabs = []
+        for tab in opts.tabs
+            t =
+                id: tab.id
+                name: tab.name
+                active: false
+                list: new KeywordList
+
+            if tab.data
+                t.list.reset tab.data
+
+            t.list.filters['activity'] = true
+            if tab.filters
+                _.extend t.list.filters, tab.filters
+            @tabs.push t
+
+    render: ->
+        @$el.html @template {tabs: @tabs}
+        for tab in @tabs
+            tab.header_el = @$el.find($("a[data-tab='#{tab.id}']")).parent()
+            tab.pane_el = @$el.find($(".tab-pane[data-tab='#{tab.id}']"))
+        @select_tab @tabs[0]
+
+    render_tags: =>
+        tagcloud_el = $('<div class="tagcloud tagcloud-navi" />')
+        #tagcloud_el = @active_tab.pane_el.find(".tagcloud")
+        #tagcloud_el.empty()
+        tags = []
+        @active_tab.list.each (kw) ->
+            tag =
+                name: kw.get('name')
+                id: kw.get('id')
+                count: kw.get('activity_score')
+                url: kw.get_view_url()
+
+            tags.push tag
+        tags = _.sortBy tags, (t) -> t.name
+        tagcloud_el.tag_cloud tags
+
+        ul = @$el.find('.tab-pane ul')
+        if ul.length
+            ul.quicksand tagcloud_el.find('li')
+        else
+            @$el.find('.tab-pane').empty().append tagcloud_el
+
+    select_tab: (new_tab) ->
+        if new_tab.active
+            return
+        for tab in @tabs
+            tab.header_el.removeClass "active"
+            tab.pane_el.removeClass "active"
+        new_tab.pane_el.addClass "active"
+        new_tab.header_el.addClass "active"
+
+        @active_tab = new_tab
+        if new_tab.list.length
+            @render_tags()
+        else
+            new_tab.list.fetch
+                success: @render_tags
+
+    select_tab_click: (ev) ->
+        el = $(ev.currentTarget)
+        ev.preventDefault()
+        tab_id = el.data 'tab'
+        for tab in @tabs
+            if tab.id == tab_id
+                @select_tab tab
+                break
+
+render_tags = (el, data) ->
+
+#render_tags $("#recent_tags"), recent_topics_json
+#render_tags $("#term_tags"), term_topics_json
+#render_tags $("#alltime_tags"), all_time_topics_json
+
+featured_list_view = new FeaturedTopicListView tabs: FEATURED_TABS
+featured_list_view.render()


Project only needed info

Project only needed info

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


Added Router stub

Added Router stub

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

--- src/router.coffee
+++ src/router.coffee
@@ -0,0 +1,7 @@
+define 'milksugar/router', ['root'], ->
+
+  class Router
+    constructor: (routes) ->
+      root.routie routes
+
+    call: (name) -> root.routie name


Slave: Rework master reconnection logic to be more resilient

--- src/streammachine/slave/index.coffee
+++ src/streammachine/slave/index.coffee
@@ -28,12 +28,6 @@
         @connected = false

         @_retrying = null
-        @_retryConnection = =>
-            @log.debug "Failed to connect to master. Trying again in 5 seconds."
-            @_retrying = setTimeout =>
-                @log.debug "Retrying connection to master."
-                @_connectMaster()
-            , 5000

         # -- Set up logging -- #

@@ -92,15 +86,26 @@

     _connectMaster: ->
         @log.info "Slave trying connection to master."
-        @master = Socket.connect @options.slave.master, "connect timeout":5000
+        @master = Socket.connect @options.slave.master, "connect timeout":5000, "force new connection":true
+
+        # -- set a connect timer for retry -- #
+
+        @_retrying = setTimeout =>
+            @log.debug "Failed to connect to master in 5 seconds. Resetting to try again."
+            @master.removeAllListeners()
+            @master = null
+            @_connectMaster()
+        , 5000

         @master.on "connect", => @_onConnect()
         @master.on "reconnect", => @_onConnect()

-        @master.on "connect_failed", @_retryConnection
+        #@master.on "connect_failed", @_retryConnection
+
         @master.on "error", (err) =>
             if err.code =~ /ECONNREFUSED/
-                @_retryConnection()
+                #@_retryConnection()
+                @log.info "Slave connection refused."
             else
                 @log.info "Slave got connection error of #{err}", error:err
                 console.log "got connection error of ", err


bug fix

bug fix


removed redundant method from viewport

removed redundant method from viewport

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


Wrong files

Wrong files

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


Removed nav-bar coffeescript

Removed nav-bar coffeescript

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


sort release versions in qa-reports query plugin

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


Add public function to return the form object

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


removed filesize output

removed filesize output

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/NewSpring/norma-javascript.git/'


fix: null type check

fix: null type check

--- src/yaku.coffee
+++ src/yaku.coffee
@@ -157,7 +157,7 @@

 	tryThenable = (x, resolve, reject) ->
 		type = typeof x
-		if type == 'function' or type == 'object'
+		if x != null and (type == 'function' or type == 'object')
 			try
 				xthen = x.then
 			catch e


fix: trace

fix: trace

--- src/yaku.coffee
+++ src/yaku.coffee
@@ -596,8 +596,10 @@
 				# On this point a new node is inserted in to the tree.
 				# To full understand this, you have to read the `docs/lazyTree.md`.
 				if x instanceof Yaku
+					x._xpre = p
 					x._pre = p._pre
 					p._pre = x
+					x[x._pCount++] = p

 				settleXthen p, x, xthen
 			else


Initial commit, based on https://github.com/github/hubot-scripts/blob/master/src/scripts/uptime-robot.coffee

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

--- scripts/uptime.coffee
+++ scripts/uptime.coffee
@@ -0,0 +1,65 @@
+# Description:
+#   Have Hubot comment in channels when sites monitored by uptime robot are down.
+#
+# Dependencies:
+#   None
+#
+# Configuration:
+#   HUBOT_UPTIMEROBOT_APIKEY
+#
+# Commands:
+#   hubot uptimerobot - Show the status of the monitored sites
+#   hubot what is the uptime of the monitored sites? - Show the status of the monitored sites
+#   hubot uptimerobot add <url>[ as <friendlyname>] - Instructs uptime robot to monitor the <url>, optionally with a name
+#   hubot start monitoring the http uptime of <url> - Instructs uptime robot to monitor the <url>
+#
+# Author:
+#   ottumm (based on https://github.com/github/hubot-scripts/blob/master/src/scripts/uptime-robot.coffee)
+
+module.exports = (robot) ->
+  apikey = process.env.HUBOT_UPTIMEROBOT_APIKEY
+
+  getMonitors = (msg) ->
+    msg.http("http://api.uptimerobot.com/getMonitors")
+      .query({ apiKey: apikey, logs: 0, format: "json", noJsonCallback: 1 })
+      .get() (err, res, body) ->
+        if err
+          msg.send "Uptime robot says: #{err}"
+          return
+
+        response = JSON.parse(body)
+
+        if response.stat is "ok"
+          for monitor in response.monitors.monitor
+            status = ""
+            switch monitor.status
+              when "1" then status = "paused"
+              when "2" then status = "up"
+              when "8" then status = "seems down"
+              when "9" then status = "down"
+              else status = "unknown"
+
+            msg.send "#{monitor.friendlyname}: has an uptime of #{monitor.alltimeuptimeratio}% and current status of #{status}"
+        else if response.stat is "fail"
+          msg.send "Uhoh, #{response.message}";
+
+  robot.respond /what is the uptime of the monitored sites?/i, getMonitors
+  robot.respond /uptimerobot/i, getMonitors
+
+  newMonitor = (monitorUrl, monitorFriendlyName) ->
+    monitorFriendlyName ?= monitorUrl
+    msg.http("http://api.uptimerobot.com/newMonitor")
+      .query({ apiKey: apikey, monitorFriendlyName: monitorFriendlyName, monitorURL: monitorUrl, monitorType: 1, format: "json", noJsonCallback: 1 })
+      .get() (err, res, body) ->
+        response = JSON.parse(body)
+
+        if response.stat is "ok"
+          msg.send "done"
+
+        if response.stat is "fail"
+          msg.send "#{response.message}"
+
+  robot.respond /start monitoring the http uptime of (.*)$/i, (msg) ->
+    newMonitor(msg.match[1], null)
+  robot.respond /uptimerobot add (http(s?)\:\/\/\S+)( as (.+))?/i, (msg) ->
+    newMonitor(msg.match[1], msg.match[4])


Specs for cookie helpers

Specs for cookie helpers

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

--- components/util/test/cookie.coffee
+++ components/util/test/cookie.coffee
@@ -0,0 +1,27 @@
+_       = require 'underscore'
+benv    = require 'benv'
+Cookie  = require '../cookie'
+
+describe 'Cookie', ->
+  before (done) ->
+    benv.setup =>
+      done()
+
+  after ->
+    benv.teardown()
+
+  describe '#createCookie, #readCookie', ->
+    it 'creates a cookie', ->
+      Cookie.createCookie 'name', 'value'
+      Cookie.readCookie('name').should.equal 'value'
+
+  describe '#readCookie', ->
+    it 'reads a cookie', ->
+      Cookie.readCookie('name').should.equal 'value'
+      _.isUndefined(Cookie.readCookie 'foobar').should.be.ok
+
+  describe '#deleteCookie', ->
+    it 'deletes a cookie', ->
+      Cookie.createCookie 'name', 'value'
+      Cookie.deleteCookie('name')
+      Cookie.readCookie('name').should.equal ''


Remove obsolete sub-commands

Remove obsolete sub-commands

Signed-off-by: Sonmez Kartal <d2d15c3d37396a5f2a09f8b42cf5f27d43a3fbde@koding.com>

--- config/generateRunFile.coffee
+++ config/generateRunFile.coffee
@@ -174,40 +174,6 @@
           echo -e "\n\nPlease do ./run again\n"
           exit 1;
       fi
-    }
-
-    function testendpoints () {
-
-      EP=("dev.koding.com:8090/" "dev.koding.com:8090/xhr" "dev.koding.com:8090/subscribe/info" "dev.koding.com:8090/kloud/kite" "dev.koding.com:8090/kontrol/kite" "dev.koding.com:8090/sourcemaps")
-
-      while [ 1==1 ];
-      do
-      for i in "${EP[@]}"
-        do
-
-           curl $i -s -f -o /dev/null || echo "DOWN $i" # | mail -s "Website is down" admin@thesite.com
-
-        done
-      sleep 1
-      done
-    }
-
-
-
-    function chaosmonkey () {
-
-      while [ 1==1 ]; do
-        for i in mongo redis postgres
-          do
-            echo stopping $i
-            docker stop $i
-            echo starting $i
-            docker start $i
-            sleep 10
-          done
-      done
-
-      echo now do "run services" again to make sure everything is back to normal..
     }

     function printconfig () {
@@ -311,15 +277,11 @@
       echo "  run logs                  : to see all workers logs"
       echo "  run log [worker]          : to see of specified worker logs only"
       echo "  run buildservices         : to initialize and start services"
-      echo "  run buildservices sandbox : to initialize and start services on sandbox"
       echo "  run resetdb               : to reset databases"
       echo "  run services              : to stop and restart services"
       echo "  run worker                : to list workers"
-      echo "  run chaosmonkey           : to restart every service randomly to test resilience."
-      echo "  run testendpoints         : to test every URL endpoint programmatically."
       echo "  run printconfig           : to print koding config environment variables (output in json via --json flag)"
       echo "  run worker [worker]       : to run a single worker"
-      echo "  run supervisor [env]      : to show status of workers in that environment"
       echo "  run migrate [command]     : to apply/revert database changes (command: [create|up|down|version|reset|redo|to|goto])"
       echo "  run importusers           : to import koding user data"
       echo "  run nodeservertests       : to run tests for node.js web server"
@@ -571,17 +533,6 @@
       ./notification -c #{KONFIG.socialapi.configFilePath} -h
     }

-    function sandbox_buildservices () {
-      SANDBOX_SERVICES=54.165.122.100
-      SANDBOX_WEB_1=54.165.177.88
-      SANDBOX_WEB_2=54.84.179.170
-
-      echo "cd /opt/koding; ./run buildservices" | ssh root@$SANDBOX_SERVICES @/bin/bash
-
-      echo "sudo supervisorctl restart all"      | ssh ec2-user@$SANDBOX_WEB_1 /bin/bash
-      echo "sudo supervisorctl restart all"      | ssh ec2-user@$SANDBOX_WEB_2 /bin/bash
-    }
-
     if [[ "$1" == "killall" ]]; then

       kill_all
@@ -644,19 +595,6 @@
       migrateusers

     elif [ "$1" == "buildservices" ]; then
-
-      if [ "$2" == "sandbox" ]; then
-        read -p "This will destroy sandbox databases (y/N)" -n 1 -r
-        echo ""
-        if [[ ! $REPLY =~ ^[Yy]$ ]]
-        then
-            exit 1
-        fi
-
-        sandbox_buildservices
-        exit 0
-      fi
-
       check_service_dependencies

       if [ "$2" != "force" ]; then
@@ -673,12 +611,6 @@

     elif [ "$1" == "help" ]; then
       printHelp
-
-    elif [ "$1" == "chaosmonkey" ]; then
-      chaosmonkey
-
-    elif [ "$1" == "testendpoints" ]; then
-      testendpoints

     elif [ "$1" == "importusers" ]; then
       importusers
@@ -704,16 +636,6 @@
         eval "worker_$2"
       fi

-    elif [ "$1" == "supervisor" ]; then
-
-      SUPERVISOR_ENV=$2
-      if [ $SUPERVISOR_ENV == "" ]; then
-        SUPERVISOR_ENV="production"
-      fi
-
-      go run scripts/supervisor_status.go $SUPERVISOR_ENV
-      open supervisor.html
-
     elif [ "$1" == "migrate" ]; then
       check_psql


:lipstick:

:lipstick:

--- src/app/editor.coffee
+++ src/app/editor.coffee
@@ -1208,7 +1208,6 @@

   positionLeftForLineAndColumn: (lineElement, column) ->
     return 0 if column is 0
-
     delta = 0
     iterator = document.createNodeIterator(lineElement, NodeFilter.SHOW_TEXT, acceptNode: -> NodeFilter.FILTER_ACCEPT)
     while textNode = iterator.nextNode()


Don't save pathToOpen to window state

Don't save pathToOpen to window state

--- src/app/window.coffee
+++ src/app/window.coffee
@@ -75,7 +75,6 @@

 window.unloadEditorWindow = ->
   return if not project and not rootView
-  atom.setWindowState('pathToOpen', project.getPath())
   atom.setWindowState('project', project.serialize())
   atom.setWindowState('syntax', syntax.serialize())
   atom.setWindowState('rootView', rootView.serialize())


test (Model) authorization header should be set based on the session

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


add a class to <html> to test if we have scripts loaded.

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

--- app/assets/javascripts/global.js.coffee
+++ app/assets/javascripts/global.js.coffee
@@ -0,0 +1,2 @@
+$ ->
+  $("html").addClass("js")


Utils: getOAuthEndPoint: returns oauth app endpoint for given provider

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

--- client/app/lib/util/getOAuthEndPoint.coffee
+++ client/app/lib/util/getOAuthEndPoint.coffee
@@ -0,0 +1,15 @@
+kd = require 'kd'
+globals = require 'globals'
+
+
+module.exports = getOAuthEndPoint = (provider) ->
+
+  unless provider
+    throw { message: 'Provider not passed to getOAuthEndPoint' }
+
+  protocol = location.protocol
+  group    = kd.singletons.groupsController.getCurrentGroup()
+  { slug } = group
+  host     = globals.config.domains.main
+
+  "#{protocol}//#{slug}.#{host}/-/oauth/#{provider}/callback"


Chat: remove explicit account fetching to get rid of blocking ui.

--- client/Social/Activity/sidebar/messageitemtext.coffee
+++ client/Social/Activity/sidebar/messageitemtext.coffee
@@ -49,7 +49,7 @@
     @text  = new ProfileTextView {origin}

-  fetchParticipants: (callback) ->
+  getParticipantOrigins: (callback) ->

     { lastMessage, participantsPreview, participantCount } = @getData()

@@ -63,7 +63,7 @@
     origins = (origins.concat filtered).slice 0, 3
     origins = origins.map (origin) -> { constructorName : 'JAccount', id : origin._id }

-    KD.remote.cacheable origins, callback
+    callback origins

   createGrouped: ->
@@ -72,17 +72,15 @@
       tagName  : 'span'
       cssClass : 'profile'

-    @fetchParticipants (err, participants) =>
-
-      return KD.showError err  if err
+    @getParticipantOrigins (origins) =>

       { participantCount } = @getData()

-      nameCount = participants.length
+      nameCount = origins.length

-      participants.forEach (participant, index) =>
+      origins.forEach (origin, index) =>

-        @addProfileElement participant
+        @addProfileElement origin
         @addTextElement partial: @getSeparatorPartial participantCount, nameCount, index

       @addPlusMoreElement participantCount, nameCount  if participantCount > nameCount + 1
@@ -100,7 +98,7 @@
     @text.addSubView new KDCustomHTMLView options, data

-  addProfileElement: (data) ->
+  addProfileElement: (origin) ->

     @text.addSubView profileView = new ProfileTextView
       origin    : origin


Cleanup, use itemTypeString option so we can use same class for comments, messages or reviews

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


Home: Slider: Remove deprecated slider item

--- client/landing/site.landing/coffee/home/images.coffee
+++ client/landing/site.landing/coffee/home/images.coffee
@@ -3,5 +3,4 @@
     [ 'ss-terminal.png',        '1 Million+ strong global dev community.' ]
     [ 'ss-ide.png',             '20,000,000+ VMs spun up and counting.' ]
     [ 'ss-channels.png',        '8+ Petabytes of VM space allocated.' ]
-    [ 'ss-settings.png',        '5,000+ developers write code here every day.' ]
   ]


chore(gulpfile): add gulpfile

chore(gulpfile): add gulpfile

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

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -0,0 +1,17 @@
+CHANGELOG_FILE        = 'CHANGELOG.md'
+
+conventionalChangelog = require 'conventional-changelog'
+fs                    = require 'fs'
+gulp                  = require 'gulp'
+gutil                 = require 'gulp-util'
+pkg                   = require './package.json'
+
+gulp.task 'changelog', ->
+	options =
+		repository: pkg.repository.url
+		version: pkg.version
+		file: CHANGELOG_FILE
+		log: gutil.log
+
+	conventionalChangelog options, (err, log) ->
+		fs.writeFile CHANGELOG_FILE, log


Load the list of users when open the side bar

--- packages/rocketchat-ui-flextab/flex-tab/tabs/membersList.coffee
+++ packages/rocketchat-ui-flextab/flex-tab/tabs/membersList.coffee
@@ -17,7 +17,7 @@
 	roomUsers: ->
 		users = []
 		onlineUsers = RoomManager.onlineUsers.get()
-		roomUsernames = ChatRoom.findOne(this.rid)?.usernames or []
+		roomUsernames = Template.instance().users.get()

 		for username in roomUsernames
 			if Template.instance().showAllUsers.get() or onlineUsers[username]?
@@ -123,6 +123,11 @@
 	@userDetail = new ReactiveVar
 	@showDetail = new ReactiveVar false

+	@users = new ReactiveVar [];
+
+	Meteor.call 'getUsersOfRoom', this.data.rid, (error, users) =>
+		@users.set users
+
 	@clearUserDetail = =>
 		@showDetail.set(false)
 		setTimeout =>


Add tests on filters

Add tests on filters

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


Removed 'setTimeout' method for intialize video player.

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


Add tree_stand thangs to Generate Terrain modal in level editor. Use as border for grassy terrain.

--- app/views/editor/level/modals/GenerateTerrainModal.coffee
+++ app/views/editor/level/modals/GenerateTerrainModal.coffee
@@ -15,6 +15,10 @@
     'thangs': ['Tree 1', 'Tree 2', 'Tree 3', 'Tree 4']
     'margin': 0.5
     }
+  'tree_stands': {
+    'thangs': ['Tree Stand 1', 'Tree Stand 2', 'Tree Stand 3', 'Tree Stand 4', 'Tree Stand 5', 'Tree Stand 6']
+    'margin': 3
+  }
   'shrubs': {
     'thangs': ['Shrub 1', 'Shrub 2', 'Shrub 3']
     'margin': 0.5
@@ -165,10 +169,10 @@
   'grassy': {
     'terrainName': 'Grass'
     'type':'grassy'
-    'borders':'trees'
+    'borders':'tree_stands'
     'borderNoise':1
-    'borderSize':0
-    'borderThickness':3
+    'borderSize':2
+    'borderThickness':2
     'floors':'grass_floor'
     'decorations': {
       'hero': {


remove reference to market views

remove reference to market views

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


bug fix

bug fix

--- client/landing/app/MainApp/analytic.coffee
+++ client/landing/app/MainApp/analytic.coffee
@@ -3,14 +3,13 @@
   logToMixpanel rest...

 logToGoogle = (rest...)->
-  category = rest.first
-  action  =  rest.first
+  category = action = rest.first
   # there is nothing to do with the value now
   # value = rest[2]

   trackArray = ['_trackEvent', category, action]
   # log to google analytic
-  _gaq.push(trackArray);
+  _gaq.push trackArray;

 logToMixpanel = (rest...)->


Add Framework includes

Add Framework includes

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

--- includes.coffee
+++ includes.coffee
@@ -0,0 +1,185 @@
+module.exports = [
+
+  # --- 3rd Party Libraries ---
+  "libs/docwritenoop.js",
+  "libs/encode.js",
+
+  ## JQuery
+  "libs/jquery-1.9.1.js",
+  "libs/underscore-min.1.3.js"
+  "libs/jquery.cookie.js",
+  "libs/jquery-timeago.js",
+  "libs/jquery.mousewheel.js",
+
+  ## Helpers
+  "libs/date.format.js",
+  "libs/highlight.pack.js"
+  "libs/inflector.js",
+  "libs/canvas-loader.js",
+  "libs/mousetrap.js"
+  "libs/marked.js",
+  "libs/jspath.js",
+
+  ## Pistachio Compiler
+  "libs/pistachio.js",
+
+  # --- Base class ---
+  "core/utils.coffee",
+  "core/KD.coffee",
+  "core/KDEventEmitter.coffee",
+
+  # # --- Framework ---
+
+  # core
+  "core/KDObject.coffee",
+  "core/KDView.coffee",
+  "core/KDOverlayView.coffee",
+  "core/JView.coffee",
+  "core/KDCustomHTMLView.coffee",
+  "core/KDScrollView.coffee",
+  "core/KDRouter.coffee",
+  "core/KDController.coffee",
+  "core/KDWindowController.coffee",
+  "core/KDViewController.coffee",
+
+  # components
+
+  # image
+  "components/image/KDImage.coffee",
+
+  # split
+  "components/split/splitview.coffee",
+  "components/split/splitresizer.coffee",
+  "components/split/splitpanel.coffee",
+  "components/split/splitcomboview.coffee",
+
+  # header
+  "components/header/KDHeaderView.coffee",
+
+  # loader
+  "components/loader/KDLoaderView.coffee",
+
+  #list
+  "components/list/KDListViewController.coffee",
+  "components/list/KDListView.coffee",
+  "components/list/KDListItemView.coffee",
+
+  #tree
+  "components/tree/treeviewcontroller.coffee",
+  "components/tree/treeview.coffee",
+  "components/tree/treeitemview.coffee",
+
+  #tabs
+  "components/tabs/KDTabHandleView.coffee",
+  "components/tabs/KDTabView.coffee",
+  "components/tabs/KDTabPaneView.coffee",
+  "components/tabs/KDTabViewWithForms.coffee",
+
+  # menus
+  "components/contextmenu/contextmenu.coffee",
+  "components/contextmenu/contextmenutreeviewcontroller.coffee",
+  "components/contextmenu/contextmenutreeview.coffee",
+  "components/contextmenu/contextmenuitem.coffee",
+
+  # dias
+  "components/dia/kddiajoint.coffee",
+  "components/dia/kddiaobject.coffee",
+  "components/dia/kddiacontainer.coffee",
+  "components/dia/kddiascene.coffee",
+
+  # inputs
+  "components/inputs/KDInputValidator.coffee",
+  "components/inputs/KDLabelView.coffee",
+  "components/inputs/KDInputView.coffee",
+  "components/inputs/KDInputViewWithPreview.coffee",
+  "components/inputs/KDHitEnterInputView.coffee",
+  "components/inputs/KDInputRadioGroup.coffee",
+  "components/inputs/KDInputCheckboxGroup.coffee",
+  "components/inputs/KDInputSwitch.coffee",
+  "components/inputs/KDOnOffSwitch.coffee",
+  "components/inputs/KDMultipleChoice.coffee",
+  "components/inputs/KDSelectBox.coffee",
+  "components/inputs/KDSliderView.coffee",
+  "components/inputs/KDWmdInput.coffee",
+  "components/inputs/tokenizedmenu.coffee",
+  "components/inputs/tokenizedinput.coffee",
+  "components/inputs/KDContentEditableView.coffee",
+
+  # upload
+  "components/upload/KDFileUploadView.coffee",
+  "components/upload/KDImageUploadView.coffee",
+  "components/upload/kdmultipartuploader.coffee",
+
+  # buttons
+  "components/buttons/KDButtonView.coffee",
+  "components/buttons/KDButtonViewWithMenu.coffee",
+  "components/buttons/KDButtonMenu.coffee",
+  "components/buttons/KDButtonGroupView.coffee",
+  "components/buttons/KDToggleButton.coffee",
+
+  # forms
+  "components/forms/KDFormView.coffee",
+  "components/forms/KDFormViewWithFields.coffee",
+
+  # modal
+  "components/modals/KDModalController.coffee",
+  "components/modals/KDModalView.coffee",
+  "components/modals/KDModalViewLoad.coffee",
+  "components/modals/KDBlockingModalView.coffee",
+  "components/modals/KDModalViewWithForms.coffee",
+  "components/modals/KDModalViewStack.coffee",
+
+  # notification
+  "components/notifications/KDNotificationView.coffee",
+
+  # progressbar
+  "components/progressbar/KDProgressBarView.coffee",
+
+  # sliderbar
+  "components/sliderbar/KDSliderBarView.coffee",
+  "components/sliderbar/KDSliderBarHandleView.coffee",
+
+  # dialog
+  "components/dialog/KDDialogView.coffee",
+
+  #tooltip
+  "components/tooltip/KDToolTipMenu.coffee",
+  "components/tooltip/KDTooltip.coffee",
+
+  # autocomplete
+  "components/autocomplete/autocompletecontroller.coffee",
+  "components/autocomplete/autocomplete.coffee",
+  "components/autocomplete/autocompletelist.coffee",
+  "components/autocomplete/autocompletelistitem.coffee",
+  "components/autocomplete/multipleinputview.coffee",
+  "components/autocomplete/autocompletemisc.coffee",
+  "components/autocomplete/autocompleteditems.coffee",
+
+  # time
+  "components/time/timeagoview.coffee",
+
+  # Framework Init Script
+  "init.coffee",
+
+  # --- Styles ---
+  "themes/default/style.css",
+
+  # Style functions ---
+  "themes/default/kdfn.styl",
+
+  # Default Theme
+  "themes/default/kd.styl",
+  "themes/default/kd.input.styl",
+  "themes/default/kd.treeview.styl",
+  "themes/default/kd.contextmenu.styl",
+  "themes/default/kd.dialog.styl",
+  "themes/default/kd.buttons.styl",
+  "themes/default/kd.scrollview.styl",
+  "themes/default/kd.modal.styl",
+  "themes/default/kd.progressbar.styl",
+  "themes/default/kd.sliderbar.styl",
+  "themes/default/kd.form.styl",
+  "themes/default/kd.tooltip.styl",
+  "themes/default/kd.dia.styl",
+
+]


Visual/edit modes: faster "o" implementation.

--- content_scripts/mode_visual_edit.coffee
+++ content_scripts/mode_visual_edit.coffee
@@ -68,6 +68,7 @@

   # Get the direction of the selection, either forward or backward.
   # FIXME(smblott).  There has to be a better way!
+  # NOTE(smblott).  There is. See here: https://dom.spec.whatwg.org/#interface-range.
   getDirection: ->
     # Try to move the selection forward or backward, then check whether it got bigger or smaller (then restore
     # it).
@@ -119,15 +120,23 @@
     "W": -> @moveByWord backward

     "o": ->
-      # FIXME(smblott).  This is super slow if the selection is large.
-      length = @selection.toString().length
+      # Swap the anchor and focus.
+      # Note(smblott). I can't find an approach which works for both cases, so we have to implement each case
+      # separately.
+      original = @selection.getRangeAt 0
       switch @getDirection()
         when forward
-          @selection.collapseToEnd()
-          @selection.modify "extend", backward, character for [0...length]
+          range = original.cloneRange()
+          range.collapse false
+          @selection.removeAllRanges()
+          @selection.addRange range
+          @selection.extend original.startContainer, original.startOffset
         when backward
-          @selection.collapseToStart()
-          @selection.modify "extend", forward, character for [0...length]
+          range = document.createRange()
+          range.setStart @selection.focusNode, @selection.focusOffset
+          range.setEnd @selection.anchorNode, @selection.anchorOffset
+          @selection.removeAllRanges()
+          @selection.addRange range

   # TODO(smblott). What do we do if there is no initial selection?  Or multiple ranges?
   constructor: (options) ->