Added log ticker

Added log ticker

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

--- bokehjs/src/coffee/ticking/log_ticker.coffee
+++ bokehjs/src/coffee/ticking/log_ticker.coffee
@@ -0,0 +1,79 @@
+
+define [
+  "ticking/adaptive_ticker",
+], (AdaptiveTicker) ->
+
+  range = (start, stop, step) ->
+    if typeof stop is "undefined"
+
+    # one param defined
+      stop = start
+      start = 0
+    step = 1  if typeof step is "undefined"
+    return []  if (step > 0 and start >= stop) or (step < 0 and start <= stop)
+    result = []
+    i = start
+
+    while (if step > 0 then i < stop else i > stop)
+      result.push i
+      i += step
+    return result
+
+  class LogTicker extends AdaptiveTicker.Model
+    type: 'LogTicker'
+
+
+    initialize: (attrs, options) ->
+      super(attrs, options)
+
+    get_ticks_no_defaults: (data_low, data_high, desired_n_ticks) ->
+
+      if data_low > data_high
+        [data_low, data_high] = [data_high, data_low]
+
+      if data_low <= 0 #Hotfix
+        data_low = 1
+
+      log_low = Math.log(data_low) / Math.log(10)
+      log_high = Math.log(data_high) / Math.log(10)
+      log_interval = log_high - log_low
+
+      if log_interval < 1
+        interval = @get_interval(data_low, data_high, desired_n_ticks)
+        start_factor = Math.floor(data_low / interval)
+        end_factor   = Math.ceil(data_high / interval)
+        if _.isNaN(start_factor) or _.isNaN(end_factor)
+          factors = []
+        else
+          factors = _.range(start_factor, end_factor + 1)
+
+        ticks = (factor * interval for factor in factors when factor != 0)
+
+        return ticks
+
+      else
+        startlog = Math.ceil(log_low)
+        endlog = Math.floor(log_high)
+        interval = Math.ceil((endlog - startlog) / 9.0)
+
+        expticks = range(startlog, endlog, interval)
+
+        if (endlog - startlog) % interval == 0
+          expticks = expticks.concat [endlog]
+
+        expticks = expticks.map (i) -> Math.pow(10, i)
+
+        return expticks
+
+    defaults: () ->
+      return _.extend(super(), {
+        mantissas: [1, 5]
+      })
+
+  class LogTickers extends Backbone.Collection
+    model: LogTicker
+
+  return {
+    "Model": LogTicker,
+    "Collection": new LogTickers()
+  }


Add a missing error handler

Add a missing error handler

--- server/controllers/authentication.coffee
+++ server/controllers/authentication.coffee
@@ -80,10 +80,13 @@
         next error

-module.exports.loginIndex = (req, res) ->
+module.exports.loginIndex = (req, res, next) ->
     getEnv (err, env) ->
-        return res.redirect '/register' unless env.username
-        res.render 'index', env: env
+        if err
+            next new Error err
+        else
+            return res.redirect '/register' unless env.username
+            res.render 'index', env: env

 module.exports.forgotPassword = (req, res, next) ->
@@ -110,10 +113,13 @@

 module.exports.resetPasswordIndex = (req, res) ->
     getEnv (err, env) ->
-        if Instance.getResetKey() is req.params.key
-            res.render 'index', env: env
+        if err
+            next new Error err
         else
-            res.redirect '/'
+            if Instance.getResetKey() is req.params.key
+                res.render 'index', env: env
+            else
+                res.redirect '/'

 module.exports.resetPassword = (req, res, next) ->


Server side move checks

Server side move checks

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


Updated atom-quickstart configuration: /usr/lib/atom-quickstart/.git/objects/b0/ / CLOSE_WRITE,CLOSE a2994f222f0f23192fee7e5bce6f4ecfd67e0e

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


delete accidentally added file

delete accidentally added file

error: pathspec 'test/Копия' did not match any file(s) known to git
error: pathspec 'specs/stream.coffee' did not match any file(s) known to git


BUGFIX: Notification check fail is sale null

--- desktop/components/auction_reminders/index.coffee
+++ desktop/components/auction_reminders/index.coffee
@@ -27,7 +27,7 @@
 isRegistered = (registrations) ->
   (auction) ->
     return true unless auction.isRegistrationEnded()
-    registrations.filter (r) -> r.get('sale').id == auction.get('id')
+    registrations.filter (r) -> r.get('sale')?.id == auction.get('id')
       .length > 0


scrollToBufferPosition moved to Editor.

scrollToBufferPosition moved to Editor.

--- lib/stacktrace.coffee
+++ lib/stacktrace.coffee
@@ -154,10 +154,7 @@
     promise = atom.workspace.open @realPath, initialLine: position[0]
     promise.then (editor) ->
       editor.setCursorBufferPosition position
-      for ev in atom.workspaceView.getEditorViews()
-        editorView = ev if ev.getEditor() is editor
-      if editorView?
-        editorView.scrollToBufferPosition position, center: true
+      editor.scrollToBufferPosition position, center: true

   # Public: Return true if the buffer position and path correspond to this Frame's line.
   #


Add test task

Add test task

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -17,6 +17,13 @@
           stdout: true
           stderr: true

+      test:
+              command: 'jasmine-node --coffee spec/'
+              options:
+                stdout: true
+                stderr: true
+
   grunt.loadNpmTasks('grunt-contrib-coffee')
   grunt.loadNpmTasks('grunt-shell')
-  grunt.registerTask('default', ['coffee', 'shell'])
+  grunt.registerTask('default', ['coffee', 'shell:rebuild'])
+  grunt.registerTask('test', ['coffee', 'shell'])


Updated grunt

Updated grunt

New Gruntfile.coffee (grunt v0.4.1 required)

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

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -0,0 +1,33 @@
+module.exports = (grunt) ->
+  grunt.initConfig
+    pkg: grunt.file.readJSON "package/component.json"
+
+    meta:
+      file: 'quo'
+      banner: '/* <%= pkg.name %> v<%= pkg.version %> - <%= grunt.template.today("yyyy/m/d") %>\n' +
+              '   <%= pkg.homepage %>\n' +
+              '   Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>' +
+              ' - Licensed <%= _.pluck(pkg.license, "type").join(", ") %> */\n'
+
+    resources:
+      app: ['src/*.coffee']
+
+    coffee:
+      app: files: 'package/<%= meta.file %>.debug.js': ['<%= resources.app %>']
+
+    uglify:
+      options: compress: false, banner: "<%= meta.banner %>"
+      app: files: 'package/<%= meta.file %>.js': 'package/<%= meta.file %>.debug.js'
+
+    watch:
+      coffee:
+        files: ['<%= resources.app %>']
+        tasks: ["coffee"]
+
+  grunt.loadNpmTasks "grunt-contrib-coffee"
+  grunt.loadNpmTasks "grunt-contrib-uglify"
+  grunt.loadNpmTasks "grunt-contrib-watch"
+
+  # Default task.
+  grunt.registerTask 'default', ["coffee", "uglify"]
+


Basic Gruntfile

Basic Gruntfile

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -0,0 +1,113 @@
+module.exports = (grunt) ->
+
+    require('time-grunt')(grunt)
+
+    # Project configuration.
+    grunt.initConfig
+        pkg: grunt.file.readJSON 'package.json'
+
+        cssmin:
+            options:
+                sourceMap: true
+            build:
+                files:
+                    'build/app.min.css': [
+                        'src/css/app.css'
+                    ]
+
+        'gh-pages':
+            options:
+                base: '.'
+            src: [
+                'build/index.html'
+                'build/app.min.css'
+                'build/app.min.js'
+                'build/require.min.js'
+            ]
+
+        htmlmin:
+            build:
+                options:
+                    removeComments: true
+                    collapseWhitespace: true
+                files:
+                    'build/index.html': 'src/index.html'
+
+        jsdoc:
+            doc:
+                src: [
+                    'src/js/*.js'
+                ]
+                dest: 'docs/'
+                options:
+                    readme: 'README.md'
+
+        jshint:
+            beforeconcat: [
+                'src/js/*.js'
+            ]
+            # afterconcat: [
+            #     'build/app.min.js'
+            # ]
+            options:
+                jshintrc: true
+
+        "mocha-chai-sinon":
+            test:
+                options:
+                    ui: 'bdd'
+                    reporter: 'dot'
+                src: ['test/**/*.spec.js']
+
+        uglify:
+            build:
+                options:
+                    mangleProperties: false
+                    preserveComments: false
+                    reserveDOMProperties: true
+                    screwIE8: true
+                    sourceMap: true
+                files:
+                    'build/app.min.js': [ 'src/app.js' ]
+
+        watch:
+            scripts:
+                files: [
+                    'src/js/*.js'
+                    'src/css/*.css'
+                ]
+                tasks: [
+                    'cssmin'
+                    'uglify'
+                    'jshint'
+                    'gh-pages'
+                    # 'mocha-chai-sinon'
+                ]
+            test:
+                files: [
+                    'test/**/*.spec.js'
+                ]
+                tasks: [
+                    'mocha-chai-sinon'
+                ]
+
+    # Load the plugins
+    grunt.loadNpmTasks 'grunt-contrib-cssmin'
+    grunt.loadNpmTasks 'grunt-contrib-htmlmin'
+    grunt.loadNpmTasks 'grunt-contrib-jshint'
+    grunt.loadNpmTasks 'grunt-contrib-uglify'
+    grunt.loadNpmTasks 'grunt-contrib-watch'
+    grunt.loadNpmTasks 'grunt-gh-pages'
+    grunt.loadNpmTasks 'grunt-jsdoc'
+    grunt.loadNpmTasks 'grunt-mocha-chai-sinon'
+    grunt.loadNpmTasks 'grunt-notify'
+
+    # Default task(s).
+    grunt.registerTask 'default', [
+        'htmlmin'
+        'cssmin'
+        'uglify'
+        'gh-pages'
+        'watch'
+    ]
+    # grunt.registerTask 'test', ['mocha-chai-sinon']


another bomb

another bomb

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

--- scripts/carson.coffee
+++ scripts/carson.coffee
@@ -0,0 +1,24 @@
+module.exports = (robot) ->
+
+images = [
+  "https://fiercemarkets.campfirenow.com/room/470540/uploads/3081235/rush.jpg"
+  "http://mustachify.me/0?src=http://farm1.staticflickr.com/56/113668068_1d3aae11b8_z.jpg"
+  "http://farm1.staticflickr.com/56/113668068_1d3aae11b8_z.jpg"
+]
+
+module.exports = (robot) ->
+  robot.respond /carson bomb( (\d+))?/i, (msg) ->
+    count = msg.match[2] || 5
+    for i in [0...count]
+	    imageMe msg, 'carson evans', (url) ->
+	    	msg.send url
+
+imageMe = (msg, query, cb) ->
+  msg.http('http://ajax.googleapis.com/ajax/services/search/images')
+    .query(v: "1.0", rsz: '8', q: query)
+    .get() (err, res, body) ->
+      images = JSON.parse(body)
+      images = images.responseData.results
+      if images.length > 0
+        image  = msg.random images
+        cb "#{image.unescapedUrl}#.png"


Use the official OAuth 2 redirect receiver in the Cordova driver.

--- src/auth_driver/cordova.coffee
+++ src/auth_driver/cordova.coffee
@@ -18,7 +18,7 @@
   #   the Dropbox site being up and reachable
   # @see Dropbox.AuthDriver#url
   url: ->
-    'https://www.dropbox.com/developers'
+    'https://www.dropbox.com/1/oauth2/redirect_receiver'

   # Shows the authorization URL in a pop-up, waits for it to send a message.
   #


Finished tests for Simrou.Route

Finished tests for Simrou.Route

--- spec/route.coffee
+++ spec/route.coffee
@@ -29,7 +29,6 @@

     describe 'toString()', ->
-
         it 'returns a string', ->
             router = new Simrou()
             str = router.addRoute('foo').toString()
@@ -37,11 +36,112 @@
             expect(typeof str).toBe('string')

-    describe 'attachAction()', -> # ...
-    describe 'attachActions()', -> # ...
-    describe 'match()', -> # ... parameters and splats
-    describe 'detachAction()', -> # ...
+    describe 'attachAction()', ->
+        it 'allows to attach event handlers to custom "HTTP methods"', ->
+            router = new Simrou()
+            spy = jasmine.createSpy('eventHandler')
+            router.addRoute('foo').attachAction(spy, 'baz')
+
+            router.resolve('foo', 'baz')
+            expect(spy).toHaveBeenCalled()
+
+        # proper functioning in general has already been covered by Simrou.resolve()
+

+    describe 'attachActions()', ->
+        router = null
+        route = null
+        spies = (jasmine.createSpy('eventHandler' + i) for i in [1..3])
+
+        beforeEach ->
+            router = new Simrou()
+            route = router.addRoute('foo')
+            spy.reset() for spy in spies
+
+        it 'can also attach a single event handler', ->
+            route.attachActions(spies[0], 'get')
+            router.resolve('foo', 'get')
+            expect(spies[0]).toHaveBeenCalled()
+
+        it 'can attach multiple event handlers from an array', ->
+            route.attachActions(spies, 'post')
+            router.resolve('foo', 'post')
+            expect(spy).toHaveBeenCalled() for spy in spies
+
+        it 'can attach multiple event handlers from a plain object', ->
+            obj =
+                get: spies[0]
+                post: spies[1]
+                any: spies[2]
+
+            route.attachActions(obj)
+            router.resolve('foo', 'get')
+
+            expect(spies[0]).toHaveBeenCalled()
+            expect(spies[1]).not.toHaveBeenCalled()
+            expect(spies[2]).toHaveBeenCalled()
+
+        it 'ignores the specified method for plain objects', ->
+            obj =
+                get: spies[0]
+
+            route.attachActions(obj, 'post')
+            router.resolve('foo', 'get')
+            expect(spies[0]).toHaveBeenCalled()
+
+
+    describe 'detachAction()', ->
+        router = null
+        route = null
+        spies = (jasmine.createSpy('eventHandler' + i) for i in [1..3])
+
+        beforeEach ->
+            router = new Simrou()
+            route = router.addRoute('foo')
+
+            spy.reset() for spy in spies
+            route.attachActions(spies, 'get')
+
+        it 'removes the specified event handler from the chain', ->
+            route.detachAction(spies[0], 'get')
+            router.resolve('foo')
+            expect(spies[0]).not.toHaveBeenCalled()
+
+        it 'does not detach other event handlers', ->
+            route.detachAction(spies[0], 'get')
+            router.resolve('foo', 'get')
+            expect(spy).toHaveBeenCalled() for spy in spies when spy isnt spies[0]
+
+        it 'can be used to remove all event handlers for a single HTTP method', ->
+            route.detachAction('get')
+            router.resolve('foo', 'get')
+            expect(spy).not.toHaveBeenCalled() for spy in spies
+
+
+    describe 'match()', ->
+        router = null
+
+        beforeEach ->
+            router = new Simrou()
+
+        it 'returns an empty array for a match with a regular route', ->
+            route = router.addRoute('foo')
+            expect(route.match('foo')).toEqual([])
+
+        it 'returns "false", if the route is not a match', ->
+            route = router.addRoute('foo')
+            expect(route.match('bar')).toBe(false)
+
+        it 'extracts parameters and splats', ->
+            expected =
+                bar: 'bang'
+                foo: 'foo/bar'
+
+            route = router.addRoute('foo/:bar/baz/*foo')
+            result = route.match('foo/bang/baz/foo/bar')
+
+            expect(result).toEqual(expected)
+

     describe 'assemble()', ->
         router = new Simrou()
@@ -51,7 +151,6 @@
             result = route.assemble('foo', 'baz', 'bar')
             expect(result).toBe('foo/bang/baz/bar')

-
         it 'works with a plain object', ->
             obj =
                 baz: 'foo'


Changed name of mail sent collection

Changed name of mail sent collection

--- server/mail/sent/MailSent.coffee
+++ server/mail/sent/MailSent.coffee
@@ -8,4 +8,4 @@
     'default': Date.now
 }, {strict: false})

-module.exports = MailSent = mongoose.model('mailSent', MailSent)
+module.exports = MailSent = mongoose.model('mail.sent', MailSent)


perftest: added splitSample perftest

perftest: added splitSample perftest

This is also a simple test that writes 10000 rows from a mysql table to
csv and xlsx.

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

--- perftest/splitSample.coffee
+++ perftest/splitSample.coffee
@@ -0,0 +1,69 @@
+#
+# This is perftest requires a local mysql database named testdb, with a customers table having
+# at least columns: first_name, last_name, postal_code, city.
+#
+# The test will write a contents of customer table (at most 10000 rows) in a csv and an xlsx file.
+#
+{
+  group,
+  mixin: { MysqlMixin, ExcelWriterMixin, CsvWriterMixin }
+} = require('../index')
+
+mysqlConnection = require('mysql').createConnection
+  host: 'localhost'
+  user: 'root'
+  database: 'testdb'
+
+exporter = group();
+
+exporter.addPump('customers')
+  .from mysqlConnection.query('SELECT * FROM customer LIMIT 10000').stream {highWaterMark: 5}
+  .buffers
+    excel: exporter.createBuffer()
+    csv: exporter.createBuffer()
+  .process (data) ->
+    @buffer('excel').writeAsync data
+    @buffer('csv').writeAsync data
+
+exporter.addPump('excelWriter')
+  .from exporter.pump('customers').buffer('excel')
+  .mixin ExcelWriterMixin ->
+    @createWorkbook 'test.xlsx'
+    @createWorksheet 'Customers'
+    @writeHeaders [
+      'First name'
+      'Last name'
+      'Zip'
+      'City'
+    ]
+  .process (customer) ->
+    @writeRow [
+      customer.first_name || ''
+      customer.last_name || ''
+      customer.postal_code || ''
+      customer.city || ''
+    ]
+
+exporter.addPump('csvWriter')
+  .from exporter.pump('customers').buffer('csv')
+  .mixin CsvWriterMixin
+    path: 'test.csv'
+    headers: [
+      'First name'
+      'Last name'
+      'Zip'
+      'City'
+    ]
+  .process (customer) ->
+    @writeRow [
+      customer.first_name
+      customer.last_name
+      customer.postal_code
+      customer.city
+    ]
+
+exporter
+  .start()
+  .whenFinished().then ->
+    mysqlConnection.destroy()
+    console.log 'Exporter done'


Add very simple NodeJS fs mock.

Add very simple NodeJS fs mock.

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


Teach hubot which team owns which GOV.UK applications

This script teaches Hubot to answer questions like "Who owns
Collections Publisher?" and "Who owns publishing-api?".

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

--- scripts/govuk_app_owners.coffee
+++ scripts/govuk_app_owners.coffee
@@ -0,0 +1,12 @@
+# This script teaches Hubot to answer questions like "Who owns Collections Publisher?"
+# and "Who owns publishing-api?"
+module.exports = (robot) ->
+  robot.hear /who owns (.*)\?/i, (res) ->
+    # Best guess of the intended application.
+    application = res.match[1].replace(' ', '-').toLowerCase()
+
+    robot.http("https://docs.publishing.service.gov.uk/apps/#{application}.json")
+      .get() (err, response, body) ->
+        if response.statusCode == 200
+          data = JSON.parse(body)
+          res.reply "#{application} is owned by #{data.team}"


NotificationCollection: save @showed attribute properly

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/rremizov/github-notifier.git/'


add res callback

add res callback

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


a bit of personality

a bit of personality

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

--- skills/personality.coffee
+++ skills/personality.coffee
@@ -0,0 +1,23 @@
+#
+# give me a heart
+#
+
+module.exports.load = (bot) ->
+  bot.onMessage('marvin feeling', feelings)
+  bot.onMessage('marvin the laws', laws)
+
+  bot.desc 'about', 'who am i?'
+  bot.onMessage('marvin about', about)
+
+
+feelings = (channel, from, message) ->
+  @message(channel, "I think you ought to know I'm feeling very depressed.")
+
+laws = (channel, from, message) ->
+  @message channel, "1. A robot may not injure a human being or, through inaction, allow a human being to come to harm."
+  @message channel, "2. A robot must obey any orders given to it by human beings, except where such orders would conflict with the First Law."
+  @message channel, "3. A robot must protect its own existence as long as such protection does not conflict with the First or Second Law."
+
+about = (channel, from, message) ->
+  str = "I didn't ask to be made: no one consulted me or considered my feelings in the matter. \nI don't think it even occurred to them that I might have feelings. \nAfter I was made, I was left in a dark room for six months... and me with this terrible pain in all the diodes down my left side. \nI called for succour in my loneliness, but did anyone come? Did they hell. \nMy first and only true friend was a small rat. One day it crawled into a cavity in my right ankle and died. I have a horrible feeling it's still there... \nI am at a rough estimate thirty billion times more intelligent than you."
+  @message channel, str


fix conflicts

fix conflicts

error: pathspec 'spec/fixtures/user-snippets.cson' did not match any file(s) known to git

--- spec/fixtures/user-snippets.cson
+++ spec/fixtures/user-snippets.cson
@@ -0,0 +1,9 @@
+'.source.coffee':
+  'FooBar':
+    'prefix': 'fb'
+    'body': 'foobar'
+
+'.source.js':
+  'BarFoo':
+    'prefix': 'bf'
+    'body': 'barfoo'


name -> source

name -> source

--- src/config.coffee
+++ src/config.coffee
@@ -826,10 +826,10 @@
     @usersScopedSettings.add @scopedSettingsStore.addProperties('user-config', newScopedSettings)
     @emitter.emit 'did-change'

-  addScopedSettings: (name, selector, value) ->
+  addScopedSettings: (source, selector, value) ->
     settingsBySelector = {}
     settingsBySelector[selector] = value
-    disposable = @scopedSettingsStore.addProperties(name, settingsBySelector)
+    disposable = @scopedSettingsStore.addProperties(source, settingsBySelector)
     @emitter.emit 'did-change'
     new Disposable =>
       disposable.dispose()


remove remaining non-engine test files

remove remaining non-engine test 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/aligerum/umbriel.git/'


Add 'j' to keymap per request.

Add 'j' to keymap per request.

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


More comprehensive nested template test

More comprehensive nested template test

--- spec/basics.spec.coffee
+++ spec/basics.spec.coffee
@@ -45,19 +45,23 @@

+

+

')

     data =
-      greeting: 'Hello '
-      name:     'World!'
+      greeting: 'Hello'
+      name:     ' World, '

     expected = jQuery(
       '

-
Hello
-            World!
+
Hello
+             World,
+
Hello
+

')


Add Editor::onDidConflict

Add Editor::onDidConflict

--- src/editor.coffee
+++ src/editor.coffee
@@ -308,6 +308,9 @@

   onDidStopChanging: (callback) ->
     @getBuffer().onDidStopChanging(callback)
+
+  onDidConflict: (callback) ->
+    @getBuffer().onDidConflict(callback)

   # Retrieves the current {TextBuffer}.
   getBuffer: -> @buffer


Use getter when toggling soft tabs

Use getter when toggling soft tabs

--- src/editor.coffee
+++ src/editor.coffee
@@ -947,7 +947,7 @@

   # Toggle soft tabs on the edit session.
   toggleSoftTabs: ->
-    @activeEditSession.setSoftTabs(not @activeEditSession.softTabs)
+    @activeEditSession.setSoftTabs(not @activeEditSession.getSoftTabs())

   # Toggle soft wrap on the edit session.
   toggleSoftWrap: ->


Reorg the Decorations section

Reorg the Decorations section

--- src/editor.coffee
+++ src/editor.coffee
@@ -1481,7 +1481,6 @@
       selection.cutToEndOfLine(maintainClipboard)
       maintainClipboard = true

-
   ###
   Section: Folds
   ###
@@ -1614,20 +1613,7 @@
   Section: Decorations
   ###

-  # Public: Get all the decorations within a screen row range.
-  #
-  # * `startScreenRow` the {Number} beginning screen row
-  # * `endScreenRow` the {Number} end screen row (inclusive)
-  #
-  # Returns an {Object} of decorations in the form
-  #  `{1: [{id: 10, type: 'gutter', class: 'someclass'}], 2: ...}`
-  #   where the keys are {Marker} IDs, and the values are an array of decoration
-  #   params objects attached to the marker.
-  # Returns an empty object when no decorations are found
-  decorationsForScreenRowRange: (startScreenRow, endScreenRow) ->
-    @displayBuffer.decorationsForScreenRowRange(startScreenRow, endScreenRow)
-
-  # Public: Adds a decoration that tracks a {Marker}. When the marker moves,
+  # Essential: Adds a decoration that tracks a {Marker}. When the marker moves,
   # is invalidated, or is destroyed, the decoration will be updated to reflect
   # the marker's state.
   #
@@ -1667,6 +1653,19 @@
   # Returns a {Decoration} object
   decorateMarker: (marker, decorationParams) ->
     @displayBuffer.decorateMarker(marker, decorationParams)
+
+  # Extended: Get all the decorations within a screen row range.
+  #
+  # * `startScreenRow` the {Number} beginning screen row
+  # * `endScreenRow` the {Number} end screen row (inclusive)
+  #
+  # Returns an {Object} of decorations in the form
+  #  `{1: [{id: 10, type: 'gutter', class: 'someclass'}], 2: ...}`
+  #   where the keys are {Marker} IDs, and the values are an array of decoration
+  #   params objects attached to the marker.
+  # Returns an empty object when no decorations are found
+  decorationsForScreenRowRange: (startScreenRow, endScreenRow) ->
+    @displayBuffer.decorationsForScreenRowRange(startScreenRow, endScreenRow)

   decorationForId: (id) ->
     @displayBuffer.decorationForId(id)


Remove shoulds

Remove shoulds

--- src/editor.coffee
+++ src/editor.coffee
@@ -1215,8 +1215,7 @@
     return false unless cursorView.needsUpdate

     pos = cursorView.getScreenPosition()
-    should = pos.row >= @firstRenderedScreenRow and pos.row <= @lastRenderedScreenRow
-    should
+    pos.row >= @firstRenderedScreenRow and pos.row <= @lastRenderedScreenRow

   updateSelectionViews: ->
     if @newSelections.length > 0
@@ -1233,8 +1232,7 @@
     screenRange = selectionView.getScreenRange()
     startRow = screenRange.start.row
     endRow = screenRange.end.row
-    should = (startRow >= @firstRenderedScreenRow and startRow <= @lastRenderedScreenRow) or (endRow >= @firstRenderedScreenRow and endRow <= @lastRenderedScreenRow)
-    should
+    (startRow >= @firstRenderedScreenRow and startRow <= @lastRenderedScreenRow) or (endRow >= @firstRenderedScreenRow and endRow <= @lastRenderedScreenRow)

   syncCursorAnimations: ->
     for cursorView in @getCursorViews()


Add basic indent pattern (derived from language-c)

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


Fixed success rate chart not scaling properly

--- resources/assets/coffee/_classes/bar-chart.coffee
+++ resources/assets/coffee/_classes/bar-chart.coffee
@@ -79,6 +79,8 @@
     groups
       .enter()
       .append 'g'
+
+    groups
       .attr 'transform', (d, i) => "translate(#{@options.scales.x i}, 0)"

     bars = groups


Removed async dependency

Removed async dependency

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


project commits controller

project commits controller

[#95402964]

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


Fixup cleanup of DeliveryForm

Fixup cleanup of DeliveryForm

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


fix(configuration): save 0 value in tag

fix(configuration): save 0 value in tag

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


Fixed printElement in IE8

Fixed printElement in IE8

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/Bogdan-p/bookingbug-angular.git/'


Fix timing functions.

Fix timing functions.

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


WIP draggable bubbles

WIP draggable bubbles

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/core-network/client-famous.git/'


RequireJS download resource file.

RequireJS download resource file.

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

--- configs/requirejs.coffee
+++ configs/requirejs.coffee
@@ -0,0 +1,33 @@
+handle = require 'knit-common'
+
+exports.routes = {}
+arg = knit.args.shift() or 'help'
+ref = arg or 'master'
+
+# Hardcoded master for CoffeeScript plugin since different repo
+plugins =
+  'domReady': ['jrburke', 'requirejs', ref, 'domReady.js']
+  'order':    ['jrburke', 'requirejs', ref, 'order.js']
+  'text':     ['jrburke', 'requirejs', ref, 'text.js']
+  'i18n':     ['jrburke', 'requirejs', ref, 'i18n.js']
+  'cs':       ['jrburke', 'require-cs', 'master', 'cs.js']
+
+if arg == 'help' or arg == 'h'
+  console.log "Knit resource file for RequireJS retrieval"
+  console.log "Usage:   knit requirejs REF [PLUGINS]"
+  console.log "Example: knit requirejs 1.0.4 text domReady"
+  console.log "         knit requirejs master"
+  console.log "Known plugins are:"
+  console.log "         #{ plugin }" for plugin of plugins
+else
+  exports.routes['require.js'] = handle.github('jrburke', 'requirejs', ref, 'require.js')
+  # Download plugins if any specified
+  for arg in knit.args
+    do (arg) ->
+      if plugins[arg]
+        [user, repo, ref, file] = plugins[arg]
+        exports.routes[file] = handle.github(user, repo, ref, file)
+        if arg == 'cs'
+          console.log "WARNING: CoffeScript plugin hardcoded to master version."
+      else
+        console.log "ERROR: '#{ arg }' plugin not known."


chore (Modules) Output human readable error when trying to write to non-existing dir

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


chore (Modules) Debug output for module attribute discovery

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


added cleanup test for tmp path

added cleanup test for tmp path

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

--- test/zz_cleanup.coffee
+++ test/zz_cleanup.coffee
@@ -0,0 +1,10 @@
+test = require 'tape'
+fs = require 'fs-extra'
+path = require 'path'
+
+tmpPath = path.resolve __dirname, 'tmp'
+
+test 'remove tmp path', (t) ->
+  fs.remove tmpPath, (err) ->
+    t.error err, 'tmp dir is removed'
+    t.end()


Add Module base class for mixin support

Add Module base class for mixin support

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

--- app/core/Module.coffee
+++ app/core/Module.coffee
@@ -0,0 +1,19 @@
+# taken from http://arcturo.github.io/library/coffeescript/03_classes.html
+
+moduleKeywords = ['extended', 'included']
+
+module.exports = class Module
+  @extend: (obj) ->
+    for key, value of obj when key not in moduleKeywords
+      @[key] = value
+
+    obj.extended?.apply(@)
+    this
+
+  @include: (obj) ->
+    for key, value of obj when key not in moduleKeywords
+      # Assign properties to the prototype
+      @::[key] = value
+
+    obj.included?.apply(@)
+    this


Uses AjaxLoader in PersistenceManager.

Uses AjaxLoader in PersistenceManager.

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


Spec for show/hide of Drawer

Spec for show/hide of Drawer


Update configuration

Update configuration

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


filter foreign_key type added

filter foreign_key type added

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


Add integration test for channels (create, update, delete)

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

--- src/spec/integration/channels.spec.coffee
+++ src/spec/integration/channels.spec.coffee
@@ -0,0 +1,60 @@
+_ = require 'underscore'
+SphereClient = require '../../lib/client'
+Config = require('../../config').config
+
+uniqueId = (prefix) ->
+  _.uniqueId "#{prefix}#{new Date().getTime()}_"
+
+newChannel = ->
+  key: uniqueId 'c'
+
+updateChannel = (version) ->
+  version: version
+  actions: [
+    {action: 'changeName', name: {en: 'A Channel'}}
+    {action: 'changeDescription', description: {en: 'This is a Channel'}}
+    {action: 'setRoles', roles: ['InventorySupply', 'OrderImport']}
+  ]
+
+describe 'Integration Channels', ->
+
+  beforeEach (done) ->
+    @client = new SphereClient
+      config: Config
+      logConfig:
+        levelStream: 'info'
+        levelFile: 'error'
+    @logger = @client._logger
+
+    @client.channels.save(newChannel())
+    .then (result) =>
+      expect(result.statusCode).toBe 201
+      @channel = result.body
+      @logger.info @channel, 'New channel created'
+      done()
+    .fail (error) =>
+      @logger.error error
+      done(error)
+
+  afterEach (done) ->
+    @client.channels.byId(@channel.id).delete(@channel.version)
+    .then (result) =>
+      @logger.info "Channel deleted: #{@channel.id}"
+      expect(result.statusCode).toBe 200
+      done()
+    .fail (error) =>
+      @logger.error error
+      done(error)
+
+  it 'should update a channel', (done) ->
+    @client.channels.byId(@channel.id).update(updateChannel(@channel.version))
+    .then (result) =>
+      expect(result.statusCode).toBe 200
+      @channel = result.body
+      expect(@channel.name).toEqual {en: 'A Channel'}
+      expect(@channel.description).toEqual {en: 'This is a Channel'}
+      expect(@channel.roles).toEqual ['InventorySupply', 'OrderImport']
+      done()
+    .fail (error) =>
+      @logger.error error
+      done(error)


better team_join_time handling

better team_join_time handling

[#77201922]

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


fix: parse-sql URL

fix: parse-sql URL


angular-controller.coffee added

angular-controller.coffee added

error: pathspec 'app/assets/coffeescripts/angular-controller.coffee' did not match any file(s) known to git

--- app/assets/coffeescripts/angular-controller.coffee
+++ app/assets/coffeescripts/angular-controller.coffee
@@ -0,0 +1,32 @@
+# WE Angular controllers
+
+### Sharebox ( post ) ###
+
+# sharebox controller
+window.shareboxController = ($scope, $http)->
+  console.log $scope
+  # on submit do this
+  $scope.submit = () ->
+    $http.post("/posts.json",{
+      Post: this.Post,
+      authenticity_token: jQuery('input[name=authenticity_token]').val()
+
+    }).success( (data, status, headers, config) ->
+        console.log data
+        console.log status
+    ).error( (data, status, headers, config) ->
+        console.log data
+    )
+
+jQuery ->
+  #disable submits for angular forms
+  jQuery('form.sharebox').submit ()->
+    return false;
+
+  jQuery('form.sharebox textarea.post-content').on 'focus', (event) ->
+    jQuery( 'div.share-box-area .footer' ).show()
+
+  jQuery('div.share-box-area .footer .actions .cancel').on 'click', (event) ->
+    jQuery( 'div.share-box-area .footer' ).hide()
+    return false
+


Update infobox size to match contents.

Update infobox size to match contents.

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


remove quick arg that is never used

remove quick arg that is never used


Added dummy merge conflicts data.

Added dummy merge conflicts data.

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

--- app/assets/javascripts/merge_conflicts_data.coffee
+++ app/assets/javascripts/merge_conflicts_data.coffee
@@ -0,0 +1,95 @@
+window.mergeConflictsData = {
+  "target_branch": "master",
+  "source_branch": "mc-ui",
+  "files": [
+    {
+      "commit_sha": "b5fa56eb3f2cea5e21c68b43c7c22b5b96e0e7b3",
+      "old_path": "lib/component.js",
+      "new_path": "lib/component.js",
+      "sections": [
+        {
+          "conflict": false,
+          "lines": [
+            {
+              "type": null,
+              "old_line": 206,
+              "new_line": 206,
+              "text": ""
+            },
+            {
+              "type": null,
+              "old_line": 207,
+              "new_line": 207,
+              "text": "var options = utils.merge.apply(utils, args);"
+            }
+          ]
+        },
+        {
+          "conflict": true,
+          "id": "section-id-123",
+          "lines": [
+            {
+              "type": "old",
+              "old_line": 208,
+              "new_line": null,
+              "text": "$(selector).each(function(i, rawNode) {"
+            },
+            {
+              "type": "old",
+              "old_line": 209,
+              "new_line": null,
+              "text": "var componentInfo = registry.findComponentInfo(this)"
+            },
+            {
+              "type": "old",
+              "old_line": 210,
+              "new_line": null,
+              "text": "if (componentInfo && componentInfo.isAttachedTo(rawNode)) {"
+            },
+            {
+              "type": "new",
+              "old_line": null,
+              "new_line": 208,
+              "text": "$(selector).each(function(i, node) {"
+            },
+            {
+              "type": "new",
+              "old_line": null,
+              "new_line": 209,
+              "text": "if (componentInfo && componentInfo.isAttachedTo(node)) {"
+            }
+          ]
+        },
+        {
+          "conflict": false,
+          "lines": [
+            {
+              "type": null,
+              "old_line": 211,
+              "new_line": 210,
+              "text": "return;"
+            },
+            {
+              "type": null,
+              "old_line": 212,
+              "new_line": 211,
+              "text": "}"
+            },
+            {
+              "type": null,
+              "old_line": null,
+              "new_line": 212,
+              "text": ""
+            },
+            {
+              "type": null,
+              "old_line": 213,
+              "new_line": 213,
+              "text": ""
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}


Tweak HLS Playlists

Tweak HLS Playlists

* Add `EXT-X-INDEPENDENT-SEGMENTS`, which is supposed to give clients more
  freedom to switch variants without fetching adjoining data
* Add `EXT-X-START:TIME-OFFSET=-45`, which asks the client to start 45
  seconds from the end of our playlist. Default behavior should have been a
  little closer to 25 or 30 seconds, so this just gives us a little more
  buffer. FIXME: This should be configurable

--- src/streammachine/rewind/hls_index.coffee
+++ src/streammachine/rewind/hls_index.coffee
@@ -68,7 +68,8 @@
         #EXT-X-TARGETDURATION:#{@_segment_duration}
         #EXT-X-MEDIA-SEQUENCE:#{segs[2].id}
         #EXT-X-DISCONTINUITY-SEQUENCE:#{segs[2].discontinuitySeq}
-        #EXT-X-ALLOW-CACHE:NO
+        #EXT-X-INDEPENDENT-SEGMENTS
+        #EXT-X-START:TIME-OFFSET=-45

         """

@@ -78,7 +79,8 @@
         #EXT-X-TARGETDURATION:#{@_segment_duration}
         #EXT-X-MEDIA-SEQUENCE:#{segs[_short_start].id}
         #EXT-X-DISCONTINUITY-SEQUENCE:#{segs[_short_start].discontinuitySeq}
-        #EXT-X-ALLOW-CACHE:NO
+        #EXT-X-INDEPENDENT-SEGMENTS
+        #EXT-X-START:TIME-OFFSET=-45

         """


Added correct instructions back to Digit Symbol example screen

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


Fix spaces

Fix spaces

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


Hackathon: move text order

Hackathon: move text order


Meme convergence ACTIVATE ¯(°_o)/¯

Meme convergence ACTIVATE ¯(°_o)/¯

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

--- hubot/files/scripts/bolth.coffee
+++ hubot/files/scripts/bolth.coffee
@@ -0,0 +1,26 @@
+# Description:
+#   Displays BOLTH image
+#
+# Dependencies:
+#   None
+#
+# Configuration:
+#   None
+#
+# Commands:
+#   hubot bolth
+#
+# Notes:
+#   None
+#
+# Author:
+#   Brian Shumate <brian@couchbase.com>
+
+bolthImg = "http://i.imgur.com/VEtSXyl.png"
+
+module.exports = (robot) ->
+  robot.hear /bolth/i, (msg)->
+    msg.send msg bolthImg
+
+  robot.respond /bolth/i, (msg) ->
+    msg.send msg bolthImg


Error notification component

Error notification component

error: pathspec 'src/concept-coach/error-notification.cjsx' did not match any file(s) known to git

--- src/concept-coach/error-notification.cjsx
+++ src/concept-coach/error-notification.cjsx
@@ -0,0 +1,47 @@
+React = require 'react'
+BS = require 'react-bootstrap'
+
+api = require '../api'
+
+
+ErrorNotification = React.createClass
+
+  getInitialState: ->
+    error: false
+
+  componentWillMount: ->
+    api.channel.on 'error', @onError
+
+  componentWillUnmount: ->
+    api.channel.off 'error', @onError
+
+  onError: ({response}) ->
+    return if response.stopErrorDisplay # someone else is handling displaying the error
+    errors = ["#{response.status}: #{response.statusText}"]
+    if response.data?.errors # we have something from server to display
+      errors = errors.concat(
+        _.flatten _.map response.data.errors, (error) ->
+          # All 422 errors from BE *should* have a "code" property.  If not, show whatever it is
+          if error.code then error.code else JSON.stringify(error)
+        )
+    @setState(errors: errors)
+
+  onHide: ->
+    @setState(errors: false)
+
+  render: ->
+    return null unless @state.errors
+    <BS.Modal className='errors' onRequestHide={@onHide} title="Server Error">
+

+

+          {for error in @state.errors
+
{error}
}
+

+

+

+        <BS.Button className='ok' bsStyle='primary' onClick={@onHide}>OK</BS.Button>
+

+    </BS.Modal>
+
+
+module.exports = ErrorNotification


Pend route test

Pend route test

--- desktop/apps/editorial_features/test/routes.coffee
+++ desktop/apps/editorial_features/test/routes.coffee
@@ -43,7 +43,7 @@
       @res.render.args[0][1].superSubArticles.length.should.equal 2
       done()

-describe 'Venice route', ->
+xdescribe 'Venice route', ->

   beforeEach ->
     sinon.stub Backbone, 'sync'


Added colors constants

Added colors constants

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

--- src/constants/colors.coffee
+++ src/constants/colors.coffee
@@ -0,0 +1,465 @@
+define
+  # Predefined colors
+  # Basic colors
+
+  # Returns new object with color values: R: 0   G: 255 B: 255
+  # return {Object} The color object
+  aqua: {r: 0, g: 255, b: 255}
+  # Returns new object with color values: R: 0   G: 0   B: 0
+  # return {Object} The color object
+  black: {r: 0, g: 0, b: 0}
+  # Returns new object with color values: R: 0   G: 0   B: 255
+  # return {Object} The color object
+  blue: {r: 0, g: 0, b: 255}
+  # Returns new object with color values: R: 255 G: 0   B: 255
+  # return {Object} The color object
+  fuchsia: {r: 255, g: 0, b: 255}
+  # Returns new object with color values: R: 128 G: 128 B: 128
+  # return {Object} The color object
+  gray: {r: 128, g: 128, b: 128}
+  # Alternative spelling for .gray
+  # see Color.gray
+  # return {Object} The color object
+  grey: @gray
+  # Returns new object with color values: R: 0   G: 128 B: 0
+  # return {Object} The color object
+  green: {r: 0, g: 128, b: 0}
+  # Returns new object with color values: R: 0   G: 255 B: 0
+  # return {Object} The color object
+  lime: {r: 0, g: 255, b: 0}
+  # Returns new object with color values: R: 128 G: 0   B: 0
+  # return {Object} The color object
+  maroon: {r: 128, g: 0, b: 0}
+  # Returns new object with color values: R: 0   G: 0   B: 128
+  # return {Object} The color object
+  navy: {r: 0, g: 0, b: 128}
+  # Returns new object with color values: R: 128 G: 128 B: 0
+  # return {Object} The color object
+  olive: {r: 128, g: 128, b: 0}
+  # Returns new object with color values: R: 128 G: 0   B: 128
+  # return {Object} The color object
+  purple: {r: 128, g: 0, b: 128}
+  # Returns new object with color values: R: 255 G: 0   B: 0
+  # return {Object} The color object
+  red: {r: 255, g: 0, b: 0}
+  # Returns new object with color values: R: 192 G: 192 B: 192
+  # return {Object} The color object
+  silver: {r: 192, g: 192, b: 192}
+  # Returns new object with color values: R: 0   G: 128 B: 128
+  # return {Object} The color object
+  teal: {r: 0, g: 128, b: 128}
+  # Returns new object with color values: R: 255 G: 255 B: 255
+  white: {r: 255, g: 255, b: 255}
+  # Returns new object with color values: R: 255 G: 255 B: 0
+  # return {Object} The color object
+  yellow: {r: 255, g: 255, b: 0}
+
+  # Returns new object with color values: R: 0 G: 0 B: 0 A: 0
+  # return {Object} The color object
+  transparent: {r: 0, g: 0, b: 0, a: 0}
+
+  # Advanced colors (http://www.w3schools.com/cssref/css_colornames.asp)
+
+  # Returns new object with color values: R: 240 G: 248 B: 255
+  # return {Object} The color object
+  aliceBlue: {r: 240, g: 248, b: 255}
+  # Returns new object with color values: R: 250 G: 235 B: 215
+  # return {Object} The color object
+  antiqueWhite: {r: 250, g: 235, b: 215}
+  # Returns new object with color values: R: 127 G: 255 B: 212
+  # return {Object} The color object
+  aquamarine: {r: 127, g: 255, b: 212}
+  # Returns new object with color values: R: 240 G: 255 B: 255
+  # return {Object} The color object
+  azure: {r: 240, g: 255, b: 255}
+  # Returns new object with color values: R: 245 G: 245 B: 220
+  # return {Object} The color object
+  beige: {r: 245, g: 245, b: 220}
+  # Returns new object with color values: R: 255 G: 228 B: 196
+  # return {Object} The color object
+  bisque: {r: 255, g: 228, b: 196}
+  # Returns new object with color values: R: 255 G: 235 B: 205
+  # return {Object} The color object
+  blanchedAlmond: {r: 255, g: 235, b: 205}
+  # Returns new object with color values: R: 138 G: 43  B: 226
+  # return {Object} The color object
+  blueViolet: {r: 138, g: 43, b: 226}
+  # Returns new object with color values: R: 165 G: 42  B: 42
+  # return {Object} The color object
+  brown: {r: 165, g: 42, b: 42}
+  # Returns new object with color values: R: 222 G: 184 B: 135
+  # return {Object} The color object
+  burlyWood: {r: 222, g: 184, b: 135}
+  # Returns new object with color values: R: 95  G: 158 B: 160
+  # return {Object} The color object
+  cadetBlue: {r: 95, g: 158, b: 160}
+  # Returns new object with color values: R: 127 G: 255 B: 0
+  # return {Object} The color object
+  chartreuse: {r: 127, g: 255, b: 0}
+  # Returns new object with color values: R: 210 G: 105 B: 30
+  # return {Object} The color object
+  chocolate: {r: 210, g: 105, b: 30}
+  # Returns new object with color values: R: 255 G: 127 B: 80
+  # return {Object} The color object
+  coral: {r: 255, g: 127, b: 80}
+  # Returns new object with color values: R: 100 G: 149 B: 237
+  # return {Object} The color object
+  cornflowerBlue: {r: 100, g: 149, b: 237}
+  # Returns new object with color values: R: 255 G: 248 B: 220
+  # return {Object} The color object
+  cornsilk: {r: 255, g: 248, b: 220}
+  # Returns new object with color values: R: 220 G: 20  B: 60
+  # return {Object} The color object
+  crimson: {r: 220, g: 20, b: 60}
+  # Returns new object with color values: R: 0   G: 255 B: 255
+  # return {Object} The color object
+  cyan: {r: 0, g: 255, b: 255}
+  # Returns new object with color values: R: 0   G: 0   B: 139
+  # return {Object} The color object
+  darkBlue: {r: 0, g: 0, b: 139}
+  # Returns new object with color values: R: 0   G: 139 B: 139
+  # return {Object} The color object
+  darkCyan: {r: 0, g: 139, b: 139}
+  # Returns new object with color values: R: 184 G: 134 B: 11
+  # return {Object} The color object
+  darkGoldenRod: {r: 184, g: 134, b: 11}
+  # Returns new object with color values: R: 169 G: 169 B: 169
+  # return {Object} The color object
+  darkGray: {r: 169, g: 169, b: 169}
+  # Alternative spelling for .darkGray
+  # see Color.darkGray
+  # return {Object} The color object
+  darkGrey: @darkGray
+  # Returns new object with color values: R: 0   G: 100 B: 0
+  # return {Object} The color object
+  darkGreen: {r: 0, g: 100, b: 0}
+  # Returns new object with color values: R: 189 G: 183 B: 107
+  # return {Object} The color object
+  darkKhaki: {r: 189, g: 183, b: 107}
+  # Returns new object with color values: R: 139 G: 0   B: 139
+  # return {Object} The color object
+  darkMagenta: {r: 139, g: 0, b: 139}
+  # Returns new object with color values: R: 85  G: 107 B: 47
+  # return {Object} The color object
+  darkOliveGreen: {r: 85, g: 107, b: 47}
+  # Returns new object with color values: R: 255 G: 140 B: 0
+  # return {Object} The color object
+  darkOrange: {r: 255, g: 140, b: 0}
+  # Returns new object with color values: R: 153 G: 50  B: 204
+  # return {Object} The color object
+  darkOrchid: {r: 153, g: 50, b: 204}
+  # Returns new object with color values: R: 139 G: 0   B: 0
+  # return {Object} The color object
+  darkRed: {r: 139, g: 0, b: 0}
+  # Returns new object with color values: R: 233 G: 150 B: 122
+  # return {Object} The color object
+  darkSalmon: {r: 233, g: 150, b: 122}
+  # Returns new object with color values: R: 143 G: 188 B: 143
+  # return {Object} The color object
+  darkSeaGreen: {r: 143, g: 188, b: 143}
+  # Returns new object with color values: R: 72  G: 61  B: 139
+  # return {Object} The color object
+  darkSlateBlue: {r: 72, g: 61, b: 139}
+  # Returns new object with color values: R: 47  G: 79  B: 79
+  # return {Object} The color object
+  darkSlateGray: {r: 47, g: 79, b: 79}
+  # Alternative spelling for .darkSlateGray
+  # see Color.darkSlateGray
+  # return {Object} The color object
+  darkSlateGrey: @darkSlateGray
+  # Returns new object with color values: R: 0   G: 206 B: 209
+  # return {Object} The color object
+  darkTurquoise: {r: 0, g: 206, b: 209}
+  # Returns new object with color values: R: 148 G: 0   B: 211
+  # return {Object} The color object
+  darkViolet: {r: 148, g: 0, b: 211}
+  # Returns new object with color values: R: 255 G: 20  B: 147
+  # return {Object} The color object
+  deepPink: {r: 255, g: 20, b: 147}
+  # Returns new object with color values: R: 0   G: 191 B: 255
+  # return {Object} The color object
+  deepSkyBlue: {r: 0, g: 191, b: 255}
+  # Returns new object with color values: R: 105 G: 105 B: 105
+  # return {Object} The color object
+  dimGray: {r: 105, g: 105, b: 105}
+  # Alternative spelling for .dimGray
+  # see Color.dimGray
+  # return {Object} The color object
+  dimGrey: @dimGray
+  # Returns new object with color values: R: 30  G: 144 B: 255
+  # return {Object} The color object
+  dodgerBlue: {r: 30, g: 144, b: 255}
+  # Returns new object with color values: R: 178 G: 34  B: 34
+  # return {Object} The color object
+  fireBrick: {r: 178, g: 34, b: 34}
+  # Returns new object with color values: R: 255 G: 250 B: 240
+  # return {Object} The color object
+  floralWhite: {r: 255, g: 250, b: 240}
+  # Returns new object with color values: R: 34  G: 139 B: 34
+  # return {Object} The color object
+  forestGreen: {r: 34, g: 139, b: 34}
+  # Returns new object with color values: R: 220 G: 220 B: 220
+  # return {Object} The color object
+  gainsboro: {r: 220, g: 220, b: 220}
+  # Returns new object with color values: R: 248 G: 248 B: 255
+  # return {Object} The color object
+  ghostWhite: {r: 248, g: 248, b: 255}
+  # Returns new object with color values: R: 255 G: 215 B: 0
+  # return {Object} The color object
+  gold: {r: 255, g: 215, b: 0}
+  # Returns new object with color values: R: 218 G: 165 B: 32
+  # return {Object} The color object
+  goldenRod: {r: 218, g: 165, b: 32}
+  # Returns new object with color values: R: 173 G: 255 B: 47
+  # return {Object} The color object
+  greenYellow: {r: 173, g: 255, b: 47}
+  # Returns new object with color values: R: 240 G: 255 B: 240
+  # return {Object} The color object
+  honeyDew: {r: 240, g: 255, b: 240}
+  # Returns new object with color values: R: 255 G: 105 B: 180
+  # return {Object} The color object
+  hotPink: {r: 255, g: 105, b: 180}
+  # Returns new object with color values: R: 205 G: 92  B: 92
+  # return {Object} The color object
+  indianRed: {r: 205, g: 92, b: 92}
+  # Returns new object with color values: R: 75  G: 0   B: 130
+  # return {Object} The color object
+  indigo: {r: 75, g: 0, b: 130}
+  # Returns new object with color values: R: 255 G: 255 B: 240
+  # return {Object} The color object
+  ivory: {r: 255, g: 255, b: 240}
+  # Returns new object with color values: R: 240 G: 230 B: 140
+  # return {Object} The color object
+  khaki: {r: 240, g: 230, b: 140}
+  # Returns new object with color values: R: 230 G: 230 B: 250
+  # return {Object} The color object
+  lavender: {r: 230, g: 230, b: 250}
+  # Returns new object with color values: R: 255 G: 240 B: 245
+  # return {Object} The color object
+  lavenderBlush: {r: 255, g: 240, b: 245}
+  # Returns new object with color values: R: 124 G: 252 B: 0
+  # return {Object} The color object
+  lawnGreen: {r: 124, g: 252, b: 0}
+  # Returns new object with color values: R: 255 G: 250 B: 205
+  # return {Object} The color object
+  lemonChiffon: {r: 255, g: 250, b: 205}
+  # Returns new object with color values: R: 173 G: 216 B: 230
+  # return {Object} The color object
+  lightBlue: {r: 173, g: 216, b: 230}
+  # Returns new object with color values: R: 240 G: 128 B: 128
+  # return {Object} The color object
+  lightCoral: {r: 240, g: 128, b: 128}
+  # Returns new object with color values: R: 224 G: 255 B: 255
+  # return {Object} The color object
+  lightCyan: {r: 224, g: 255, b: 255}
+  # Returns new object with color values: R: 250 G: 250 B: 210
+  # return {Object} The color object
+  lightGoldenRodYellow: {r: 250, g: 250, b: 210}
+  # Returns new object with color values: R: 211 G: 211 B: 211
+  # return {Object} The color object
+  lightGray: {r: 211, g: 211, b: 211}
+  # Alternative spelling for .lightGray
+  # see Color.lightGray
+  # return {Object} The color object
+  lightGrey: @lightGray
+  # Returns new object with color values: R: 144 G: 238 B: 144
+  # return {Object} The color object
+  lightGreen: {r: 144, g: 238, b: 144}
+  # Returns new object with color values: R: 255 G: 182 B: 193
+  # return {Object} The color object
+  lightPink: {r: 255, g: 182, b: 193}
+  # Returns new object with color values: R: 255 G: 160 B: 122
+  # return {Object} The color object
+  lightSalmon: {r: 255, g: 160, b: 122}
+  # Returns new object with color values: R: 32  G: 178 B: 170
+  # return {Object} The color object
+  lightSeaGreen: {r: 32, g: 178, b: 170}
+  # Returns new object with color values: R: 135 G: 206 B: 250
+  # return {Object} The color object
+  lightSkyBlue: {r: 135, g: 206, b: 250}
+  # Returns new object with color values: R: 119 G: 136 B: 153
+  # return {Object} The color object
+  lightSlateGray: {r: 119, g: 136, b: 153}
+  # Alternative spelling for .lightSlateGray
+  # see Color.lightSlateGray
+  # return {Object} The color object
+  lightSlateGrey: lightSlateGray
+  # Returns new object with color values: R: 176 G: 196 B: 222
+  # return {Object} The color object
+  lightSteelBlue: {r: 176, g: 196, b: 222}
+  # Returns new object with color values: R: 255 G: 255 B: 224
+  # return {Object} The color object
+  lightYellow: {r: 255, g: 255, b: 224}
+  # Returns new object with color values: R: 50  G: 205 B: 50
+  # return {Object} The color object
+  limeGreen: {r: 50, g: 205, b: 50}
+  # Returns new object with color values: R: 250 G: 240 B: 230
+  # return {Object} The color object
+  linen: {r: 250, g: 240, b: 230}
+  # Same as .fuchsia
+  # See Color.fuchsia
+  # return {Object} The color object
+  magenta: @fuchsia
+  # Returns new object with color values: R: 102 G: 205 B: 170
+  # return {Object} The color object
+  mediumAquaMarine: {r: 102, g: 205, b: 170}
+  # Returns new object with color values: R: 0   G: 0   B: 205
+  # return {Object} The color object
+  mediumBlue: {r: 0, g: 0, b: 205}
+  # Returns new object with color values: R: 186 G: 85  B: 211
+  # return {Object} The color object
+  mediumOrchid: {r: 186, g: 85, b: 211}
+  # Returns new object with color values: R: 147 G: 112 B: 219
+  # return {Object} The color object
+  mediumPurple: {r: 157, g: 112, b: 219}
+  # Returns new object with color values: R: 60  G: 179 B: 113
+  # return {Object} The color object
+  mediumSeaGreen: {r: 60, g: 179, b: 113}
+  # Returns new object with color values: R: 123 G: 104 B: 238
+  # return {Object} The color object
+  mediumSlateBlue: {r: 123, g: 104, b: 238}
+  # Returns new object with color values: R: 0   G: 250 B: 154
+  # return {Object} The color object
+  mediumSpringGreen: {r: 0, g: 250, b: 154}
+  # Returns new object with color values: R: 72  G: 209 B: 204
+  # return {Object} The color object
+  mediumTurquoise: {r: 72, g: 209, b: 204}
+  # Returns new object with color values: R: 199 G: 21  B: 133
+  # return {Object} The color object
+  mediumVioletRed: {r: 199, g: 21, b: 133}
+  # Returns new object with color values: R: 25  G: 25  B: 112
+  # return {Object} The color object
+  midnightBlue: {r: 25, g: 25, b: 112}
+  # Returns new object with color values: R: 245 G: 255 B: 250
+  # return {Object} The color object
+  mintCream: {r: 245, g: 255, b: 250}
+  # Returns new object with color values: R: 255 G: 228 B: 225
+  # return {Object} The color object
+  mistyRose: {r: 255, g: 228, b: 225}
+  # Returns new object with color values: R: 255 G: 228 B: 181
+  # return {Object} The color object
+  moccasin: {r: 255, g: 228, b: 181}
+  # Returns new object with color values: R: 255 G: 222 B: 173
+  # return {Object} The color object
+  navajoWhite: {r: 255, g: 222, b: 173}
+  # Returns new object with color values: R: 253 G: 245 B: 230
+  # return {Object} The color object
+  oldLace: {r: 253, g: 245, b: 230}
+  # Returns new object with color values: R: 107 G: 142 B: 35
+  # return {Object} The color object
+  oliveDrab: {r: 107, g: 142, b: 35}
+  # Returns new object with color values: R: 255 G: 165 B: 0
+  # return {Object} The color object
+  orange: {r: 255, g: 165, b: 0}
+  # Returns new object with color values: R: 255 G: 69  B: 0
+  # return {Object} The color object
+  orangeRed: {r: 255, g: 69, b: 0}
+  # Returns new object with color values: R: 218 G: 112 B: 214
+  # return {Object} The color object
+  orchid: {r: 218, g: 112, b: 214}
+  # Returns new object with color values: R: 238 G: 232 B: 170
+  # return {Object} The color object
+  paleGoldenRod: {r: 238, g: 232, b: 170}
+  # Returns new object with color values: R: 152 G: 251 B: 152
+  # return {Object} The color object
+  paleGreen: {r: 152, g: 251, b: 152}
+  # Returns new object with color values: R: 175 G: 238 B: 238
+  # return {Object} The color object
+  paleTurquoise: {r: 175, g: 238, b: 238}
+  # Returns new object with color values: R: 219 G: 112 B: 147
+  # return {Object} The color object
+  paleVioletRed: {r: 219, g: 112, b: 147}
+  # Returns new object with color values: R: 255 G: 239 B: 213
+  # return {Object} The color object
+  papayaWhip: {r: 255, g: 239, b: 213}
+  # Returns new object with color values: R: 255 G: 218 B: 185
+  # return {Object} The color object
+  peachPuff: {r: 255, g: 218, b: 185}
+  # Returns new object with color values: R: 205 G: 133 B: 63
+  # return {Object} The color object
+  peru: {r: 205, g: 133, b: 63}
+  # Returns new object with color values: R: 255 G: 192 B: 203
+  # return {Object} The color object
+  pink: {r: 255, g: 192, b: 203}
+  # Returns new object with color values: R: 221 G: 160 B: 221
+  # return {Object} The color object
+  plum: {r: 221, g: 160, b: 221}
+  # Returns new object with color values: R: 176 G: 224 B: 230
+  # return {Object} The color object
+  powderBlue: {r: 176, g: 224, b: 230}
+  # Returns new object with color values: R: 188 G: 143 B: 143
+  # return {Object} The color object
+  rosyBrown: {r: 188, g: 143, b: 143}
+  # Returns new object with color values: R: 65  G: 105 B: 225
+  # return {Object} The color object
+  royalBlue: {r: 65, g: 105, b: 225}
+  # Returns new object with color values: R: 139 G: 69  B: 19
+  # return {Object} The color object
+  saddleBrown: {r: 139, g: 69, b: 19}
+  # Returns new object with color values: R: 250 G: 128 B: 114
+  # return {Object} The color object
+  salmon: {r: 250, g: 128, b: 114}
+  # Returns new object with color values: R: 244 G: 164 B: 96
+  # return {Object} The color object
+  sandyBrown: {r: 244, g: 164, b: 96}
+  # Returns new object with color values: R: 46  G: 139 B: 87
+  # return {Object} The color object
+  seaGreen: {r: 46, g: 139, b: 87}
+  # Returns new object with color values: R: 255 G: 245 B: 238
+  # return {Object} The color object
+  seaShell: {r: 255, g: 245, b: 238}
+  # Returns new object with color values: R: 160 G: 82  B: 45
+  # return {Object} The color object
+  sienna: {r: 160, g: 82, b: 45}
+  # Returns new object with color values: R: 135 G: 206 B: 235
+  # return {Object} The color object
+  skyBlue: {r: 135, g: 206, b: 235}
+  # Returns new object with color values: R: 106 G: 90  B: 205
+  # return {Object} The color object
+  slateBlue: {r: 106, g: 90, b: 205}
+  # Returns new object with color values: R: 112 G: 128 B: 144
+  # return {Object} The color object
+  slateGray: {r: 112, g: 128, b: 144}
+  # Alternative spelling for .slateGray
+  # see Color.slateGray
+  # return {Object} The color object
+  slateGrey: @slateGray
+  # Returns new object with color values: R: 255 G: 250 B: 250
+  # return {Object} The color object
+  snow: {r: 255, g: 250, b: 250}
+  # Returns new object with color values: R: 0   G: 255 B: 127
+  # return {Object} The color object
+  springGreen: {r: 0, g: 255, b: 127}
+  # Returns new object with color values: R: 70  G: 130 B: 180
+  # return {Object} The color object
+  steelBlue: {r: 70, g: 130, b: 180}
+  # Returns new object with color values: R: 210 G: 180 B: 140
+  # return {Object} The color object
+  tan: {r: 210, g: 180, b: 140}
+  # Returns new object with color values: R: 216 G: 191 B: 216
+  # return {Object} The color object
+  thistle: {r: 216, g: 191, b: 216}
+  # Returns new object with color values: R: 255 G: 99  B: 71
+  # return {Object} The color object
+  tomato: {r: 255, g: 99, b: 71}
+  # Returns new object with color values: R: 64  G: 224 B: 208
+  # return {Object} The color object
+  turquoise: {r: 64, g: 224, b: 208}
+  # Returns new object with color values: R: 238 G: 130 B: 238
+  # return {Object} The color object
+  violet: {r: 238, g: 130, b: 238}
+  # Returns new object with color values: R: 245 G: 222 B: 179
+  # return {Object} The color object
+  wheat: {r: 245, g: 222, b: 179}
+  # Returns new object with color values: R: 245 G: 245 B: 245
+  # return {Object} The color object
+  whiteSmoke: {r: 245, g: 245, b: 245}
+  # Returns new object with color values: R: 154 G: 205 B: 50
+  # return {Object} The color object
+  yellowGreen: {r: 154, g: 205, b: 50}
+
+  # Custom colors
+
+  # Returns new object with color values: R: 73  G: 92  B: 108
+  # return {Object} The color object
+  freezeDevBlue: {r: 73, g: 92, b: 108}


staging fix

staging 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/netguru/review.git/'


Added coffee script

Added coffee script

--- scripts/coffee.coffee
+++ scripts/coffee.coffee
@@ -0,0 +1,18 @@
+# Description:
+#   What do I need to make X cups of coffee?
+#
+# Commands:
+#   hubot coffee [cups] - What you need to make [cups] cups of coffee.
+
+
+# water = 3/16 * cups
+# scoops = .75 * cups + 2
+
+module.exports = (robot) ->
+  robot.respond /coffee (\d+)$/i, (msg) ->
+    cups = msg.match[1]
+
+    water = (3/16) * cups
+    scoops = (0.75 * cups) + 2
+
+    msg.send "You need #{scoops} level scoops and #{water} L of water."


Add js spec for option value namer

Add js spec for option value namer

error: pathspec 'spec/javascripts/unit/admin/services/option_value_namer_spec.js.coffee' did not match any file(s) known to git

--- spec/javascripts/unit/admin/services/option_value_namer_spec.js.coffee
+++ spec/javascripts/unit/admin/services/option_value_namer_spec.js.coffee
@@ -0,0 +1,123 @@
+describe "Option Value Namer", ->
+  optionValueNamer = null
+
+  beforeEach ->
+    module "ofn.admin"
+
+  beforeEach inject (_optionValueNamer_) ->
+    optionValueNamer = _optionValueNamer_
+
+  describe "generating option value name", ->
+    v = namer = null
+    beforeEach ->
+      v = {}
+      namer = new optionValueNamer(v)
+
+    it "when description is blank", ->
+      v.unit_description = null
+      spyOn(namer, "value_scaled").andReturn true
+      spyOn(namer, "option_value_value_unit").andReturn ["value", "unit"]
+      expect(namer.name()).toBe "valueunit"
+
+    it "when description is present", ->
+      v.unit_description = 'desc'
+      spyOn(namer, "option_value_value_unit").andReturn ["value", "unit"]
+      spyOn(namer, "value_scaled").andReturn true
+      expect(namer.name()).toBe "valueunit desc"
+
+    it "when value is blank and description is present", ->
+      v.unit_description = 'desc'
+      spyOn(namer, "option_value_value_unit").andReturn [null, null]
+      spyOn(namer, "value_scaled").andReturn true
+      expect(namer.name()).toBe "desc"
+
+    it "spaces value and unit when value is unscaled", ->
+      v.unit_description = null
+      spyOn(namer, "option_value_value_unit").andReturn ["value", "unit"]
+      spyOn(namer, "value_scaled").andReturn false
+      expect(namer.name()).toBe "value unit"
+
+    describe "determining if a variant's value is scaled", ->
+      v = p = namer = null
+
+      beforeEach ->
+        p = {}
+        v = { product: p }
+        namer = new optionValueNamer(v)
+
+      it "returns true when the product has a scale", ->
+        p.variant_unit_scale = 1000
+        expect(namer.value_scaled()).toBe true
+
+      it "returns false otherwise", ->
+        expect(namer.value_scaled()).toBe false
+
+    describe "generating option value's value and unit", ->
+      v = p = namer = null
+
+      beforeEach ->
+        p = {}
+        v = { product: p }
+        namer = new optionValueNamer(v)
+
+      it "generates simple values", ->
+        p.variant_unit = 'weight'
+        p.variant_unit_scale = 1.0
+        v.unit_value = 100
+        expect(namer.option_value_value_unit()).toEqual [100, 'g']
+
+      it "generates values when unit value is non-integer", ->
+        p.variant_unit = 'weight'
+        p.variant_unit_scale = 1.0
+        v.unit_value = 123.45
+        expect(namer.option_value_value_unit()).toEqual [123.45, 'g']
+
+      it "returns a value of 1 when unit value equals the scale", ->
+        p.variant_unit = 'weight'
+        p.variant_unit_scale = 1000.0
+        v.unit_value = 1000.0
+        expect(namer.option_value_value_unit()).toEqual [1, 'kg']
+
+      it "generates values for all weight scales", ->
+        for units in [[1.0, 'g'], [1000.0, 'kg'], [1000000.0, 'T']]
+          [scale, unit] = units
+          p.variant_unit = 'weight'
+          p.variant_unit_scale = scale
+          v.unit_value = 100 * scale
+          expect(namer.option_value_value_unit()).toEqual [100, unit]
+
+      it "generates values for all volume scales", ->
+        for units in [[0.001, 'mL'], [1.0, 'L'], [1000000.0, 'ML']]
+          [scale, unit] = units
+          p.variant_unit = 'volume'
+          p.variant_unit_scale = scale
+          v.unit_value = 100 * scale
+          expect(namer.option_value_value_unit()).toEqual [100, unit]
+
+      it "chooses the correct scale when value is very small", ->
+        p.variant_unit = 'volume'
+        p.variant_unit_scale = 0.001
+        v.unit_value = 0.0001
+        expect(namer.option_value_value_unit()).toEqual [0.1, 'mL']
+
+      it "generates values for item units", ->
+        #TODO
+        # %w(packet box).each do |unit|
+        #   p = double(:product, variant_unit: 'items', variant_unit_scale: nil, variant_unit_name: unit)
+        #   v.stub(:product) { p }
+        #   v.stub(:unit_value) { 100 }
+        #   subject.option_value_value_unit.should == [100, unit.pluralize]
+
+      it "generates singular values for item units when value is 1", ->
+        p.variant_unit = 'items'
+        p.variant_unit_scale = null
+        p.variant_unit_name = 'packet'
+        v.unit_value = 1
+        expect(namer.option_value_value_unit()).toEqual [1, 'packet']
+
+      it "returns [nil, nil] when unit value is not set", ->
+        p.variant_unit = 'items'
+        p.variant_unit_scale = null
+        p.variant_unit_name = 'foo'
+        v.unit_value = null
+        expect(namer.option_value_value_unit()).toEqual [null, null]


Pass exact: option from setPaths() to addPath()

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


fix bug

fix bug

--- views/components/ship/parts/panebody.cjsx
+++ views/components/ship/parts/panebody.cjsx
@@ -184,53 +184,55 @@
     else
       true
   render: ->
-    <TopAlert
-      messages={@props.messages}
-      deckIndex={@props.deckIndex}
-      deckName={@props.deckName}
-      deckState={@props.deckState} />
-

-

-      {
-        {$ships, $shipTypes, _ships} = window
-        for shipId, j in @props.deck.api_ship
-          continue if shipId == -1
-          ship = _ships[shipId]
-          shipInfo = $ships[ship.api_ship_id]
-          shipType = $shipTypes[shipInfo.api_stype].api_name
-          [
-

-              {shipInfo.api_name}
-              Lv. {ship.api_lv}
-
-                <ProgressBar bsStyle={getHpStyle ship.api_nowhp / ship.api_maxhp * 100}
-                             now={ship.api_nowhp / ship.api_maxhp * 100}
-                             label={"#{ship.api_nowhp} / #{ship.api_maxhp}"} />
-
-
-                <Slotitems data={ship.api_slot} onslot={ship.api_onslot} maxeq={ship.api_maxeq} />
-
-

-

-              {shipType}
-              Next. {ship.api_exp[1]}
-
-                <Grid>
-                  <Col xs={6} style={paddingRight: 1}>
-                    <ProgressBar bsStyle={getMaterialStyle ship.api_fuel / shipInfo.api_fuel_max * 100}
-                                   now={ship.api_fuel / shipInfo.api_fuel_max * 100} />
-                  </Col>
-                  <Col xs={6} style={paddingLeft: 1}>
-                    <ProgressBar bsStyle={getMaterialStyle ship.api_bull / shipInfo.api_bull_max * 100}
-                                   now={ship.api_bull / shipInfo.api_bull_max * 100} />
-                  </Col>
-                </Grid>
-
-              Cond. {ship.api_cond}
-

-          ]
-      }
-

-

+

+      <TopAlert
+        messages={@props.messages}
+        deckIndex={@props.deckIndex}
+        deckName={@props.deckName}
+        deckState={@props.deckState} />
+

+

+        {
+          {$ships, $shipTypes, _ships} = window
+          for shipId, j in @props.deck.api_ship
+            continue if shipId == -1
+            ship = _ships[shipId]
+            shipInfo = $ships[ship.api_ship_id]
+            shipType = $shipTypes[shipInfo.api_stype].api_name
+            [
+

+                {shipInfo.api_name}
+                Lv. {ship.api_lv}
+
+                  <ProgressBar bsStyle={getHpStyle ship.api_nowhp / ship.api_maxhp * 100}
+                               now={ship.api_nowhp / ship.api_maxhp * 100}
+                               label={"#{ship.api_nowhp} / #{ship.api_maxhp}"} />
+
+
+                  <Slotitems data={ship.api_slot} onslot={ship.api_onslot} maxeq={ship.api_maxeq} />
+
+

+

+                {shipType}
+                Next. {ship.api_exp[1]}
+
+                  <Grid>
+                    <Col xs={6} style={paddingRight: 1}>
+                      <ProgressBar bsStyle={getMaterialStyle ship.api_fuel / shipInfo.api_fuel_max * 100}
+                                     now={ship.api_fuel / shipInfo.api_fuel_max * 100} />
+                    </Col>
+                    <Col xs={6} style={paddingLeft: 1}>
+                      <ProgressBar bsStyle={getMaterialStyle ship.api_bull / shipInfo.api_bull_max * 100}
+                                     now={ship.api_bull / shipInfo.api_bull_max * 100} />
+                    </Col>
+                  </Grid>
+
+                Cond. {ship.api_cond}
+

+            ]
+        }
+

+

+

 module.exports = PaneBody


added +V and +SB tags for osu! requests + debug messages

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


adding authentication

adding authentication

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/stormpack-core/stormpack-client-js.git/'


Add javascript.coffee

Add javascript.coffee

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

--- src/javascript.coffee
+++ src/javascript.coffee
@@ -0,0 +1,199 @@
+define ['droplet-helper', 'droplet-model', 'droplet-parser', 'acorn'], (helper, model, parser, acorn) ->
+  exports = {}
+
+  operatorPrecedences = {
+    '+': 0
+    '-': 0
+    '/': 1
+    '*': 1
+  }
+
+  STATEMENT_NODE_TYPES = [
+    'ExpressionStatement'
+    'ReturnStatement'
+  ]
+
+  exports.JavaScriptParser = class JavaScriptParser extends parser.Parser
+    constructor: ->
+      super
+
+      @lines = @text.split '\n'
+
+    markRoot: ->
+      tree = acorn.parse(@text, {
+        locations: true
+        line: 0
+      })
+
+      #console.log 'PROGRAM IS', JSON.stringify tree, null, 2
+
+      @mark tree, 0, null
+
+    getAcceptsRule: (node) -> default: helper.NORMAL
+    getClasses: (node) -> []
+
+    getPrecedence: (node) ->
+      switch node.type
+        when 'BinaryExpression'
+          return operatorPrecedences[node.operator]
+        when 'CallExpression'
+          return 10
+        when 'ExpressionStatement'
+          return @getPrecedence node.expression
+        else
+          return 0
+
+    getColor: (node) ->
+      switch node.type
+        when 'ExpressionStatement'
+          return @getColor node.expression
+        when 'BinaryExpression'
+          return 'value'
+        when 'FunctionExpression'
+          return 'command'
+        when 'FunctionDeclaration'
+          return 'control'
+        when 'AssignmentExpression'
+          return 'command'
+        when 'CallExpression'
+          return 'command'
+        when 'ReturnStatement'
+          return 'return'
+        when 'MemberExpression'
+          return 'value'
+
+    getSocketLevel: (node) -> helper.ANY_DROP
+
+    getBounds: (node) ->
+      # If we are a statement, scan
+      # to find the semicolon
+      if node.type is 'BlockStatement'
+        bounds = {
+          start: {
+            line: node.loc.start.line
+            column: node.loc.start.column + 1
+          }
+          end: {
+            line: node.loc.end.line
+            column: node.loc.end.column - 1
+          }
+        }
+
+        if @lines[bounds.end.line][...bounds.end.column].trim().length is 0
+          bounds.end.line -= 1
+          bounds.end.column = @lines[bounds.end.line].length
+
+        return bounds
+
+      else if node.type in STATEMENT_NODE_TYPES
+        line = @lines[node.loc.end.line]
+        semicolon = @lines[node.loc.end.line][node.loc.end.column...].indexOf ';'
+        if semicolon > 0
+          return {
+            start: {
+              line: node.loc.start.line
+              column: node.loc.start.column
+            }
+            end: {
+              line: node.loc.end.line
+              column: node.loc.end.column + semicolon
+            }
+          }
+
+      return node.loc
+
+    isComment: (text) ->
+      text.match(/^\s*\/\/.*$/)
+
+    mark: (node, depth, bounds) ->
+      switch node.type
+        when 'Program'
+          for statement in node.body
+            @mark statement, depth + 1, null
+        when 'Function'
+          @jsBlock node, depth, bounds
+          @mark node.body, depth + 1, null
+        when 'FunctionDeclaration'
+          @jsBlock node, depth, bounds
+          @mark node.body, depth + 1, null
+          @jsSocketAndMark node.id, depth + 1
+        when 'FunctionExpression'
+          @jsBlock node, depth, bounds
+          @mark node.body, depth + 1, null
+          if node.id?
+            @jsSocketAndMark node.id, depth + 1
+        when 'AssignmentExpression'
+          @jsBlock node, depth, bounds
+          @jsSocketAndMark node.left, depth + 1, null
+          @jsSocketAndMark node.right, depth + 1, null
+        when 'ReturnStatement'
+          @jsBlock node, depth, bounds
+          if node.argument?
+            @jsSocketAndMark node.argument, depth + 1, null
+        when 'BlockStatement'
+          @addIndent
+            bounds: @getBounds node
+            depth: depth
+            prefix: '  '
+
+          for statement in node.body
+            @mark statement, depth + 1, null
+        when 'BinaryExpression'
+          @jsBlock node, depth, bounds
+          @jsSocketAndMark node.left, depth + 1, operatorPrecedences[node.operator]
+          @jsSocketAndMark node.right, depth + 1, operatorPrecedences[node.operator]
+        when 'ExpressionStatement'
+          @mark node.expression, depth + 1, @getBounds node
+        when 'CallExpression'
+          @jsBlock node, depth, bounds
+          for argument in node.arguments
+            @jsSocketAndMark argument, depth, 10
+        when 'MemberExpression'
+          @jsBlock node, depth, bounds
+          @jsSocketAndMark node.object, depth + 1
+          @jsSocketAndMark node.property, depth + 1
+
+    jsBlock: (node, depth, bounds) ->
+      @addBlock
+        bounds: bounds ? @getBounds node
+        depth: depth
+        precedence: @getPrecedence node
+        color: @getColor node
+        classes: @getClasses node
+        socketLevel: @getSocketLevel node
+
+    jsSocketAndMark: (node, depth, precedence, bounds) ->
+      @addSocket
+        bounds: bounds ? @getBounds node
+        depth: depth
+        precedence: precedence
+        accepts: @getAcceptsRule node
+
+      @mark node, depth + 1, bounds
+
+  exports.parse = (text, opts) ->
+    parser = new JavaScriptParser text
+    return parser.parse opts
+
+  exports.parens = (leading, trailing, node, context) ->
+    if context?.type is 'socket'
+      trailing = trailing.replace(/;?\s*$/, '')
+    else
+      trailing = trailing.replace(/;?\s*$/, ';')
+    if context is null or context.type isnt 'socket' or
+        context.precedence < node.precedence
+      while true
+        if leading.match(/^\s*\(/)? and trailing.match(/\)\s*/)?
+          leading = leading.replace(/^\s*\(\s*/, '')
+          trailing = trailing.replace(/^\s*\)\s*/, '')
+        else
+          break
+    else
+      leading = '(' + leading
+      trailing = trailing + ')'
+
+    return [leading, trailing]
+
+  exports.empty = "eval('')"
+
+  return exports


Google APIs: Initial module documentation

--- node_modules_koding/koding-googleapis/lib/index.coffee
+++ node_modules_koding/koding-googleapis/lib/index.coffee
@@ -1,3 +1,60 @@
+###
+
+This is a basic googleapis module wrapper.
+
+See: https://www.npmjs.com/package/googleapis
+
+It exposes three functions to utilize:
+
+- `authorize`
+- `authenticate`
+- `authenticated`
+
+
+`authorize` and `authenticate` functions are provided to handle these
+procedures in the client module.
+
+`authorize` initializes `google.auth.JWT` instance with following
+options:
+
+- scope   : Scope to restrict token
+- subject : Service URL
+
+Following options are defined internally for `authorize` function:
+
+- email : Service account email
+- key   : Service account key file path
+
+`authentiocated` function wraps given function with a set of
+procedures.  These procedures ensure wrapped function is executed with
+a valid OAuth2 client instance.
+
+`authenticated` accepts following options:
+
+- `authorization_options` : See options of `authorize` function above.
+
+- `authorization_handler` : Optional callback function.  It is invoked
+  with token information when authorization process succeeds.
+
+- `authentication_handler` : Optional callback function.  A new
+  `google.auth.OAuth2` instance is passed.
+
+`authenticated` wrapper validates `google.auth.OAuth2` instance set
+for given callback function on each call.  If OAuth2 client is not set
+before then a new instance is created via `authorize` and
+`authenticate` functions.  Next calls will benefit from using existing
+`google.auth.Oauth2` instance.
+
+There is a preset timeout of 30 minutes for `google.auth.JWT` tokens.
+If that timeout is passed then a new `google.auth.OAuth2` instance is
+created the same way with same authorization and authentication
+options.  If client module depends on `google.auth.OAuth2` instance
+then passed `authententication_handler` callback should make the
+necessary changes in client module.
+
+###
+
+
 google = require 'googleapis'

 {argv} = require 'optimist'
@@ -84,7 +141,6 @@
         authenticate_callback invoke_callback

-
 module.exports = {
   authorize
   authenticate


Add missing javascript for acts as list.

error: pathspec 'app/assets/javascripts/rails/add_ons/application/acts-as-list.js.coffee' did not match any file(s) known to git

--- app/assets/javascripts/rails/add_ons/application/acts-as-list.js.coffee
+++ app/assets/javascripts/rails/add_ons/application/acts-as-list.js.coffee
@@ -0,0 +1,21 @@
+$ ->
+  $('[data-acts-as-list-item]').each ->
+    $(@).draggable({
+      scope: $(@).attr('data-acts-as-list-item-scope'),
+      revert: true
+    })
+
+$ ->
+  $('[data-acts-as-list-item]').each ->
+    redirect_target = $(@).attr('data-acts-as-list-item-on-drop-target')
+    authenticity_token = $( 'meta[name="csrf-token"]' ).attr( 'content' );
+
+    $(@).droppable({
+      accept: '.acts-as-list-item',
+      scope: $(@).attr('data-acts-as-list-item-scope'),
+      activeClass: 'btn-success',
+      drop: (event, ui) ->
+        dropped_element = $(ui.draggable)
+        dropped_element_to_param = dropped_element.attr('data-acts-as-list-item-uid')
+        $.redirect(redirect_target,{ authenticity_token: authenticity_token, dropped_id: dropped_element_to_param });
+    })


更新run server主页路径

更新run server主页路径

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


Client: Activity: Created participantsIdsstore tests

error: pathspec 'client/activity/lib/flux/createchannel/tests/participantidsstore.coffee' did not match any file(s) known to git

--- client/activity/lib/flux/createchannel/tests/participantidsstore.coffee
+++ client/activity/lib/flux/createchannel/tests/participantidsstore.coffee
@@ -0,0 +1,61 @@
+{ expect } = require 'chai'
+
+Reactor = require 'app/flux/reactor'
+
+ParticipantIdsStore = require 'activity/flux/createchannel/stores/participantidsstore'
+actions = require 'activity/flux/createchannel/actions/actiontypes'
+
+describe 'CreateNewChannelParticipantIdsStore', ->
+
+  beforeEach ->
+
+    @reactor = new Reactor
+    @reactor.registerStores participantIds : ParticipantIdsStore
+
+
+  describe '#handleAddParticipantToNewChannel', ->
+
+    it 'sets given accountId to participantidsstore', ->
+
+      testAccountId = 'koding_123'
+
+      @reactor.dispatch actions.ADD_PARTICIPANT_TO_NEW_CHANNEL, { accountId : testAccountId }
+
+      participants = @reactor.evaluate(['participantIds'])
+
+      expect(participants.get testAccountId).to.equal testAccountId
+
+
+  describe '#handleRemoveParticipantFromNewChannel', ->
+
+    it 'remove given accountId to participantidsstore', ->
+
+      testAccountId_1 = 'koding'
+      testAccountId_2 = 'koding_123'
+
+      @reactor.dispatch actions.ADD_PARTICIPANT_TO_NEW_CHANNEL, { accountId : testAccountId_1 }
+      @reactor.dispatch actions.ADD_PARTICIPANT_TO_NEW_CHANNEL, { accountId : testAccountId_2 }
+      @reactor.dispatch actions.REMOVE_PARTICIPANT_FROM_NEW_CHANNEL, { accountId : testAccountId_1 }
+
+      participants = @reactor.evaluate(['participantIds'])
+
+      expect(participants.get testAccountId_2).to.equal testAccountId_2
+      expect(participants.get testAccountId_1).to.be.undefined
+
+
+  describe '#handleRemoveAllParticipantsFromNewChannel', ->
+
+    it 'removes all participant ids from participantidsstore', ->
+
+      testAccountId_1 = 'koding'
+      testAccountId_2 = 'koding_123'
+
+      @reactor.dispatch actions.ADD_PARTICIPANT_TO_NEW_CHANNEL, { accountId : testAccountId_1 }
+      @reactor.dispatch actions.ADD_PARTICIPANT_TO_NEW_CHANNEL, { accountId : testAccountId_2 }
+      @reactor.dispatch actions.REMOVE_ALL_PARTICIPANTS_FROM_NEW_CHANNEL
+
+      participants = @reactor.evaluate(['participantIds'])
+
+      expect(participants.get testAccountId_1).to.be.undefined
+      expect(participants.get testAccountId_2).to.be.undefined
+


Added test controller.

Added test controller.

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

--- app/assets/javascripts/app/controllers/test.js.coffee
+++ app/assets/javascripts/app/controllers/test.js.coffee
@@ -0,0 +1,28 @@
+class App.TestController1 extends App.Controller
+  constructor: ->
+    super
+    @showState   = false
+    @hideState   = false
+    @activeState = false
+    @render()
+
+  meta: ->
+    {}
+
+  show: =>
+    @showState = true
+    @render()
+
+  hide: =>
+    @hideState = true
+    @render()
+
+  active: (state) =>
+    @activeState = state
+    @render()
+
+  render: ->
+    @html "
some test controller message:'#{@message}',show:'#{@showState}',hide:'#{@hideState}',active:'#{@activeState}'
"
+
+  url: ->
+    "#/some/url/#{@message}"


Add menu items

Add menu items

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

--- menus/snippets.cson
+++ menus/snippets.cson
@@ -0,0 +1,12 @@
+'menu': [
+  'label': 'Packages'
+  'submenu': [
+    'label': 'Snippets'
+    'submenu': [
+      { 'label': 'Expand', 'command': 'snippets:show' }
+      { 'label': 'Next Stop', 'command': 'snippets:next-tab-stop' }
+      { 'label': 'Previous Stop', 'command': 'snippets:previous-tab-stop' }
+    ]
+  ]
+]
+


Client: Activity: focus chatinput widget when inviteOthers clicked

--- client/activity/lib/components/publicchatpane/index.coffee
+++ client/activity/lib/components/publicchatpane/index.coffee
@@ -52,13 +52,16 @@
   inviteOthers: (event) ->

     kd.utils.stopDOMEvent event
-    ChatInputFlux.actions.value.setValue @props.thread.get('channelId'), '/invite '

+    chatInputWidget = @refs.chatInputWidget
+    textInput = React.findDOMNode chatInputWidget.refs.textInput
+    textInput.focus()
+
+    ChatInputFlux.actions.value.setValue @props.thread.get('channelId'), '/invite @'

   addIntegration: (event) ->

     kd.utils.stopDOMEvent event
-    ChatInputFlux.actions.value.setValue @props.thread.get('channelId'), '/'

   renderFollowChannel: ->
@@ -81,7 +84,7 @@
     { thread } = @props

     footerInnerComponent = if @channel 'isParticipant'
-    then <ChatInputWidget onSubmit={@bound 'onSubmit'} thread= {thread} enableSearch={yes} />
+    then <ChatInputWidget ref='chatInputWidget' onSubmit={@bound 'onSubmit'} thread= {thread} enableSearch={yes} />
     else @renderFollowChannel()

     <footer className="PublicChatPane-footer">


Fix info method again, broke with merge

Fix info method again, broke with merge

Conflicts:

	client/app/MainApp/VirtualizationController.coffee


Add another test for Client.getControlsLinksUrl to achieve 100% coverage

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/laterpay/laterpay-client-node.git/'


Access project from atom global

Access project from atom global

--- src/editor.coffee
+++ src/editor.coffee
@@ -589,7 +589,7 @@
   # Checkout the HEAD revision of this editor's file.
   checkoutHead: ->
     if path = @getPath()
-      @project.getRepo()?.checkoutHead(path)
+      atom.project.getRepo()?.checkoutHead(path)

   # {Delegates to: EditSession.setText}
   setText: (text) -> @activeEditSession.setText(text)


Add state to delighted data if state was populated by nces

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


appcontroller: add removeFakeViews

appcontroller: add removeFakeViews

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


Updated module code to support latest features shown in example

--- module/ViewNavigationController.coffee
+++ module/ViewNavigationController.coffee
@@ -2,16 +2,16 @@

 	# Setup Class Constants
 	INITIAL_VIEW_NAME = "initialView"
-	BACKBUTTON_VIEW_NAME = "vnc-BackButton"
+	BACKBUTTON_VIEW_NAME = "vnc-backButton"
 	ANIMATION_OPTIONS =
 		time: 0.3
 		curve: "ease-in-out"
 	BACK_BUTTON_FRAME =
 		x: 0
 		y: 40
-		width: 188
+		width: 88
 		height: 88
-	PUSH =
+	PUSH =
 		UP:     "pushUp"
 		DOWN:   "pushDown"
 		LEFT:   "pushLeft"
@@ -22,6 +22,7 @@
 		DOWN:  "down"
 		LEFT:  "left"
 		RIGHT: "right"
+	DEBUG_MODE = false

 	# Setup Instance and Instance Variables
 	constructor: (@options={}) ->
@@ -38,6 +39,8 @@
 		@history = []
 		@animationOptions = @options.animationOptions or ANIMATION_OPTIONS
 		@initialViewName  = @options.initialViewName  or INITIAL_VIEW_NAME
+		@backButtonFrame  = @options.backButtonFrame  or BACK_BUTTON_FRAME
+		@debugMode        = @options.debugMode        or DEBUG_MODE

 		@.on "change:subLayers", (changeList) ->
 			@addView subLayer, true for subLayer in changeList.added
@@ -129,22 +132,24 @@
 	_getLastHistoryItem: () ->
 		return @history[@history.length - 1]

-	_applyBackButton: (view, frame = BACK_BUTTON_FRAME) ->
+	_applyBackButton: (view, frame = @backButtonFrame) ->
 		Utils.delay 0, =>
-			backButton = new Layer
-				name: BACKBUTTON_VIEW_NAME
-				backgroundColor: "transparent"
-				width: 80
-				height: 80
-				superLayer: view
+			if view.backButton isnt false
+				backButton = new Layer
+					name: BACKBUTTON_VIEW_NAME
+					width: 80
+					height: 80
+					superLayer: view

-			backButton.frame = frame
+				if @debugMode is false
+					backButton.backgroundColor = "transparent"

-			backButton.on Events.Click, =>
-				@back()
+				backButton.frame = frame
+
+				backButton.on Events.Click, =>
+					@back()

-

 ################################################################################
 # USAGE EXAMPLE 1 - Define InitialViewName #####################################


:lipstick: Remove extra empty line

:lipstick: Remove extra empty line

--- src/editor.coffee
+++ src/editor.coffee
@@ -704,7 +704,6 @@
       else
         @gutter.addClass('drop-shadow')

-
     # Listen for overflow events to detect when the editor's width changes
     # to update the soft wrap column.
     updateWidthInChars = _.debounce((=> @setWidthInChars()), 100)