Move the menu into the submenus of "Packages".

--- menus/copy-path.cson
+++ menus/copy-path.cson
@@ -1,41 +1,44 @@
 menu: [
-  {
-    label: "Copy Path"
-    submenu: [
-      {
-        label: "Copy Basename"
-        command: "copy-path:copy-basename"
-      }
-      {
-        label: "Copy Extension"
-        command: "copy-path:copy-extension"
-      }
-      {
-        label: "Copy Basename w/o Extension"
-        command: "copy-path:copy-basename-wo-extension"
-      }
-      {
-        label: "Copy Project-Relative Path"
-        command: "copy-path:copy-project-relative-path"
-      }
-      {
-        label: "Copy Full Path"
-        command: "copy-path:copy-full-path"
-      }
-      {
-        label: "Copy Base Dirname"
-        command: "copy-path:copy-base-dirname"
-      }
-      {
-        label: "Copy Project-Relative Dirname"
-        command: "copy-path:copy-project-relative-dirname"
-      }
-      {
-        label: "Copy Full Dirname"
-        command: "copy-path:copy-full-dirname"
-      }
-    ]
-  }
+  label: "Packages"
+  submenu: [
+    {
+      label: "Copy Path"
+      submenu: [
+        {
+          label: "Copy Basename"
+          command: "copy-path:copy-basename"
+        }
+        {
+          label: "Copy Extension"
+          command: "copy-path:copy-extension"
+        }
+        {
+          label: "Copy Basename w/o Extension"
+          command: "copy-path:copy-basename-wo-extension"
+        }
+        {
+          label: "Copy Project-Relative Path"
+          command: "copy-path:copy-project-relative-path"
+        }
+        {
+          label: "Copy Full Path"
+          command: "copy-path:copy-full-path"
+        }
+        {
+          label: "Copy Base Dirname"
+          command: "copy-path:copy-base-dirname"
+        }
+        {
+          label: "Copy Project-Relative Dirname"
+          command: "copy-path:copy-project-relative-dirname"
+        }
+        {
+          label: "Copy Full Dirname"
+          command: "copy-path:copy-full-dirname"
+        }
+      ]
+    }
+  ]
 ]
 "context-menu":
   "atom-text-editor": [


Fix jump calulation

Fix jump calulation

--- scripts/stats.coffee
+++ scripts/stats.coffee
@@ -1,18 +1,17 @@
 applyScale = (min, max) ->
-    jump = 1
-    if max > 20
-        jump = 5
-    else if max > 100
-        jump = 10
-    else if max > 150
-        jump = 20
-    else if max > 250
-        jump = 50
-    else if max > 500
-        jump = 100
-    else if max > 2000
-        jump = Math.ceil(10 / max - min)
-    return jump
+    if max > 2000
+        return Math.ceil(10 / max - min)
+    if max > 1000
+        return 50
+    if max > 500
+        return 25
+    if max > 200
+        return 20
+    if max > 100
+        return 10
+    if max > 50
+        return 5
+    return 1

 months = ['Janurary', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
 colors = [


Reducing timeouts more and more

Reducing timeouts more and more

--- tests/www/run.coffee
+++ tests/www/run.coffee
@@ -7,7 +7,7 @@

 exports.test = ( name, conf, base_url, mark_as_passed )->

-  timeout = if name is 'local' then 5000 else 15000
+  timeout = if name is 'local' then 3000 else 10000

   describe name, ->


Fix typo

Fix typo

--- services/web/app/coffee/Features/Project/ProjectDeleter.coffee
+++ services/web/app/coffee/Features/Project/ProjectDeleter.coffee
@@ -51,7 +51,7 @@
 			if err?
 				logger.err err:err, "problem archived project"
 				return callback(err)
-			logger.log project_id:project_id, "succesfully archived project from user request"
+			logger.log project_id:project_id, "successfully archived project from user request"
 			callback()

 	restoreProject: (project_id, callback = (error) ->) ->


Scroll down 120px on the user profile pages.

--- app/assets/javascripts/controllers/application_controller.js.coffee
+++ app/assets/javascripts/controllers/application_controller.js.coffee
@@ -14,7 +14,11 @@

     # Scroll to the top of the page.
     Ember.run.next ->
-      window.scrollTo(0, 0)
+      if window.location.href.match('/users/')
+        scrollAmount = 120
+      else
+        scrollAmount = 0
+      window.scrollTo(0, scrollAmount)

   ).observes('currentPath')


add the unbind function to the dispatcher (javascript client)

--- lib/assets/javascripts/websocket_rails/websocket_rails.js.coffee
+++ lib/assets/javascripts/websocket_rails/websocket_rails.js.coffee
@@ -88,6 +88,9 @@
     @callbacks[event_name] ?= []
     @callbacks[event_name].push callback

+  unbind: (event_name) =>
+    delete @callbacks[event_name]
+
   trigger: (event_name, data, success_callback, failure_callback) =>
     event = new WebSocketRails.Event( [event_name, data, @_conn?.connection_id], success_callback, failure_callback )
     @trigger_event event


Add event to prevent saving when content is modified

--- plugins/image.coffee
+++ plugins/image.coffee
@@ -255,7 +255,7 @@
                     $("<div/>").addClass "tmp tmpBig"

                 showOverlay: (position) ->
-
+
                     eHeight = editable.height() + parseFloat(editable.css('paddingTop')) + parseFloat(editable.css('paddingBottom'))

                     overlay.big.css height: eHeight
@@ -304,6 +304,9 @@
                         helper.showOverlay position
                     helper.delayAction createTmpObject, 300

+                handleStartEvent: (event, ui) ->
+                    $(document).trigger('startPreventSave');
+
                 handleStopEvent: (event, ui) ->
                     internalDrop = helper.checkOrigin(event)
                     $(event.target).remove()  if internalDrop
@@ -311,6 +314,8 @@
                     overlay.big.hide()
                     overlay.left.hide()
                     overlay.right.hide()
+
+                    $(document).trigger('stopPreventSave');

                 handleDropEvent: (event, ui) ->
                     # check whether it's an internal drop or not
@@ -356,7 +361,7 @@
                           helperInsert = helper.createInsertElement(ui, true)
                       $(event.target).prepend helperInsert
                       helper.showOverlay position
-
+
                   helper.delayAction createTmp, 100

                 handleLeaveEvent: (event, ui) ->
@@ -390,6 +395,7 @@
                 cursor: "move"
                 helper: dnd.createHelper
                 drag: dnd.handleDragEvent
+                start: dnd.handleStartEvent
                 stop: dnd.handleStopEvent

             $(@options.editable.element).children('p').droppable


fix content type

fix content type

--- looker_client.coffee
+++ looker_client.coffee
@@ -1,4 +1,5 @@
 request = require("request")
+_ = require("underscore")

 module.exports = class LookerAPIClient

@@ -14,8 +15,9 @@
       return

     requestConfig.url = "#{@options.baseUrl}/#{requestConfig.path}"
-    requestConfig.headers =
+    headers =
       Authorization: "token #{@token}"
+    requestConfig.headers = _.extend(headers, requestConfig.headers || {})
     request(requestConfig, (error, response, body) =>
       if error
         errorCallback?(error)
@@ -32,7 +34,17 @@
     @request({method: "GET", path: path}, successCallback, errorCallback)

   post: (path, body, successCallback, errorCallback) ->
-    @request({method: "POST", path: path, body: JSON.stringify(body)}, successCallback, errorCallback)
+    @request(
+      {
+        method: "POST"
+        path: path
+        body: JSON.stringify(body)
+        headers:
+          "content-type": "application/json"
+      },
+      successCallback,
+      errorCallback
+    )

   fetchAccessToken: ->


AdminIntegrationItemView: Pass data to emitted event.

--- client/admin/lib/views/integrations/adminintegrationitemview.coffee
+++ client/admin/lib/views/integrations/adminintegrationitemview.coffee
@@ -24,9 +24,9 @@

   fetchIntegrationChannels: ->

-    remote.api.JAccount.some {}, {}, =>
+    remote.api.JAccount.some {}, {}, (err, data) =>
       @addButton.hideLoader()
-      @emit 'IntegrationGroupsFetched'
+      @emit 'IntegrationGroupsFetched', data

   pistachio: ->


No need second argument there

No need second argument there

--- client/app/MainApp/filetree/controllers/findertreecontroller.coffee
+++ client/app/MainApp/filetree/controllers/findertreecontroller.coffee
@@ -445,7 +445,7 @@
               @getSingleton('mainController').emit 'CreateNewActivityRequested', 'JCodeShare', CodeShares

   openTerminalFromHere: (nodeView) ->
-    appManager.open "WebTerm", yes, (appInstance) =>
+    appManager.open "WebTerm", (appInstance) =>
       path        = nodeView.getData().path
       webTermView = KD.getSingleton('mainView').mainTabView.getActivePane().mainView
       #TODO: webTermView != appInstance.getView() so should simplify the line above


Implemented XSS encoder to finder

Implemented XSS encoder to finder

--- client/finder/lib/filetree/controllers/nfindertreecontroller.coffee
+++ client/finder/lib/filetree/controllers/nfindertreecontroller.coffee
@@ -1,20 +1,21 @@
-Promise = require 'bluebird'
-$ = require 'jquery'
-kd = require 'kd'
-JTreeViewController = kd.JTreeViewController
-KDCustomHTMLView = kd.CustomHTMLView
-KDModalView = kd.ModalView
-KDNotificationView = kd.NotificationView
-globals = require 'globals'
-logToExternal = require 'app/util/logToExternal'
-logToExternalWithTime = require 'app/util/logToExternalWithTime'
-whoami = require 'app/util/whoami'
-KodingAppsController = require 'app/kodingappscontroller'
-FSHelper = require 'app/util/fs/fshelper'
-getPublicURLOfPath = require 'app/util/getPublicURLOfPath'
-CloneRepoModal = require 'app/commonviews/clonerepomodal'
-NFinderDeleteDialog = require '../itemsubviews/nfinderdeletedialog'
-DropboxDownloadItemView = require 'app/commonviews/dropboxdownloaditemview'
+Promise                   = require 'bluebird'
+$                         = require 'jquery'
+kd                        = require 'kd'
+JTreeViewController       = kd.JTreeViewController
+KDCustomHTMLView          = kd.CustomHTMLView
+KDModalView               = kd.ModalView
+KDNotificationView        = kd.NotificationView
+globals                   = require 'globals'
+logToExternal             = require 'app/util/logToExternal'
+logToExternalWithTime     = require 'app/util/logToExternalWithTime'
+whoami                    = require 'app/util/whoami'
+KodingAppsController      = require 'app/kodingappscontroller'
+FSHelper                  = require 'app/util/fs/fshelper'
+getPublicURLOfPath        = require 'app/util/getPublicURLOfPath'
+CloneRepoModal            = require 'app/commonviews/clonerepomodal'
+NFinderDeleteDialog       = require '../itemsubviews/nfinderdeletedialog'
+DropboxDownloadItemView   = require 'app/commonviews/dropboxdownloaditemview'
+Encoder                   = require 'htmlencode'

 module.exports = class NFinderTreeController extends JTreeViewController
@@ -279,6 +280,7 @@
     nodeData = nodeView.getData()
     oldPath = nodeData.path
     nodeView.showRenameView (newValue)=>
+      newValue = Encoder.XSSEncode newValue
       return  if newValue is nodeData.name
       return  unless FSHelper.isValidFileName newValue


Take care shared vms for groups

Take care shared vms for groups

--- client/landing/app/MainApp/filetree/itemsubviews/copyurlview.coffee
+++ client/landing/app/MainApp/filetree/itemsubviews/copyurlview.coffee
@@ -18,9 +18,19 @@

     KD.getSingleton('vmController').fetchVMDomains hostname, (err, domains)=>
       if domains?.length > 0 and not err
-        @publicPath = domains.first
-        @inputUrl.setValue (FSHelper.plainPath path).replace \
-          ////home/(.*)/Web/(.*)///, "http://#{@publicPath}/$2"
+
+        path  = FSHelper.plainPath path
+        match = path.match ///home/(\w+)/Web/(.*)///
+        return  unless match
+        [rest..., user, pathrest] = match
+
+        if /^shared-/.test hostname
+          subdomain = unless user is KD.nick() then "" else "#{user}."
+        else
+          subdomain = ''
+
+        @publicPath = "#{subdomain}#{domains.first}/#{pathrest}"
+        @inputUrl.setValue "http://#{@publicPath}"

   focusAndSelectAll:->
     @inputUrl.setFocus()


increase project user cache size

increase project user cache size

--- salvus/hub.coffee
+++ salvus/hub.coffee
@@ -2711,7 +2711,7 @@
     # Now replenish the cache for next time.
     replenish_random_unix_user_cache()

-new_random_unix_user_cache_target_size = 1
+new_random_unix_user_cache_target_size = 2
 new_random_unix_user.cache = []
 replenish_random_unix_user_cache = () ->
     cache = new_random_unix_user.cache


reload => render (match backbone.js)

reload => render (match backbone.js)

--- extensions/tree/tree-pane.coffee
+++ extensions/tree/tree-pane.coffee
@@ -14,7 +14,7 @@
   html: $ require "tree/tree.html"

   constructor: (@tree) ->
-    @reload()
+    @render()

     $('#tree li').live 'click', (event) =>
       $('#tree .active').removeClass 'active'
@@ -36,7 +36,7 @@

       false

-  reload: ->
+  render: ->
     @html.children('#tree .cwd').text _.last window.url.split '/'
     fileList = @createList @tree.urls()
     fileList.addClass 'files'


Pull IRC wrapping out of openSock.

Pull IRC wrapping out of openSock.

--- mixirc/mixirc.coffee
+++ mixirc/mixirc.coffee
@@ -145,6 +145,20 @@
 	# Send HTTP POST
 	sendHTTP httpHeader, ""

+ircWrapMessage = (a) ->
+	ircSay = irc.colors.wrap "light_gray", "["
+	ircSay += irc.colors.wrap "light_green", a.name
+	ircSay += irc.colors.wrap "light_gray", "]: "
+	ircSay += irc.colors.wrap "yellow", a.content
+	ircSay += irc.colors.wrap "light_gray", " [#{a.id}]"
+	return ircSay
+
+ircWrapHeart = (a) ->
+	ircSay = irc.colors.wrap "light_magenta", "<3 "
+	ircSay += irc.colors.wrap "light_blue", a.user_ids + " "
+	ircSay += irc.colors.wrap "light_red", a.comment_id
+	return ircSay
+
 # Opens a websocket connection and receives data as long as the connection remains open
 # TODO: add in the ping function (seems to be every 5 minutes)
 openSock = () ->
@@ -179,13 +193,7 @@
 					console.log "JSON.parse(unescape(m.data)) failed: #{err.message}"
 				unless ignoreList[a.name]?
 					try
-						id = a.id
-						ircSay = irc.colors.wrap "light_gray", "["
-						ircSay += irc.colors.wrap "light_green", a.name
-						ircSay += irc.colors.wrap "light_gray", "]: "
-						ircSay += irc.colors.wrap "yellow", a.content
-						ircSay += irc.colors.wrap "light_gray", " [#{id}]"
-						ircBot.say ircChannel, ircSay
+						ircBot.say ircChannel, ircWrapMessage a
 					catch err
 						ircBot.say ircChannel, err.message
 						console.log "ircBot.say failed: #{err.message}"
@@ -198,13 +206,10 @@
 					ircBot.say ircChannel, "STREAM IS LIVE: http://mixlr.com/jeff-gerstmann/chat/"

 			when "comment:hearted"
-				a = JSON.parse (unescape m.data)
+				a = JSON.parse unescape m.data
 				# TODO make this pretty, show original comment and translate
 				# user_ids into names.
-				ircSay = irc.colors.wrap "light_magenta", "<3 "
-				ircSay += irc.colors.wrap "light_blue", a.user_ids + " "
-				ircSay += irc.colors.wrap "light_red", a.comment_id
-				ircBot.say ircChannel, ircSay
+				ircBot.say ircChannel, ircWrapHeart a

 	ws.on 'close', ->
 		console.log "WebSocket Closed"


fixed bad coffeescript in settings file

fixed bad coffeescript in settings file

--- server-ce/settings.coffee
+++ server-ce/settings.coffee
@@ -423,7 +423,7 @@

 if process.env["SHARELATEX_EMAIL_FROM_ADDRESS"]

-	settings.email:
+	settings.email =
 		fromAddress: process.env["SHARELATEX_EMAIL_FROM_ADDRESS"]
 		replyTo: process.env["SHARELATEX_EMAIL_REPLY_TO"] or ""
 		parameters:
@@ -446,7 +446,7 @@
 # opts are from http://antelle.github.io/passfield
 if process.env["SHARELATEX_PASSWORD_VALIDATION_PATTERN"] or process.env["SHARELATEX_PASSWORD_VALIDATION_MIN_LENGTH"] or process.env["SHARELATEX_PASSWORD_VALIDATION_MAX_LENGTH"]

-	settings.passwordStrengthOptions:
+	settings.passwordStrengthOptions =
 		pattern: process.env["SHARELATEX_PASSWORD_VALIDATION_PATTERN"] or "aA$3"
 		length: {min:process.env["SHARELATEX_PASSWORD_VALIDATION_MIN_LENGTH"] or 8, max: process.env["SHARELATEX_PASSWORD_VALIDATION_MAX_LENGTH"] or 50}

@@ -467,7 +467,7 @@

 if process.env["SHARELATEX_LDAP_HOST"]
-	settings.ldap :
+	settings.ldap =
 		host: process.env["SHARELATEX_LDAP_HOST"]
 		dn: process.env["SHARELATEX_LDAP_DN"]
 		baseSearch: process.env["SHARELATEX_LDAP_BASE_SEARCH"]
@@ -486,7 +486,6 @@

 # Compiler
 # --------
-
 if process.env["DOCKER_IN_DOCKER"]
 	clsi:
 		commandRunner: "docker-runner-sharelatex"


Fix ldap settings

Fix ldap settings

--- server-ce/settings.coffee
+++ server-ce/settings.coffee
@@ -452,6 +452,11 @@
 if process.env["SHARELATEX_LDAP_URL"]
 	settings.externalAuth = true
 	settings.ldap =
+		emailAtt: process.env["SHARELATEX_LDAP_EMAIL_ATT"]
+		nameAtt: process.env["SHARELATEX_LDAP_NAME_ATT"]
+		lastNameAtt: process.env["SHARELATEX_LDAP_LAST_NAME_ATT"]
+		updateUserDetailsOnLogin: process.env["SHARELATEX_LDAP_UPDATE_USER_DETAILS_ON_LOGIN"] == 'true'
+		placeholder: process.env["SHARELATEX_LDAP_PLACEHOLDER"]
 		server:
 			url: process.env["SHARELATEX_LDAP_URL"]
 			bindDn: process.env["SHARELATEX_LDAP_BIND_DN"]
@@ -472,7 +477,7 @@
 			groupDnProperty: process.env["SHARELATEX_LDAP_GROUP_DN_PROPERTY"]
 			groupSearchBase: process.env["SHARELATEX_LDAP_GROUP_SEARCH_BASE"]
 			groupSearchScope: process.env["SHARELATEX_LDAP_GROUP_SEARCH_SCOPE"]
-			groupSearchFilter: process.env["SHARELATEX_LDAP_GROUP_SEARCH_FILTER"] #
+			groupSearchFilter: process.env["SHARELATEX_LDAP_GROUP_SEARCH_FILTER"]
 			groupSearchAttributes: (
 				if _ldap_group_search_attribs = process.env["SHARELATEX_LDAP_GROUP_SEARCH_ATTRIBUTES"]
 					try
@@ -501,11 +506,6 @@
 				else
 					undefined
 			)
-		emailAtt: process.env["SHARELATEX_LDAP_"]
-		nameAtt: process.env["SHARELATEX_LDAP_"]
-		lastNameAtt: process.env["SHARELATEX_LDAP_"]
-		updateUserDetailsOnLogin: process.env["SHARELATEX_LDAP_UPDATE_USER_DETAILS_ON_LOGIN"] == 'true'
-		placeholder: process.env["SHARELATEX_LDAP_"]

 	if process.env["SHARELATEX_LDAP_TLS_OPTS_CA_PATH"]
 		try


clear cache on import

clear cache on import

fixes #103

--- lib/championify.coffee
+++ lib/championify.coffee
@@ -1,6 +1,8 @@
 async = require 'async'
 cheerio = require 'cheerio'
+fs = require 'fs-extra'
 glob = require 'glob'
+path = require 'path'
 _ = require 'lodash'

 hlp = require './helpers'
@@ -30,6 +32,18 @@
   window.cSettings = preferences.get().options
   preferences.save step

+
+###*
+ * Function Clears electrons cache if it exists.
+ * @callback {Function} Callback.
+###
+clearCache = (step) ->
+  cache_directory = path.join preferences.directory(), 'Cache'
+  if fs.existsSync(cache_directory)
+    fs.remove cache_directory, (err) ->
+      step(err)
+  else
+    step()

 ###*
  * Function Gets the latest Riot Version.
@@ -160,8 +174,9 @@
   async_tasks = {
     # Default
     settings: getSettings
+    clearCache: clearCache,
     championTest: ['settings', permissions.championTest]
-    riotVer: ['championTest', getRiotVer]
+    riotVer: ['clearCache', 'championTest', getRiotVer]
     champs_json: ['riotVer', getChamps]
     champs: ['champs_json', champNames]
     manaless: ['champs_json', genManaless]


core/router: use debug instead of KD.log

--- lib/core/router.coffee
+++ lib/core/router.coffee
@@ -1,3 +1,4 @@
+debug = require('debug') 'kd:router'
 KD = require './kd'
 KDObject           = require './object'
 KDNotificationView = require '../components/notifications/notificationview'
@@ -70,8 +71,7 @@
     return yes

   @handleNotFound =(route)->
-    console.trace()
-    KD.log "The route #{ Encoder.XSSEncode route } was not found!"
+    debug "route #{route} not found"

   getCurrentPath:-> @currentPath

@@ -83,7 +83,7 @@

     delete @userRoute
     @clear()
-    KD.log "The route #{route} was not found!"
+    debug "route #{route} not found"
     new KDNotificationView title: message

   routeWithoutEdgeAtIndex =(route, i)->


updates for doctype html5

updates for doctype html5

--- src/art/engine/core/canvas_element.coffee
+++ src/art/engine/core/canvas_element.coffee
@@ -76,10 +76,25 @@

       parentSize: getter: ->
         if @_canvas
-          point(
-            @_canvas.parentElement.clientWidth
-            @_canvas.parentElement.clientHeight
-          )
+
+          ###
+          When using HTML5 <!DOCTYPE html>, parentElement.clientWidth* doesn't work right
+          It appears that the canvas's size effects the parent's size. A feedback loop.
+
+            # old:
+            point(
+              @_canvas.parentElement.clientWidth
+              @_canvas.parentElement.clientHeight
+            )
+
+          For FullScreenApps, we just want to use the whole viewport anyway, so that's what I'm
+          doing right now. If we want to have apps in canvas elements which are not full-screen,
+          then we need to update this.
+          ###
+          w = Math.max document.documentElement.clientWidth, window.innerWidth || 0
+          h = Math.max document.documentElement.clientHeight, window.innerHeight || 0
+
+          point w, h
         else point 100

     _domListener: (target, type, listener)->


Sentence-by-sentence-produced ranges do not currently have a TextQuoteSelector. Needs investigation.

Contributes to #27

--- annotran/static/scripts/annotator/plugin/sentenceselection.coffee
+++ annotran/static/scripts/annotator/plugin/sentenceselection.coffee
@@ -59,8 +59,6 @@
       end: full_xpath
       endOffset: offset_to_use + desiredText.length + this.currentIndex + 1
     }
-
-    console.log(data)

     return data

@@ -134,11 +132,38 @@
     this.currentIndex = 0
     this.selectSentence event.target

-  moveToNextSentence: () ->
+    selection = Annotator.Util.getGlobal().getSelection()
+    ranges = for i in [0...selection.rangeCount]
+      r = selection.getRangeAt(0)
+      if r.collapsed then continue else r
+
+    if ranges.length
+      event.ranges = ranges
+      @annotator.onSuccessfulSelection event
+
+      # in H's guest.coffee, createAnnotation -> getSelectors is NOT correctly describing the selection made here
+      # it's missing a TextQuoteSelector -- need to work out how to create this and inject it.
+      @annotator.createAnnotation()
+
+    return null
+
+
+  moveToNextSentence: (event) ->
     this.currentIndex = this.currentIndex + 1
     currentSelection = window.getSelection()

     this.selectSentence(currentSelection.baseNode.parentElement)
+
+    selection = Annotator.Util.getGlobal().getSelection()
+    ranges = for i in [0...selection.rangeCount]
+      r = selection.getRangeAt(0)
+      if r.collapsed then continue else r
+
+    if ranges.length
+      event.ranges = ranges
+      @annotator.onSuccessfulSelection event, true
+    else
+      @annotator.onFailedSelection event

     return null

@@ -149,4 +174,4 @@

     if event.which == 13
       # handle the enter key
-      this.moveToNextSentence()+      this.moveToNextSentence(event)


req.ip can't be modified

req.ip can't be modified

--- node/tracking.coffee
+++ node/tracking.coffee
@@ -122,10 +122,10 @@

 			parse.visits req, ->

-				if process.env.npm_package_config_anonymize is 'true'
-
-					# Do not save ip
-					req.ip = '-'
+				ip = '-'
+
+				# Save IP
+				ip = req.ip if process.env.npm_package_config_anonymize isnt 'true'

 				timezoneOffset	= (+new Date().getTimezoneOffset()) * 60
 				currentTime		= Math.round(+new Date()/1000) - timezoneOffset
@@ -133,7 +133,7 @@
 				# Required data available
 				db.source.run 'INSERT INTO stats VALUES (NULL, $ip, $referrer, $site, $site_title, $time, $duration, $language, $browser, $browser_version, $browser_width, $browser_height, $platform, $screen_width, $screen_height)',

-					$ip: req.ip
+					$ip: ip
 					$referrer: req.query.referrer
 					$site: req.query.site
 					$site_title: req.query.site_title
@@ -168,10 +168,10 @@

 			parse.duration req, ->

-				if process.env.npm_package_config_anonymize is 'true'
-
-					# Do not save ip
-					req.ip = '-'
+				ip = '-'
+
+				# Save IP
+				ip = req.ip if process.env.npm_package_config_anonymize isnt 'true'

 				timezoneOffset	= (+new Date().getTimezoneOffset()) * 60
 				currentTime		= Math.round(+new Date()/1000) - timezoneOffset
@@ -180,7 +180,7 @@

 					$duration: currentTime
 					$id: req.query.id
-					$ip: req.ip
+					$ip: ip

 				, (error) ->


Fix reference error in Association constructor.

--- src/model/associations/association.coffee
+++ src/model/associations/association.coffee
@@ -13,7 +13,7 @@
     @options = Batman.extend defaultOptions, @defaultOptions, options

     if @options.nestUrl
-      developer.error "You must persist the the model #{@model.constructor.name} to use the url helpers on an association" if !@model.urlNestsUnder?
+      Batman.developer.error "You must persist the the model #{@model.constructor.name} to use the url helpers on an association" if !@model.urlNestsUnder?
       @model.urlNestsUnder Batman.helpers.underscore(@getRelatedModel().get('resourceName'))

     if @options.extend?


add test dir

add test dir

--- karma.conf.coffee
+++ karma.conf.coffee
@@ -5,14 +5,16 @@
   config.set

     # base path, that will be used to resolve all patterns, eg. files, exclude
-    basePath: ''
+    basePath: '.'

     # frameworks to use
     frameworks: ['jasmine']

     # list of files / patterns to load in the browser
     files: [
-      'coolforms.js'
+      'test/angular.js',
+      'coolforms.js',
+      'test/*.coffee'
     ]

     # list of files to exclude
@@ -35,7 +37,7 @@
     logLevel: config.LOG_INFO

     # enable / disable watching file and executing tests whenever any file changes
-    autoWatch: false
+    autoWatch: true

     # Start these browsers, currently available:
     # - Chrome


.

Former-commit-id: 31b1bc00219e0a7fa69e95c96b2961c1ca7bd2e0 [formerly ff2a47cb462ea694340e761af21af99356fb905c] [formerly 3e3e6d0a55d635477132a5be7dad0357fb3d5b83 [formerly a84f87e5c2a13773884c81e068aa241619544347]] [formerly 9bcf9e40975a48595e503992b06134ac9bdd66c5 [formerly 57eacdd36a97d9184050ec428b8760ac21654d21] [formerly f28680afc4e79868c2e40c7c07211b6d22a0b817 [formerly 75f6e12c9e191c43d7b0dd9bddad19d089d9d77a]]]
Former-commit-id: 688181f543db6cf177477bb762464f63f6c2c7bc [formerly 8ad6dba9efa6dd8d96d578b09177b28ae3102fd6] [formerly 76e5a100af85170f38f32b3ff157327cd66fa8bb [formerly ecdd9fc140b1f3353ce0dccd59298d7647d6172e]]
Former-commit-id: 560922448b198b967fa4d1833d56f0603d5d480c [formerly ef34d7f2ec679c1f4d5bf3e7c6d87797af12792e]
Former-commit-id: c34371ef9d6afda566829f3a22cbb39c8392a934
Former-commit-id: 2d657d3b171656f135cfe6e339b7bb1dafc37001

--- @client/customizations.coffee
+++ @client/customizations.coffee
@@ -1877,24 +1877,6 @@

   show_score: false

-
-  # auth:
-  #   user_questions : [
-  #     {
-  #       tag: 'bitcoin_developer.editable'
-  #       question: 'Others consider me a bitcoin developer'
-  #       input: 'dropdown'
-  #       options:['No', 'Yes']
-  #       required: false
-  #     },{
-  #       tag: 'bitcoin_business.editable'
-  #       question: 'I operate these bitcoin businesses (urls)'
-  #       input: 'text'
-  #       required: false
-  #     }
-  #   ]
-
-
   opinion_filters: [
     {
       label: 'Account holder'
@@ -1982,17 +1964,18 @@
               verticalAlign: 'middle'
               marginTop: 5

-            DIV
-              style:
-                paddingBottom: 10
-                fontSize: 16
-                color: '#444'
-
-              "Please first put your proposal into the Fidor Community platform, and link to it in your consider.it proposal.
-              This allows us to converse, update our opinions, and track progress over a longer period of time."
-
-
-
+            if homepage
+              DIV
+                style:
+                  paddingBottom: 10
+                  fontSize: 16
+                  color: '#444'
+
+                "Please first put your proposal into the Fidor Community platform, and link to it in your consider.it proposal.
+                This allows us to converse, update our opinions, and track progress over a longer period of time."
+
+
+customizations.fidoruk.NonHomepageHeader = customizations.fidoruk.HomepageHeader

 customizations.bitcoin =


Update example.pre.coffee

Update example.pre.coffee

--- demo/input/example.pre.coffee
+++ demo/input/example.pre.coffee
@@ -75,3 +75,7 @@
 	constraints.push(formula :: a + b ** 2)
 	console.log(*) = jsx :: {username} says: {message}
 	console.log(*) = i8n :: "Hello {{username}}" #quotes are optional
+
+	import {sql, promisify} from 'utils'
+	query = sql :: select * from table where criteria = true
+	result = await promisify :: http.get(url) #macro to promisify an async function with the err, result callback


Fix rimg

Fix rimg

--- modules/image.coffee
+++ modules/image.coffee
@@ -45,8 +45,8 @@
         # Send the image
         msg.reply '', embed: {
           title: l.generic.sauceBtn
-          url: r.items[0].image.contextLink
-          image: { url: r.items[0].link }
+          url: image.image.contextLink
+          image: { url: image.link }
         }
       catch err
         if err.statusCode is 403


Sending invalid JSON does not crash the server.

--- server/connections.coffee
+++ server/connections.coffee
@@ -29,8 +29,11 @@
       user = new User(socket, this)

       socket.on 'data', (data) =>
-        # todo: error handling.
-        data = JSON.parse(data)
+        try
+          data = JSON.parse(data)
+        catch e
+          # Invalid JSON. Discard.
+          return
         messageType = data.messageType
         for callback in (@callbacks[messageType] || [])
           callback.apply(user, [user, data.data...])


Don't overwrite cmap method

Don't overwrite cmap method

--- lib/font/subset.coffee
+++ lib/font/subset.coffee
@@ -29,7 +29,7 @@

     return string

-  cmap: ->
+  generateCmap: ->
     # generate the cmap table for this subset
     unicodeCmap = @font.cmap.tables[0].codeMap
     mapping = {}
@@ -67,7 +67,7 @@

   encode: ->
     # generate the Cmap for this subset
-    cmap = CmapTable.encode @cmap(), 'unicode'
+    cmap = CmapTable.encode @generateCmap(), 'unicode'
     glyphs = @glyphsFor @glyphIDs()

     # compute old2new and new2old mapping tables


one more comment on the new "separate aligned lines" policy

--- fizzylogo_tokenizer.coffee
+++ fizzylogo_tokenizer.coffee
@@ -268,6 +268,32 @@

   return outputSource.replace /^[ ]*/g, ""

+# since we separate with ";" all aligned lines, we need
+# a way to make the program "flow" again in some cases,
+# so here we go. Note that this is not strictly necessary,
+# you can always indent in non-aligned way, for example
+# in the case of the "do" one could write:
+#
+#    for each word in
+#    ﹍﹍myList
+#    ﹍do
+#    ﹍﹍codeToBeRun eval
+#    something else
+#
+# and that needs no fixing by this function. However,
+# it's rather unconventional to have that second line
+# to have TWO tabs, expecially in some cases such as
+# if/else-if/else , where you'd have to write:
+#
+#   if a==5:
+#   ﹍﹍console print "yes a is 5"
+#   ﹍else:
+#   ﹍﹍console print "no a is not 5"
+#   console print ". the end."
+#
+# which is somewhat unconventional.
+# Hence, we apply this trick here.
+
 removeStatementSeparatorsBeforeAlignedConstructs = (command) ->
   command = command.replace /[; ]*(do[ \n])/g, " $1"
   command = command.replace /[; ]*(by[ \n])/g, " $1"


removed transitionend events

removed transitionend events

--- oriDomi.coffee
+++ oriDomi.coffee
@@ -12,7 +12,6 @@
 silent = false
 testEl = document.createElement 'div'
 prefixList = ['Webkit', 'Moz', 'O', 'ms', 'Khtml']
-transitionEnd = 'webkitTransitionEnd transitionend oTransitionEnd MSTransitionEnd KhtmlTransitionEnd'
 oriDomiSupport = true


return this from setTweening

return this from setTweening

--- oridomi.coffee
+++ oridomi.coffee
@@ -702,8 +702,7 @@
         for side in shaderPair
           @_shaders[@lastOp.anchor][side][i].style[css.transitionDuration] = speed

-    # Return null and not the loop's result.
-    null
+    @

   # Gives the element a resize cursor to prompt the user to drag the mouse.


Revert style

Revert style

--- server/publication.coffee
+++ server/publication.coffee
@@ -58,9 +58,9 @@
       hmac.update "#{ num }"
       digest = hmac.digest 'hex'

-      return
-        offset: parseInt(digest, 16) % (@size - VERIFICATION_SAMPLE_SIZE)
-        size: VERIFICATION_SAMPLE_SIZE
+      # return
+      offset: parseInt(digest, 16) % (@size - VERIFICATION_SAMPLE_SIZE)
+      size: VERIFICATION_SAMPLE_SIZE

   # A subset of public fields used for search results to optimize transmission to a client
   # This list is applied to PUBLIC_FIELDS to get a subset
@@ -146,10 +146,10 @@

     samples = if verify then existingPublication._verificationSamples Meteor.personId() else null

-    return
-      publicationId: id
-      verify: verify
-      samples: samples
+    # return
+    publicationId: id
+    verify: verify
+    samples: samples

   uploadPublication: (file, options) ->
     throw new Meteor.Error 401, "User is not signed in." unless Meteor.personId()


DRYer nudge strings

DRYer nudge strings

--- oridomi.coffee
+++ oridomi.coffee
@@ -514,19 +514,19 @@
     switch anchor
       when 'left'
         axes = [0, angle, 0]
-        translate = 'X(-1px)'
+        translate = 'X(-1'
       when 'right'
         axes = [0, -angle, 0]
-        translate = 'X(1px)'
+        translate = 'X(1'
       when 'top'
         axes = [-angle, 0, 0]
-        translate = 'Y(-1px)'
+        translate = 'Y(-1'
       when 'bottom'
         axes = [angle, 0, 0]
-        translate = 'Y(1px)'
+        translate = 'Y(1'

     axes = [angle, angle, angle] if fracture
-    "rotateX(#{ axes[0] }deg) rotateY(#{ axes[1] }deg) rotateZ(#{ axes[2] }deg) translate#{ translate }"
+    "rotateX(#{ axes[0] }deg) rotateY(#{ axes[1] }deg) rotateZ(#{ axes[2] }deg) translate#{ translate }px)"

   # `_normalizeAngle` validates a given angle by making sure it's a float and by


groups: wip of intro text for /Groups

groups: wip of intro text for /Groups

--- client/app/Applications/Groups.kdapplication/AppController.coffee
+++ client/app/Applications/Groups.kdapplication/AppController.coffee
@@ -119,13 +119,16 @@
       onboarding            :
         everything          :
           """
-
yooo onboard me for da groop!!!

-

-              Cosby sweater ethnic neutra meggings, actually single-origin coffee next level before they sold out scenester food truck banh mi gluten-free pitchfork. Before they sold out whatever chillwave, flexitarian stumptown mlkshk pour-over iphone brooklyn semiotics. Seitan brooklyn cliche before they sold out blue bottle polaroid godard marfa fingerstache blog authentic salvia.
-

-

-              Portland freegan raw denim readymade, mumblecore neutra brunch keffiyeh. Fashion axe beard gluten-free, pork belly plaid bushwick lo-fi pitchfork etsy. Cosby sweater portland umami deep v VHS, shoreditch biodiesel raw denim butcher messenger bag ethnic scenester banh mi. Polaroid gluten-free you probably haven't heard of them +1, tumblr four loko fap shoreditch put a bird on it plaid disrupt freegan. Blog occupy typewriter put a bird on it authentic. Semiotics bespoke hashtag fap cliche. Viral semiotics tonx 8-bit selfies cliche, Austin bushwick photo booth keytar art party occupy.
-

+
Koding groups is a simple way to connect and interact with people who share
+            your interests.

+
+
When you join a group within a community such as your univeristy or you
+company, you can share virtual machines, files and stay up to date on the
+activites of others in your group.

+
+
Easy to get started and safe

+
+
Groups are free to create. You decide who can join and what they see.

           """
         mine                : "
yooo onboard me for my groops!!!
"
       filter                :


client: chatlio: fixed copy

client: chatlio: fixed copy

--- client/home/lib/utilities/components/customerfeedback/view.coffee
+++ client/home/lib/utilities/components/customerfeedback/view.coffee
@@ -7,7 +7,7 @@
   render: ->

-      Customer Feedback
+      Chatlio
       Enable Chatlio.com for real-time customer feedback

@@ -15,15 +15,15 @@
         existing Slack service. For this integration you need to create an
         account at chatlio.com. * Requires Slack integration.

-        Once you get your Chatlio data-widget-id
-        and paste below, we will complete the integration for you.
+        Once you get your Chatlio data-widget-id and
+        paste below, we will complete the integration for you.

-      <filedset>
+      <fieldset>
         Chatlio.com data-widget-id
         <InputArea value={@props.defaultValue} callback={@props.onInputAreaChange} />
         <SaveButton callback={@props.handleSaveButton} />
         <GuideButton />
-      </filedset>
+      </fieldset>


add image alternative text.

add image alternative text.

--- fav.coffee
+++ fav.coffee
@@ -72,40 +72,40 @@
   @view index: ->
     script id: 'tweetTemplate', type: 'x-jquery-tmpl', ->
       div class: "item", ->
-        a class: "icon_link", href: "/${user.screen_name}", -> img class:"icon", src: "${user.profile_image_url}"
+        a class: "icon_link", href: "/${user.screen_name}", -> img class:"icon", src: "${user.profile_image_url}", alt:"${user.screen_name} icon"
         a class: "screen_name", href: "/${user.screen_name}", -> "${user.screen_name}"
         p class: "item_content", ->
         footer class:"item_footer", ->
           div class: "tools", ->
             span class: "fav_button", ->
               text "{{if favorited}}"
-              img src:"/star.png"
+              img src:"/star.png", alt:"favorited"
               text "{{else}}"
-              img src:"/star_w.png"
+              img src:"/star_w.png", alt:"No favorite yet."
               text "{{/if}}"
               span class:"star", -> "fav"
             text " | "
             span class: "retweet_button", ->
               text "{{if retweeted}}"
-              img src:"/rt.png"
+              img src:"/rt.png", alt:"retweeted"
               text "{{else}}"
-              img src:"/rt_w.png"
+              img src:"/rt_w.png", alt:"No retweet yet."
               text "{{/if}}"
               span class:"rt", -> "RT"
             text " | "
             span class: "user_button", ->
               a href: "http://twitter.com/${user.screen_name}", target:"_blank", ->
-                img src:"/user.png"
+                img src:"/user.png", alt:"Jump to twitter user page"
                 span class:"user", -> "user"
     div id: "favs", ->
       header ->
-        img class:"icon", src:"/favicon73x73.png"
+        img class:"icon", src:"/favicon73x73.png", alt:"user icon"
         form ->
           input class:"screen_name_input", type: 'text'
           input class:"favtile_button", type: 'submit', value: "favtile!"
       div class: 'items'
       footer class: "favs_footer", ->
-        img class:"loading", src: "ajax-loader.gif"
+        img class:"loading", src: "ajax-loader.gif", alt:"Now loading..."
         p id:"error"

   @view layout: ->
@@ -142,7 +142,7 @@
         div class: "content", ->
           @body
         div class:"top_background", ->
-          img src: "top_background.png"
+          img src: "top_background.png", alt: "Enter your twitter ID"
         footer class: "global_footer", ->
           a href:"https://twitter.com/share", class:"twitter-share-button", "data-via":"hanachin_", "data-size":"large", ->
             text "Tweet"


Calculate lineWidth of underline/strike based on font size

--- lib/mixins/text.coffee
+++ lib/mixins/text.coffee
@@ -185,11 +185,13 @@
         if options.underline or options.strike
             @save()
             @strokeColor @_fillColor... unless options.stroke
-            @lineWidth 2
+
+            lineWidth = if @_fontSize >= 20 then 2 else 1
+            @lineWidth lineWidth

             d = if options.underline then 1 else 2
             lineY = y + @currentLineHeight() / d
-            lineY -= 2 if options.underline
+            lineY -= lineWidth if options.underline

             @moveTo x, lineY
             @lineTo x + renderedWidth, lineY


Polishing up 3Dcode.

Polishing up 3Dcode.

--- source/Pieces3D.js.coffee
+++ source/Pieces3D.js.coffee
@@ -41,59 +41,59 @@
     for x_side in [Layer.R, slice, Layer.L]
       for y_side in [Layer.F, slice, Layer.B]
         for z_side in [Layer.U, slice, Layer.D]
-          name = standard_piece_name(x_side, y_side, z_side)
-          new_3d_piece = new THREE.Object3D()
-          new_3d_piece.name = name
-          new_3d_piece.sticker_locations = name.split('')
-          new_3d_piece.middle = v3(x_side.normal.x, y_side.normal.y, z_side.normal.z).multiplyScalar(2)
+          piece = this._new_piece(x_side, y_side, z_side)

           for side in [x_side, y_side, z_side]
             unless side == slice
-              sticker_look = colors.to_draw(name, side)
+              sticker_look = colors.to_draw(piece.name, side)

-              this._add_sticker(side, new_3d_piece, sticker_look)
-              this._add_hover_sticker(side, new_3d_piece, sticker_look, hover) if sticker_look.hovers && hover > 1
-              this._add_cube(side, new_3d_piece, colors.of('cube'))
+              this._add_sticker(side, piece, sticker_look)
+              this._add_hover_sticker(side, piece, sticker_look, hover) if sticker_look.hovers && hover > 1
+              this._add_cubeside(side, piece, colors.of('cube'))

-          this[name] = @at[name] = new_3d_piece
-          scene.add(new_3d_piece)
+          this[piece.name] = @at[piece.name] = piece
+          scene.add(piece)
+
+  _new_piece: (x_side, y_side, z_side) ->
+    new_piece = new THREE.Object3D()
+    new_piece.name = standard_piece_name(x_side, y_side, z_side)
+    new_piece.sticker_locations = new_piece.name.split('')
+    new_piece.middle = v3(2*x_side.normal.x, 2*y_side.normal.y, 2*z_side.normal.z)
+    new_piece

   _add_sticker: (side, piece_3d, sticker) ->
     [dx, dy] = this._offsets(side.normal, 0.90, false)
-    piece_3d.add(this._3d_diamond(this._square_center(side, piece_3d.middle, 1.0002), dx, dy, sticker.color))
+    piece_3d.add(this._diamond(this._square_center(side, piece_3d.middle, 1.0002), dx, dy, sticker.color))

     if sticker.x_color
       this._add_X(side, piece_3d, sticker.x_color, 1.0004, true)

   _add_hover_sticker: (side, piece_3d, sticker, hover) ->
     [dx, dy] = this._offsets(side.normal, 0.98, true)
-    piece_3d.add(this._3d_diamond(this._square_center(side, piece_3d.middle, hover), dx, dy, sticker.color))
+    piece_3d.add(this._diamond(this._square_center(side, piece_3d.middle, hover), dx, dy, sticker.color))

     if sticker.x_color
       this._add_X(side, piece_3d, sticker.x_color, hover - 0.0002, false)

-  _add_X: (side, piece_3d, color, hover, reversed) ->
+  _add_cubeside: (side, piece_3d, color) ->
+    [dx, dy] = this._offsets(side.normal, 1.0, true)
+    piece_3d.add(this._diamond(this._square_center(side, piece_3d.middle, 1), dx, dy, color))
+
+  _add_X: (side, piece_3d, color, distance, reversed) ->
     [dx, dy] = this._offsets(side.normal, 0.54, reversed)
-    center = this._square_center(side, piece_3d.middle, hover)
-    piece_3d.add(this._3d_rect(center, dx, v3_x(dy, 0.14), color))
-    piece_3d.add(this._3d_rect(center, v3_x(dx, 0.14), dy, color))
-
-  _add_cube: (side, piece_3d, color) ->
-    [dx, dy] = this._offsets(side.normal, 1.0, true)
-    piece_3d.add(this._3d_diamond(this._square_center(side, piece_3d.middle, 1), dx, dy, color))
+    center = this._square_center(side, piece_3d.middle, distance)
+    piece_3d.add(this._rect(center, dx, v3_x(dy, 0.14), color))
+    piece_3d.add(this._rect(center, v3_x(dx, 0.14), dy, color))

   _square_center: (side, piece_center, distance) ->
     v3_add(piece_center, v3_x(side.normal, distance))

-  _3d_diamond: (stc, d1, d2, color) ->
-    this._3d_4side(v3_add(stc, d1), v3_add(stc, d2), v3_sub(stc, d1), v3_sub(stc, d2), color)
+  _rect: (center, d1, d2, color) ->
+    this._diamond(center, v3_add(d1, d2), v3_sub(d1, d2), color)

-  _3d_rect: (stc, d1, d2, color) ->
-    this._3d_diamond(stc, v3_add(d1, d2), v3_sub(d1, d2), color)
-
-  _3d_4side: (v1, v2, v3 ,v4, color) ->
+  _diamond: (center, d1, d2, color) ->
     geo = new THREE.Geometry();
-    geo.vertices.push(v1, v2, v3 ,v4);
+    geo.vertices.push(v3_add(center, d1), v3_add(center, d2), v3_sub(center, d1), v3_sub(center, d2));
     geo.faces.push(new THREE.Face3(0, 1, 2), new THREE.Face3(0, 2, 3));

     # http://stackoverflow.com/questions/20734216/when-should-i-call-geometry-computeboundingbox-etc
@@ -109,5 +109,4 @@

     dx = v3_add(axis2, axis3).multiplyScalar(sticker_size * flip)
     dy = v3_sub(axis2, axis3).multiplyScalar(sticker_size)
-    [dx, dy]
-
+    [dx, dy]


Move require statement to the top of the file

--- lib/to-the-hubs.coffee
+++ lib/to-the-hubs.coffee
@@ -1,4 +1,5 @@
-EditSession = require 'edit-session'
+child_process = require 'child_process'
+EditSession   = require 'edit-session'

 githubOpen = (editSession) ->
   gitUrl = git.getRepo().getConfigValue("remote.#{remoteName()}.url")
@@ -11,8 +12,7 @@

   blobUrl = "#{repoUrl}/blob/#{branch()}/#{path}"

-  exec = require('child_process').exec
-  exec "open #{blobUrl}", (error, stdout, stderr) ->
+  child_process.exec "open #{blobUrl}", (error, stdout, stderr) ->
     throw error if error?

 githubRepoUrl = (gitUrl) ->


:bug: Add a dummy error to act as a summary Fix the bug where first error would not be shown sometimes Fix #41

--- lib/typechecker.coffee
+++ lib/typechecker.coffee
@@ -76,6 +76,12 @@
       Main.V.MPI.clear()
       if LeErrors.length
         Main.V.MPI.attach()
+        # Set a summary
+        Main.V.MPI.add(new Main.V.MP.PlainMessageView(
+          raw: true
+          message: ''
+        ))
+        # Summary part ends
         LeErrors.forEach (error)->
           error.Render(RowStart,RowEnd,ActiveFile,Editor,EditorView,LineHeight)
       else


reporter: add one reporter per entire pipeline to ensure interval is cleared

If you add a separate reporter to each pipeline segment, if an error is emitted
from a stream, only the segment with that stream will clear its reporter.

--- lib/understream.coffee
+++ lib/understream.coffee
@@ -97,7 +97,6 @@
     # If the final stream is Readable, attach a dummy writer to receive its output
     # and alleviate pressure in the pipe
     @_streams.push new DevNull() if is_readable _(@_streams).last()
-    add_reporter @_streams
     handler = (err) =>
       if cb.length is 1
         cb err
@@ -105,19 +104,18 @@
         cb err, result
     _(@_streams).last().on 'finish', handler
     # Catch any errors thrown emitted by a stream with a handler
-    _(@_streams).each (stream) ->
-      _.each (stream._pipeline?() or [stream]), (stream) ->
-        domainify stream
-        stream.on 'error', handler
+    pipeline = _.flatten _(@_streams).map (stream) -> stream._pipeline?() or [stream]
+    add_reporter pipeline
+    _.each pipeline, (stream) ->
+      domainify stream
+      stream.on 'error', handler
     debug 'running'
     pipe_streams_together @_streams...
     @
   readable: => # If you want to get out of understream and access the raw stream
-    add_reporter @_streams
     pipe_streams_together @_streams...
     _.extend _.last(@_streams), _pipeline: => @_streams
   duplex: =>
-    add_reporter @_streams
     _.extend new StreamCombiner(@_streams...), _pipeline: => @_streams
   stream: => @readable() # Just an alias for compatibility purposes
   pipe: (stream_instance) => # If you want to add an instance of a stream to the middle of your understream chain


translate sanitization

translate sanitization

--- lineman/app/app.coffee
+++ lineman/app/app.coffee
@@ -33,6 +33,8 @@
     locale = window.Loomio.currentUserLocale
     $translateProvider.useUrlLoader("/api/v1/translations").
                        preferredLanguage(locale)
+
+    $translateProvider.useSanitizeValueStrategy('sanitizeParameters');

   # stuff that only runs in production environment
   if window.Loomio? and window.Loomio.environment == 'production'


activity: simplify `post` and `edit` methods of `ActivityAppController` class

--- client/Social/Activity/AppController.coffee
+++ client/Social/Activity/AppController.coffee
@@ -24,18 +24,12 @@

   post: (options = {}, callback = noop) ->

-    {body, payload} = options
-    {socialapi} = KD.singletons
-
-    socialapi.message.post {body, payload}, callback
+    (KD.singleton 'socialapi').message.post options, callback

   edit: (options = {}, callback = noop) ->

-    {id, body, payload} = options
-    {socialapi} = KD.singletons
-
-    socialapi.message.edit {id, body, payload}, callback
+    (KD.singleton 'socialapi').message.edit options, callback

   reply: ({activity, body}, callback = noop) ->


Activity: changed ctrl to meta in shortcuts

--- client/Social/Activity/AppController.coffee
+++ client/Social/Activity/AppController.coffee
@@ -8,10 +8,10 @@
       'next tab'     : 'goToNextTab'
       'previous tab' : 'goToPreviousTab'
     keyBindings: [
-      { command: 'next tab',      binding: 'ctrl+alt+]',    global: yes }
-      { command: 'next tab',      binding: 'ctrl+alt+down', global: yes }
-      { command: 'previous tab',  binding: 'ctrl+alt+up',   global: yes }
-      { command: 'previous tab',  binding: 'ctrl+alt+[',    global: yes }
+      { command: 'next tab',      binding: 'meta+alt+]',    global: yes }
+      { command: 'next tab',      binding: 'meta+alt+down', global: yes }
+      { command: 'previous tab',  binding: 'meta+alt+up',   global: yes }
+      { command: 'previous tab',  binding: 'meta+alt+[',    global: yes }
     ]

   constructor: (options = {}) ->


kite: increase ping interval

kite: increase ping interval

--- client/landing/app/MainApp/kite/kite.coffee
+++ client/landing/app/MainApp/kite/kite.coffee
@@ -70,7 +70,7 @@

     @pingTimeoutId = setTimeout =>
       @pingChannel()
-    , 5000
+    , 10000

   handleChannelMessage: (args) ->


add toggle

add toggle

--- led-server.coffee
+++ led-server.coffee
@@ -2,6 +2,8 @@
 gpio = require 'gpio'
 app = express()
 gpio18 = gpio.export 18
+
+gpio.state = 0

 app.configure ->
   app.set "port", process.env.PORT or 4000
@@ -19,5 +21,15 @@
   gpio18.reset()

+app.get '/toggle/18', ->
+  gpio18.set(1 - gpio.state)
+
+
+gpio18.on("change", (val) ->
+  # value will report either 1 or 0 (number) when the value changes
+   console.log(val)
+   gpio18.state = val
+
+
 app.listen app.get('port'), ->
   console.log "Listening on port #{app.get('port')}"


Avoid unnecessary check

Avoid unnecessary check

--- lib/Format.coffee
+++ lib/Format.coffee
@@ -99,7 +99,7 @@
       args.unshift arg
       match
     )
-  fmt += ' ' + serialize arg, color for arg in args if args.length
+    fmt += ' ' + serialize arg, color for arg in args if args.length

   fmt = fmt.replace(ESCAPE_REGEX, '%') if fmt.replace?
   serialize fmt, color


If the compile request errors out, set view to 'errors'.

--- services/web/public/coffee/ide/pdf/controllers/PdfController.coffee
+++ services/web/public/coffee/ide/pdf/controllers/PdfController.coffee
@@ -179,6 +179,7 @@
 				.error () ->
 					$scope.pdf.compiling = false
 					$scope.pdf.error = true
+					$scope.pdf.view = 'errors'

 		# This needs to be public.
 		ide.$scope.recompile = $scope.recompile


Remove unused function

Remove unused function

--- lib/layervault/services/upload.coffee
+++ lib/layervault/services/upload.coffee
@@ -14,12 +14,6 @@
       @getAwsCredentials md5, (err, resp) =>
         return cb(err, null) if err
         @sendFileToS3 resp, cb
-
-  calculateMd5: (cb) ->
-    md5 = crypto.createHash 'md5'
-    s = fs.ReadStream(@localPath)
-    s.on 'data', (d) -> md5.update(d)
-    s.on 'end', -> cb md5.digest('hex')

   getAwsCredentials: (md5, cb) => @api.put @file.nodePath, md5: md5, cb


remove malfunctioning spec (it's tested in store)

--- tutor/test/components/questions/exercises-display.spec.coffee
+++ tutor/test/components/questions/exercises-display.spec.coffee
@@ -43,12 +43,3 @@
         document.querySelector('.question-library-min-exercise-exclusions .btn-default')
       )
       expect( ExerciseActions.saveExerciseExclusion ).to.have.been.called
-
-  it 'saves exercise exclusions immediately when not at minimum', ->
-    ex = ld.cloneDeep(EXERCISES)
-    ex.items = ex.items.slice(0, 3)
-    ExerciseActions.loadedForCourse(ex, COURSE_ID, SECTION_IDS)
-    Testing.renderComponent( ExercisesDisplay, props: @props ).then ({dom}) ->
-      Testing.actions.click(dom.querySelector('.openstax-exercise-preview .action.exclude'))
-      expect( ExerciseActions.saveExerciseExclusion ).to.have.been
-        .calledWith(COURSE_ID, ex.items[0].id, true)


minor bug fixes in markupable that will allow for them to be re-initialized nicely

--- vendor/assets/javascripts/mercury/regions/markupable.js.coffee
+++ vendor/assets/javascripts/mercury/regions/markupable.js.coffee
@@ -17,11 +17,11 @@
     height = @element.height()

     value = @element.html().replace(/^\s+|\s+$/g, '').replace('>', '>')
+    @element.removeClass(Mercury.config.regionClass)
     @textarea = jQuery('<textarea>', @document).val(value)
     @textarea.attr('class', @element.attr('class')).addClass('mercury-textarea')
     @textarea.css({border: 0, background: 'transparent', display: 'block', width: width, height: height, fontFamily: '"Courier New", Courier, monospace', fontSize: '14px'})
     @element.empty().append(@textarea)
-    @element.removeClass(Mercury.config.regionClass)

     @previewElement = jQuery('<div>', @document)
     @element.append(@previewElement)
@@ -163,14 +163,17 @@

   togglePreview: ->
     if @previewing
+      @previewing = false
       @previewElement.hide()
       @element.show()
+      @focus() if Mercury.region == @
     else
+      @previewing = true
       value = @converter.makeHtml(@element.val())
       @previewElement.html(value)
       @previewElement.show()
       @element.hide()
-    super
+      Mercury.trigger('region:blurred', {region: @})

   execCommand: (action, options = {}) ->


Use a here-string instead of an array

Use a here-string instead of an array

--- lib/rails/remote_submit_button.coffee
+++ lib/rails/remote_submit_button.coffee
@@ -19,14 +19,14 @@
 # This workaround only needs to happen on AJAX forms, so
 # `data-remote=true` must be set on the form to enable it.

-submitSelectors = [
-  'form[data-remote] input[type=submit]',
-  'form[data-remote] button[type=submit]',
-  'form[data-remote] button:not([type])'
-]
+submitSelectors = """
+  form[data-remote] input[type=submit],
+  form[data-remote] button[type=submit],
+  form[data-remote] button:not([type])
+"""

 # Listen for all submit buttons clicks that bubble up to the doucment.
-$(document).delegate submitSelectors.join(', '), 'click', ->
+$(document).delegate submitSelectors, 'click', ->
   submit = $(this)
   form   = submit.closest 'form'
   input  = form.find '.js-submit-button-value'


minor build script fix

minor build script fix

--- package-scripts.cson
+++ package-scripts.cson
@@ -133,7 +133,7 @@
     &&
         mv build-output/r.js
         build-output/_multiple-bundles/RequireJS.js
-    ||
+    &&
     npm run rimraf
         build-output/_multiple-bundles/RequireJS.js.src.js
 '


Fix tail view rendering after the first render (Fixes #110)

--- SingularityUI/app/views/tailer.coffee
+++ SingularityUI/app/views/tailer.coffee
@@ -160,6 +160,8 @@
     render: ->
         @$el.addClass 'loading'

+        @lines.sort()
+
         @taskHistory.fetch().done =>
             @$el.removeClass 'loading'


Fix "Uncaught ReferenceError: defer is not defined" introduced in e2bceea2d8a1786d79b95d9bddab9e0b3309aa1c

--- src/trix/config/selection_elements.coffee
+++ src/trix/config/selection_elements.coffee
@@ -1,4 +1,4 @@
-{makeElement} = Trix
+{makeElement, defer} = Trix

 prototypes =
   cursorPoint:


add fix again

add fix again

--- server/job.coffee
+++ server/job.coffee
@@ -605,7 +605,16 @@
       cluster: job_result.terms('_cid')
   res.limits = {} # may not be worth reporting on limit index in new structure
   job_limit.each 'NOT last:*', (lm) -> res.limits[lm.group ? lm._id] = {date:lm.created_date,limit:lm.limit}
-  job_job.each 'NOT done:true', {_source:['count','processed']}, (j) -> res.jobs.waiting += (j.count - (j.processed ? 0))
+  job_job.each 'NOT done:true', {_source:['_id','count','processed']}, (j) ->
+    console.log j
+    console.log (j.count - (j.processed ? 0))
+    if j.processed? and typeof j.processed isnt 'number'
+      j.processed = j.processed.length
+      job_job.update j._id, {processed: j.processed}
+      res.fixprocessed ?= 0
+      res.fixprocessed += 1
+    res.jobs.waiting += (j.count - (j.processed ? 0))
+    console.log res.jobs.waiting
   return res

 API.job.orphans = (remove=false,types=['process','result']) ->


job reload change

job reload change

--- server/job.coffee
+++ server/job.coffee
@@ -384,6 +384,7 @@
     API.log {msg:'Not running more jobs, job max memory reached', _cid: process.env.CID, _appid: process.env.APP_ID, function:'API.job.next'}
   else
     API.log {msg:'Checking for jobs to run', ignores: {groups:API.job._ignoregroups,ids:API.job._ignoreids}, function:'API.job.next', level:'debug'}
+    job_process.refresh()
     match = must_not:[{term:{available:false}}] # TODO check this will get matched properly to something where available = false
     match.must_not.push({term: 'group.exact':g}) for g of API.job._ignoregroups
     match.must_not.push({term: '_id':m}) for m of API.job._ignoreids
@@ -392,7 +393,7 @@
       if job_processing.get(p._id)? # because job_process is searched, there can be a delay before it reflects deleted jobs, so accept this extra load on ES
         API.job._ignoreids[p._id] = now + API.settings.job?.interval ? 1000
         future = new Future()
-        Meteor.setTimeout (() -> future.return()), Math.floor((API.settings.job?.interval ? 1000)/3)
+        Meteor.setTimeout (() -> future.return()), Math.floor((API.settings.job?.interval ? 1000)/2)
         future.wait()
         return API.job.next()
       else if p.limit?
@@ -448,11 +449,10 @@
   Meteor.setTimeout (() -> future.return()), Math.floor(Math.random()*interval+1)
   future.wait()
   API.log {msg: 'Starting job runner with interval ' + interval, _cid: process.env.CID, _appid: process.env.APP_ID, function: 'API.job.start', level: 'debug'}
-  job_limit.remove '*'
-  job_process.remove 'STUCK'
-  job_processing.remove 'STUCK'
-  job_result.remove 'STUCK'
-  API.job.reload() # TODO this will be risky if multiple cluster machines try to run it - add a limit checker or something so it only runs on the first machine
+  if not job_limit.get 'START_RELOAD'
+    job_limit.insert _id: 'START_RELOAD'
+    API.job.reload()
+    job_limit.remove '*'
   #job_process.remove 'TEST'
   #job_processing.remove 'TEST'
   #job_result.remove 'TEST'


Fix random team assign

Fix random team assign

--- server/lib.coffee
+++ server/lib.coffee
@@ -8,5 +8,4 @@
 Meteor.methods
   lastTeam: () ->
     team = Teams.find({}, {sort:{$natural: -1}}, limit:1).fetch()[0]
-    console.log team.team
     team.team


adds event emitter interface to connection

--- drivers/javascript/src/net.coffee
+++ drivers/javascript/src/net.coffee
@@ -6,6 +6,11 @@
 goog.require("Query")
 goog.require("goog.proto2.WireFormatSerializer")

+# Eventually when we ditch Closure we can actually use the node
+# event emitter library. For now it's simple enough that we'll
+# emulate the interface.
+# var events = require('events')
+
 class Connection
     DEFAULT_HOST: 'localhost'
     DEFAULT_PORT: 28015
@@ -26,12 +31,17 @@

         @buffer = new ArrayBuffer 0

-        @_connect = =>
+        @_events = {}
+
+        errCallback =  =>
+            callback new RqlDriverError "Could not connect to #{@host}:#{@port}."
+
+        @on 'error', errCallback
+
+        @on 'connect', =>
             @open = true
-            @_error = => # Clear failed to connect callback
+            @removeListener 'error', errCallback
             callback null, @
-
-        @_error = => callback new RqlDriverError "Could not connect to #{@host}:#{@port}."

     _data: (buf) ->
         # Buffer data, execute return results if need be
@@ -110,7 +120,7 @@
             else
                 cb new RqlDriverError "Unknown response type"
         else
-            @_error new RqlDriverError "Unknown token in response"
+            @emit 'error', new RqlDriverError "Unknown token in response"

     close: ar () ->
         @open = false
@@ -194,6 +204,36 @@

         @write finalArray.buffer

+    ## Emulate the event emitter interface
+
+    addListener: (event, listener) ->
+        unless @_events[event]?
+            @_events[event] = []
+        @_events[event].push(listener)
+
+    on: (event, listener) -> @addListener(event, listener)
+
+    once: (event, listener) ->
+        listener._once = true
+        addListener(event, listener)
+
+    removeListener: (event, listener) ->
+        if @_events[event]?
+            @_events[event] = @_events[event].filter (lst) -> (lst isnt listener)
+
+    removeAllListeners: (event) -> delete @_events[event]
+
+    listeners: (event) -> @_events[event]
+
+    emit: (event, args...) ->
+        toRemove = []
+        for lst in @_events[event]
+            lst.apply(null, args)
+            if lst._once
+                toRemove.push(lst)
+        for lst in toRemove
+            @removeListener(event, lst)
+
 class TcpConnection extends Connection
     @isAvailable: -> typeof require isnt 'undefined' and require('net')

@@ -215,9 +255,9 @@
             buf = new ArrayBuffer 4
             (new DataView buf).setUint32 0, VersionDummy.Version.V0_1, true
             @write buf
-            @_connect()
-
-        @rawSocket.on 'error', => @_error()
+            @emit 'connect'
+
+        @rawSocket.on 'error', (args...) => @emit 'error', args...

         @rawSocket.on 'end', => @_end()

@@ -268,9 +308,9 @@
                 if xhr.status is 200
                     @_url = url
                     @_connId = (new DataView xhr.response).getInt32(0, true)
-                    @_connect()
+                    @emit 'connect'
                 else
-                    @_error()
+                    @emit 'error', new RqlDriverError "XHR error, http status #{xhr.status}."
         xhr.send()

     cancel: ->
@@ -296,7 +336,7 @@
     constructor: (embeddedServer, callback) ->
         super({}, callback)
         @_embeddedServer = embeddedServer
-        @_connect()
+        @emit 'connect'

     write: (chunk) -> @_data(@_embeddedServer.execute(chunk))


Verify thrown error

Verify thrown error

--- spec/autosave-spec.coffee
+++ spec/autosave-spec.coffee
@@ -154,9 +154,13 @@
     saveError.code = 'EACCES'
     saveError.path = initialActiveItem.getPath()
     initialActiveItem.save.andThrow(saveError)
+
+    errorCallback = jasmine.createSpy('errorCallback').andCallFake ({preventDefault}) -> preventDefault()
+    atom.onWillThrowError(errorCallback)
+
     initialActiveItem.insertText('a')
+    atom.config.set('autosave.enabled', true)

-    atom.config.set('autosave.enabled', true)
     expect(-> atom.workspace.destroyActivePaneItem()).not.toThrow()
-
     expect(initialActiveItem.save).toHaveBeenCalled()
+    expect(errorCallback.callCount).toBe 1


Updates the install shots for a show to use the v2 endpoint.

--- src/desktop/apps/show/components/flickity_zoom_sequence/view.coffee
+++ src/desktop/apps/show/components/flickity_zoom_sequence/view.coffee
@@ -1,6 +1,6 @@
 Backbone = require 'backbone'
 _ = require 'underscore'
-metaphysics = require '../../../../../lib/metaphysics.coffee'
+metaphysics = require '../../../../../lib/metaphysics2.coffee'
 initCarousel = require '../../../../components/merry_go_round/bottom_nav_mgr.coffee'
 ViewHelpers = require '../../helpers/view_helpers.coffee'
 template = -> require('../../templates/carousel.jade') arguments...


Default 'color' option of colorize() to yes

--- lib/colorize.iced
+++ lib/colorize.iced
@@ -68,7 +68,7 @@
 colorize = (diff, options={}) ->
   output = []
   colorizeToCallback diff, (color, line) ->
-    if options.color
+    if options.color ? yes
       output.push (options.theme?[color] ? Theme[color])("#{color}#{line}") + "\n"
     else
       output.push "#{color}#{line}\n"


this option somehow breaks key bindings

this option somehow breaks key bindings

--- lib/config.coffee
+++ lib/config.coffee
@@ -88,13 +88,15 @@
       else
         body.setAttribute('isotope-ui-gutter-style', 'false')

-    applyTooltipContrast = () ->
-      if atom.config.get('isotope-ui.lowContrastTooltip')
-        body.className =
-          body.setAttribute('isotope-ui-tooltip-lowcontrast', 'true')
-      else
-        body.className =
-          body.setAttribute('isotope-ui-tooltip-lowcontrast', 'false')
+    # applyTooltipContrast = () ->
+    #   if atom.config.get('isotope-ui.lowContrastTooltip')
+    #     body.className = body.setAttribute(
+    #       'isotope-ui-tooltip-lowcontrast', 'true'
+    #     )
+    #   else
+    #     body.className = body.setAttribute(
+    #       'isotope-ui-tooltip-lowcontrast', 'false'
+    #     )

     # run when atom is ready
@@ -108,7 +110,7 @@
     applyBackgroundGradient()
     applyBackgroundImage()
     applyGutterStyle()
-    applyTooltipContrast()
+    # applyTooltipContrast()

     # run when configs change
@@ -142,6 +144,6 @@

     atom.config.onDidChange 'isotope-ui.gutterStyle', ->
       applyGutterStyle()
-
-    atom.config.onDidChange 'isotope-ui.lowContrastTooltip', ->
-      applyTooltipContrast()
+    #
+    # atom.config.onDidChange 'isotope-ui.lowContrastTooltip', ->
+    #   applyTooltipContrast()


remove focus container

remove focus container

--- app/components/vnc-viewer.coffee
+++ app/components/vnc-viewer.coffee
@@ -30,7 +30,6 @@
     that = @
     @set "rfb", new RFB
       'target': canvasEl
-      'focusContainer': @element
       'encrypt': ENV.deviceFarmSsl
       'repeaterID': ''
       'true_color': true


JSUserCookies update

JSUserCookies update

--- JSKit/01_JSUserCookies.coffee
+++ JSKit/01_JSUserCookies.coffee
@@ -15,4 +15,4 @@
 		return ret

 	removeObjectForKey:(forKey)->
-		$.cookie(forKey, null)
+		$.removeCookie(forKey)


Fix Plotly graph exponenet formatting for log plots

--- _includes/coffee/result_comparison.coffee
+++ _includes/coffee/result_comparison.coffee
@@ -29,6 +29,7 @@
               type:chart_item.x_scale
               domain:chart_item.x_domain
               scaleanchor:chart_item.x_scaleanchor
+              exponentformat:"E"
             }
           yaxis:
             {
@@ -36,6 +37,7 @@
               title:chart_item.y_title
               type:chart_item.y_scale
               domain:chart_item.y_domain
+              exponentformat:"E"
             }
         }
     }


Memoize built packages

Memoize built packages

Packages that successfully built are now stored internally
so they can be quickly accessed on future calls instead of
returning an array of newly built packages on each call.

--- spec/snippets-spec.coffee
+++ spec/snippets-spec.coffee
@@ -250,6 +250,7 @@

   describe "snippet loading", ->
     beforeEach ->
+      atom.packages = null
       jasmine.unspy(LoadSnippetsTask.prototype, 'start')
       spyOn(LoadSnippetsTask.prototype, 'loadAtomSnippets').andCallFake -> @snippetsLoaded({})
       spyOn(LoadSnippetsTask.prototype, 'loadTextMateSnippets').andCallFake -> @snippetsLoaded({})


:fire: Cleanup validate specs

:fire: Cleanup validate specs

--- spec/validate-spec.coffee
+++ spec/validate-spec.coffee
@@ -111,13 +111,3 @@
       validate.messages([{type: 'Error', text: 'Well', class: 'error', filePath: '/'}], {name: ''})
       validate.messages([{type: 'Error', html: 'Well', class: 'error', filePath: '/'}], {name: ''})
       validate.messages([{type: 'Error', html: document.createElement('div'), class: 'error', filePath: '/'}], {name: ''})
-    it 'sets name on messages according to linter or message itself', ->
-      linter = {name: 'Wow'}
-
-      message = {type: 'Error', text: 'Some Text'}
-      validate.messages([message], linter)
-      expect(message.name).toBe('Wow')
-
-      message = {type: 'Error', text: 'Some Text', name: 'Ha!'}
-      validate.messages([message], linter)
-      expect(message.name).toBe('Ha!')


travis debug

travis debug

--- spec/vim-mode-spec.coffee
+++ spec/vim-mode-spec.coffee
@@ -60,4 +60,5 @@

       expect(vimCommands().length).toBeGreaterThan(0)
       atom.packages.deactivatePackage(packageName)
+      console.log vimCommands()
       expect(vimCommands().length).toBe(0)


Updated main file to use new config schema instead of old way of defining config

--- lib/format.coffee
+++ lib/format.coffee
@@ -1,24 +1,14 @@
-FileTypeNotSupportedView = require './not-supported-view'
-Observer = require './observer'
-
+###
+ Package dependencies
+###
 jsbeautify = (require 'js-beautify').js_beautify

+packgeConfig = require './config'
+Observer = require './observer'
+FileTypeNotSupportedView = require './not-supported-view'
+
 module.exports =
-  configDefaults:
-    format_on_save: true,
-    indent_with_tabs: false,
-    max_preserve_newlines: 4,
-    preserve_newlines: true,
-    space_in_paren: false,
-    jslint_happy: false,
-    brace_style: "collapse",
-    keep_array_indentation: false,
-    keep_function_indentation: false,
-    space_before_conditional: true,
-    eval_code: false,
-    unescape_strings: false,
-    break_chained_methods: false,
-    e4x: false
+  config: packgeConfig

   activate: (state) ->
     atom.workspaceView.command 'jsformat:format', => @format(state)
@@ -34,7 +24,7 @@

   format: (state) ->
     editor = atom.workspace.activePaneItem
-
+    debugger
     if !editor
       return


removed alert

removed alert

--- lib/assets/javascripts/block.coffee
+++ lib/assets/javascripts/block.coffee
@@ -1,3 +1,3 @@
 class window.Block
 	constructor: (name, options) ->
-		alert(name)+		#alert(name)


Removed duplication

Removed duplication

--- lib/installed-packages-panel.coffee
+++ lib/installed-packages-panel.coffee
@@ -184,36 +184,45 @@
   updateSectionCounts: ->
     filterText = @filterEditor.getModel().getText()
     if filterText is ''
-      @totalPackages.text(@packages.user.length + @packages.core.length + @packages.dev.length)
-
-      @communityCount.text @packages.user.length
-      if @packages.user.length > 0
-        @communityPackagesHeader.addClass("has-items")
-
-      @coreCount.text @packages.core.length
-      if @packages.core.length > 0
-        @corePackagesHeader.addClass("has-items")
-
-      @devCount.text @packages.dev.length
-      if @packages.dev.length > 0
-        @devPackagesHeader.addClass("has-items")
-
-      @deprecatedCount.text @packages.deprecated.length
-      if @packages.deprecated.length > 0
-        @deprecatedPackagesHeader.addClass("has-items")
+      @updateUnfilteredSectionCounts()
     else
-      community = @communityPackages.find('.package-card:not(.hidden)').length
-      @communityCount.text "#{community}/#{@packages.user.length}"
-      dev = @devPackages.find('.package-card:not(.hidden)').length
-      @devCount.text "#{dev}/#{@packages.dev.length}"
-      core = @corePackages.find('.package-card:not(.hidden)').length
-      @coreCount.text "#{core}/#{@packages.core.length}"
-      deprecated = @deprecatedPackages.find('.package-card:not(.hidden)').length
-      @deprecatedCount.text "#{deprecated}/#{@packages.deprecated.length}"
-
-      shownPackages = dev + core + community
-      totalPackages = @packages.user.length + @packages.core.length + @packages.dev.length
-      @totalPackages.text "#{shownPackages}/#{totalPackages}"
+      @updateFilteredSectionCounts()
+
+  updateUnfilteredSectionCounts: ->
+    @updateSectionCount @deprecatedPackagesHeader, @deprecatedCount, @packages.deprecated.length
+    @updateSectionCount @communityPackagesHeader, @communityCount, @packages.user.length
+    @updateSectionCount @corePackagesHeader, @coreCount, @packages.core.length
+    @updateSectionCount @devPackagesHeader, @devCount, @packages.dev.length
+
+    @totalPackages.text(@packages.user.length + @packages.core.length + @packages.dev.length)
+
+  updateFilteredSectionCounts: ->
+    deprecated = @notHiddenCardsLength @deprecatedPackages
+    @updateSectionCount @deprecatedPackagesHeader, @deprecatedCount, deprecated, @packages.deprecated.length
+
+    community = @notHiddenCardsLength @communityPackages
+    @updateSectionCount @communityPackagesHeader, @communityCount, community, @packages.user.length
+
+    core = @notHiddenCardsLength @corePackages
+    @updateSectionCount @corePackagesHeader, @coreCount, core, @packages.core.length
+
+    dev = @notHiddenCardsLength @devPackages
+    @updateSectionCount @devPackagesHeader, @devCount, dev, @packages.dev.length
+
+    shownPackages = dev + core + community
+    totalPackages = @packages.user.length + @packages.core.length + @packages.dev.length
+    @totalPackages.text "#{shownPackages}/#{totalPackages}"
+
+  updateSectionCount: (headerElement, countElement, packageCount, totalCount) ->
+    if totalCount is undefined
+      countElement.text packageCount
+    else
+      countElement.text "#{packageCount}/#{totalCount}"
+
+    headerElement.addClass("has-items") if packageCount > 0
+
+  notHiddenCardsLength: (sectionElement) ->
+    sectionElement.find('.package-card:not(.hidden)').length

   matchPackages: ->
     filterText = @filterEditor.getModel().getText()


JCredential: Add meta field for created/modified date information

--- workers/social/lib/social/models/computeproviders/credential.coffee
+++ workers/social/lib/social/models/computeproviders/credential.coffee
@@ -77,6 +77,8 @@
         type          : ObjectId
         required      : yes

+      meta            : require 'bongo/bundles/meta'
+
     relationships     :

       data            :


Rawmetas is now indexed by site and then name within site.

--- lib/loader.coffee
+++ lib/loader.coffee
@@ -66,10 +66,11 @@
       r

     loadTree= (rootdir,superMeta,supersites) ->
+      rawmetas[rootdir]= {}
       load= (name,superMeta)->
         fullname= path.join(rootdir,name)
         raw= require(fullname)
-        rawmetas[name.replace(stripDotMeta,'$1')]= raw
+        rawmetas[rootdir][name.replace(stripDotMeta,'$1')]= raw
         extend(superMeta, raw, fullname)

       modules= []
@@ -82,32 +83,34 @@
         for filename in fs.readdirSync(fulldirname)
           unless skipThisFileSignature.test(filename)
             fullname= path.join(fulldirname,filename)
+            partialname= path.join(dirname,filename)
             stat = fs.lstatSync(fullname)
             if stat.isDirectory()
               unless visited[stat.ino]  # do not follow circular symbolic link
                 newvisited= {}
                 newvisited[ino] = true for ino, val of visited
                 newvisited[stat.ino]= true
-                loadDir(path.join(dirname,filename),meta,newvisited)
+                loadDir(partialname,meta,newvisited)
             else
               if moduleSignature.test(filename)
                 if metafileSignature.test(filename)
                   metacache[fullname.replace(stripMetaExtension,'$1')]= load(path.join(dirname,stripExtension(filename)),meta)
                 else
-                  modules.unshift(stripExtension(fullname))
+                  modules.unshift(stripExtension(partialname))
         return meta
       visited= {}
       visited[fs.lstatSync(rootdir).ino]= true
       metacache[rootdir+'/']= superMeta  # this will be overridden if _default_meta found
       meta= loadDir('',superMeta,visited)
       for modname in modules
-        m= require(modname)
+        fullmodname= path.join(rootdir,modname)
+        m= require(fullmodname)
         if m?.meta
-          rawmetas[modname]= m.meta
-          itsMeta= meta_lookup(modname)
-          metacache[modname]= extend(itsMeta,m.meta,modname)
+          rawmetas[rootdir][modname]= m.meta
+          itsMeta= meta_lookup(fullmodname)
+          metacache[fullmodname]= extend(itsMeta,m.meta,fullmodname)
         if sitesModuleSignature.test(modname)
-          siteroot= path.dirname(modname)
+          siteroot= path.dirname(fullmodname)
           siteLookupRoot ?= siteroot
           sites[siteroot]= m
           (xsupersites= supersites.slice(0)).push(siteroot)


Properly serialize the view

Properly serialize the view

Fix #14

--- lib/keybinding-resolver-view.coffee
+++ lib/keybinding-resolver-view.coffee
@@ -16,7 +16,7 @@
     @on 'click', '.source', (event) -> atom.workspace.open(event.target.innerText)

   serialize: ->
-    attached: @hasParent()
+    attached: @panel?.isVisible()

   destroy: ->
     @detach()


performing js driver handshake in one write to avoid EPIPE

--- drivers/javascript/net.coffee
+++ drivers/javascript/net.coffee
@@ -357,17 +357,18 @@

         @rawSocket.once 'connect', =>
             # Initialize connection with magic number to validate version
-            buf = new Buffer(4)
-            buf.writeUInt32LE(protoVersion, 0)
-            @rawSocket.write buf
-
-            buf = new Buffer(@authKey, 'ascii')
-            @write buf
+            version = new Buffer(4)
+            version.writeUInt32LE(protoVersion, 0)
+
+            auth_buffer = new Buffer(@authKey, 'ascii')
+            auth_length = new Buffer(4)
+            auth_length.writeUInt32LE(auth_buffer.length, 0)

             # Send the protocol type that we will be using to communicate with the server
-            buf = new Buffer(4)
-            buf.writeUInt32LE(protoProtocol, 0)
-            @rawSocket.write buf
+            protocol = new Buffer(4)
+            protocol.writeUInt32LE(protoProtocol, 0)
+
+            @rawSocket.write Buffer.concat([version, auth_length, auth_buffer, protocol])

             # Now we have to wait for a response from the server
             # acknowledging the new connection


add auto resizing

add auto resizing

--- app/assets/javascripts/active_admin/lib/modal_dialog.js.coffee
+++ app/assets/javascripts/active_admin/lib/modal_dialog.js.coffee
@@ -56,6 +56,8 @@
     open: (event, ui) ->
       $('body').trigger 'modal_dialog:after_open', [form]
     dialogClass: 'active_admin_dialog'
+    resizable: true
+    width:'auto'
     buttons:
       OK: ->
         callback $(@).serializeObject()


Remove unused file

Remove unused file


Fixed validity check for radio buttons on data requests

--- app/assets/javascripts/components/expandable_text_input.coffee
+++ app/assets/javascripts/components/expandable_text_input.coffee
@@ -1,7 +1,25 @@
+@isDataRequestInputValid = (element) ->
+  (
+    $(element).hasClass("signature-pad-body") &&
+    window.$signaturePad? &&
+    !window.$signaturePad.isEmpty()
+  ) ||
+  (
+    $(element).is(":radio") &&
+    $("[name=#{element.attr("name")}]:checked").length > 0
+  ) ||
+  (
+    $(element).is(":checkbox") &&
+    $(element).is(":checked")
+  ) ||
+  !$(element).is(":checkbox") &&
+  !$(element).is(":radio") &&
+  $(element).val().length > 0
+
 @setInputSize = (element) ->
   $(element).removeClass("input-success input-highlight")
   $widthTest = getWidthTestElement()
-  if ($(element).hasClass("signature-pad-body") && window.$signaturePad? && !window.$signaturePad.isEmpty()) || ($(element).is(":checkbox") && $(element).is(":checked")) || !$(element).is(":checkbox") && $(element).val().length > 0
+  if isDataRequestInputValid(element)
     $widthTest.text($(element).val())
     $(element).addClass("input-success")
   else
@@ -16,11 +34,11 @@
 @resetHelpText = (element) ->
   $help_element = $("##{$(element).data("help-element")}_help_text")
   $help_element.removeClass("agreement-helper-success agreement-helper-highlight")
-  if ($(element).hasClass("signature-pad-body") && window.$signaturePad? && !window.$signaturePad.isEmpty()) || ($(element).is(":checkbox") && $(element).is(":checked")) || !$(element).is(":checkbox") && $(element).val().length > 0
+  if isDataRequestInputValid(element)
     $help_element.html(' ' + $(element).data("help-text") + ' ')
     $help_element.addClass("agreement-helper-success")
   else
-    $help_element.html(' ' + $(element).data("help-text")) #  + ' '
+    $help_element.html(' ' + $(element).data("help-text"))
     $help_element.addClass("agreement-helper-highlight")
   offset = $("#top-menu").height()
   offset = offset - ($(element).height() / 2) if $(element).hasClass("signature-pad-body")


Add popstate event handler to cover the case where the browser history state is missing a turbolinks object due to Universal Viewer's manipulation of the browser history outside of turbolinks.  This fix is based on https://github.com/turbolinks/turbolinks/issues/219#issuecomment-275838923.  I'm seeing this handler getting registered after the turbolinks handler but I don't think order matters since the two are operating on mutually exclusive cases.  The turbolinks handler does nothing if the turbolinks object isn't in the event state (https://github.com/turbolinks/turbolinks/blob/master/src/turbolinks/history.coffee#L26-L31).

--- app/assets/javascripts/hyrax/monkey_patch_turbolinks.js.coffee
+++ app/assets/javascripts/hyrax/monkey_patch_turbolinks.js.coffee
@@ -9,3 +9,15 @@
       else
         @failed = true
         @delegate.requestFailedWithStatusCode(@xhr.status, @xhr.responseText)
+
+  # Fixes a back/forward navigation problem with UV and turbolinks
+  # See https://github.com/samvera/hyrax/issues/2964
+  # This is based on https://github.com/turbolinks/turbolinks/issues/219#issuecomment-275838923
+  $(window).on 'popstate', (event) =>
+    @turbolinks_location = Turbolinks.Location.wrap(window.location)
+    return if Turbolinks.controller.location.requestURL == @turbolinks_location.requestURL
+    return if event.state?.turbolinks
+    if @window_turbolinks = window.history.state?.turbolinks
+      Turbolinks.controller.historyPoppedToLocationWithRestorationIdentifier(@turbolinks_location, @window_turbolinks.restorationIdentifier)
+    else
+      Turbolinks.controller.historyPoppedToLocationWithRestorationIdentifier(@turbolinks_location, Turbolinks.uuid())


Fix prop type

Fix prop type

--- app/assets/javascripts/rglossa/react/components/centre/search_inputs/cwb_multiword_term.jsx.coffee
+++ app/assets/javascripts/rglossa/react/components/centre/search_inputs/cwb_multiword_term.jsx.coffee
@@ -9,7 +9,7 @@
     queryHasSingleTerm: React.PropTypes.bool.isRequired
     isFirst: React.PropTypes.bool.isRequired
     isLast: React.PropTypes.bool.isRequired
-    tags: React.PropTypes.array.isRequired
+    tags: React.PropTypes.object.isRequired
     handleTermChanged: React.PropTypes.func.isRequired
     handleAddTerm: React.PropTypes.func.isRequired
     handleRemoveTerm: React.PropTypes.func.isRequired


Modified so an action supplier is always in the set

--- utils/creator.coffee
+++ utils/creator.coffee
@@ -26,6 +26,7 @@
          setTypesOnFilter,
          fillKingdom,
          alchemySetCorrection,
+         actionSupplierCorrection
       ], callback

 ###
@@ -74,7 +75,6 @@
       else if costMap
          kingdom.filter.$or.push(costMap[type])

-   console.log '$or', kingdom.filter.$or
    callback(null, kingdom)

 fillKingdom = (kingdom, callback) ->
@@ -158,6 +158,24 @@
       alchemyCards.push(card) for card in replaceableCards
       alchemyCards.push(card) for card in nonReplaceableCards
       kingdom.cards = alchemyCards
+      callback(null, kingdom)
+
+actionSupplierCorrection = (kingdom, callback) ->
+
+   for card in kingdom.cards
+      if card.isActionSupplier
+         console.log "Has Action Supplier"
+         return callback(null, kingdom)
+   console.log "Needs Action Supplier"
+   filter =
+      set: kingdom.filter.set
+      _id: { $nin: (card._id for card in kingdom.cards) }
+      isActionSupplier: true
+
+   getCards 1, filter, (err, cards) ->
+      return callback(err) if err
+      evictIndex = rand.getRandomInt(0,10)
+      kingdom.cards[evictIndex] = cards[0]
       callback(null, kingdom)

 ###


redirect after clicking register button

redirect after clicking register button

--- apps/feature/client/index.coffee
+++ apps/feature/client/index.coffee
@@ -68,8 +68,9 @@
         @initializeAuction @model

   initializeAuction: (sale) ->
-    sale = new Sale(id: @model.get('id')).fetch
+    new Sale(id: @model.get('id')).fetch
       success: (sale) =>
+        @sale = sale
         if sale.get('is_auction')
           if @currentUser
             @currentUser.checkRegisteredForAuction
@@ -149,7 +150,7 @@

   triggerLoginPopup: =>
     unless @currentUser
-      mediator.trigger 'open:auth', { mode: 'register', copy: 'Sign up to bid on artworks' }
+      mediator.trigger 'open:auth', { mode: 'register', copy: 'Sign up to bid on artworks', redirectTo: @sale.registerUrl() }
       false

 module.exports.init = ->


add responses

add responses

--- scripts/ask.coffee
+++ scripts/ask.coffee
@@ -1,6 +1,5 @@
 module.exports = (robot) ->
     robot.respond /ask/i, (res) ->
-        console.log res
         responses = [
             "Yes, definitely.",
             "No, definitely not.",
@@ -21,9 +20,12 @@
             "Signs point to yes.",
             "Signs point to no.",
             "I'm sorry, Dave, I cannot answer that question.",
-            "Aw hell nah."
+            "Aw hell nah.",
+            "No idea, but personally I blame Canada.",
+            ""
         ]
         random = responses[Math.floor(Math.random() * responses.length)]
+        res.send random

-
-        res.send random
+    robot.respond /ask are you racist/i, (res) ->
+        res.send "Most definitely not!"


Might as well get ahead of Nomikos' Kenny 🐔

--- scripts/ayp.coffee
+++ scripts/ayp.coffee
@@ -141,6 +141,10 @@
   # I'm not kidding. Whole. fucking. channel.
   if /shadypkg/i.test(name)
     name = 'shadypkg'
+
+  # I don't even know how to joke about this anymore
+  if /nomikos/i.test(name)
+    name = 'nomikos'

   return name


Actually load the avatar based on the nick

--- scripts/ayp.coffee
+++ scripts/ayp.coffee
@@ -132,8 +132,9 @@
     return faliled = true

   charPathForNick = (nick) ->
-    # TODO: You know, do what it says
-    path.resolve(AVATAR_BASE, "stan.png")
+    potential = path.resolve(AVATAR_BASE, "#{nick.toLowerCase()}.png")
+    return potential if (try fs.statSync(potential))
+    return path.resolve(AVATAR_BASE, "default.png")

   for nameObj in names
     do (nameObj) ->


Improved handling of uncaught AJAX errors

--- SingularityUI/app/application.coffee
+++ SingularityUI/app/application.coffee
@@ -99,13 +99,21 @@
             url = settings.url.replace(config.appRoot, '')

             if jqxhr.status is 502
-                Messenger().post "
A request failed because Singularity is deploying. Things should resolve in a few seconds so just hang tight...
"
+                Messenger().info
+                    message:   "Singularity is deploying, your requests cannot be handled. Things should resolve in a few seconds so just hang tight!"
+                    hideAfter: 10
             else if jqxhr.statusText is 'timeout'
-                Messenger().post "
A #{ jqxhr.statusText } error occurred while accessing:

#{ url }
"
+                Messenger().error
+                    message:   "
A #{ jqxhr.statusText } error occurred while accessing:

#{ url }
"
+                    hideAFter: 20
             else
+                serverMessage = jqxhr.responseJSON.message or jqxhr.responseText
+                Messenger().error
+                    message:   "
An uncaught error occurred with your request. The server said:

#{ serverMessage }

The error has been saved to your JS console.
"
+                    hideAfter: 20
+
                 console.error jqxhr
                 throw new Error "AJAX Error"
-                Messenger().post "
An error occurred when trying to access:

#{ url }

Check JS console for response.
"

     # Usually called by Controllers when they're initialized. Loader is overwritten by views
     showPageLoader: ->


rotation_styleがロードできない不具合を修正

--- app/assets/javascripts/smalruby.js.coffee
+++ app/assets/javascripts/smalruby.js.coffee
@@ -131,7 +131,7 @@
           x: parseInt(xmlChild.getAttribute('x'), 10)
           y: parseInt(xmlChild.getAttribute('y'), 10)
           angle: parseInt(xmlChild.getAttribute('angle'), 10)
-          rotationStyle: xmlChild.getAttribute('rotationStyle') || 'free'
+          rotationStyle: xmlChild.getAttribute('rotation_style') || 'free'
         chars.push(c)
       i++
     Smalruby.Collections.CharacterSet.reset(chars)
@@ -149,7 +149,7 @@
       e.setAttribute('angle', c.get('angle'))
       rotationStyle = c.get('rotationStyle')
       if rotationStyle != 'free'
-        e.setAttribute('rotationStyle', rotationStyle)
+        e.setAttribute('rotation_style', rotationStyle)
       xmlDom.insertBefore(e, blocklyDom)
     Blockly.Xml.domToPrettyText(xmlDom)


"Just a module" only works for .js and .coffee, but not .json.

--- lib/actions/just_a_module.coffee
+++ lib/actions/just_a_module.coffee
@@ -1,9 +1,11 @@
-isModule = require('../utilities').isModule
+hasAnExtension = require('../utilities').hasAnExtension
+
+extensions= ['.js','.coffee']

 # invoke the module at the given path if it is present
 module.exports= justAModuleAction= (pass,req,res,next,malifi,meta) ->
   path = req.malifi.path.full
-  isModule path, (found)->
+  hasAnExtension path, extensions, (found)->
     if found
       require(path)(req,res,next,malifi,meta)
     else


Copywriting.

Copywriting.

--- app/client/js/react/pages/editsong.coffee
+++ app/client/js/react/pages/editsong.coffee
@@ -55,10 +55,12 @@
                 ref: 'lyrics'
                 value: song.lyrics
               p className: 'help-block',
+                editMode && 'Just edit song, no need to save it. '
                 a
                   href: 'http://linkesoft.com/songbook/chordproformat.html'
                   target: '_blank'
                 , EditSong.MSG_HOW_TO_WRITE_LYRICS
+                '.'
             nav {},
               if editMode
                 button
@@ -109,7 +111,7 @@
   @MSG_CREATE_NEW_SONG: goog.getMsg 'Add New Song'
   @MSG_DELETE: goog.getMsg 'Delete'
   @MSG_RESTORE: goog.getMsg 'Restore'
-  @MSG_HOW_TO_WRITE_LYRICS: goog.getMsg 'How to Write Lyrics'
+  @MSG_HOW_TO_WRITE_LYRICS: goog.getMsg 'How to write lyrics'
   @MSG_SONG_ARTIST: goog.getMsg 'Artist (or band)'
   @MSG_SONG_NAME: goog.getMsg 'Song name'
   @MSG_WRITE_LYRICS_HERE: goog.getMsg '[F]Michelle [Bmi7]ma belle...'


Prevent project links issues with anonymous links

--- app/coffee/modules/common/sections.coffee
+++ app/coffee/modules/common/sections.coffee
@@ -45,8 +45,10 @@
         defaultHomePage = "timeline"

         projects = @currentUserService.projects?.get("all")
+        if not projects
+            return defaultHomePage
+
         project = projects.find (p) -> return p.get('slug') == projectSlug
-
         if not project
             return defaultHomePage


EditorSensorViewSpec: events calling correct methods

--- app/coffeescripts/EditorSensorView.coffee
+++ app/coffeescripts/EditorSensorView.coffee
@@ -8,8 +8,10 @@
   URL_DESC += 'For ranges, use this date format:<br/>July 20-21, 2012'

   events : {
-    'blur #name, #description, #type' : 'save'
-    'blur #lat, #lng, #elevation' : 'saveGeo'
+    'blur #sensor_desc, #sensor_type, #sensor_link_type, #sensor_links' : 'save'
+    'blur #sensor_format, #sensor_url' : 'save'
+    'blur #sensor_hour, #sensor_minute, #sensor_second' : 'saveTime'
+    'blur #sensor_lat, #sensor_lng, #sensor_elev' : 'saveGeo'
     'click #display-at-pos' : 'displayAtPos'
   }

@@ -30,8 +32,10 @@
   _setSelectedType: ->
     format = @model.get('data_sources').get('data_source')[0].get('format')
     type = @model.get('type')
+    lType = @model.get('link_type')
     $("#sensor_type > option[value='#{type}']").attr('selected','selected')
     $("#sensor_format > option[value='#{format}']").attr('selected','selected')
+    $("#sensor_link_type > option[value='#{lType}']").attr('selected','selected')

   # set up a hash of values from the model and inserted into the html template
   _getTemplateData: (model) ->
@@ -58,6 +62,16 @@
     id = e.currentTarget.id
     @model.set(id, $("##{id}").val())

+  saveTime: (e) ->
+    p = @model.get('data_sources').get('data_source')[0]
+    dt = {
+      'h': $("#sensor_hour").val()
+      'm': $("#sensor_minute").val()
+      's': $("#sensor_second").val()
+    }
+
+    p?.set('dt', $a.Util.convertToSeconds(dt))
+
   # This is used to save the latitude, longitude and elevation when focus is
   # lost from the element
   saveGeo: (e) ->


add github show issues command.

add github show issues command.

--- scripts/github-op.coffee
+++ scripts/github-op.coffee
@@ -12,6 +12,7 @@
 #   hubot github show repos -- デフォルトの対象リポジトリ一覧表示
 #   hubot github add repo <repo> -- デフォルトの対象リポジトリに <repo> を追加
 #   hubot github show {PR,pull req} [<repo>] -- GitHub の open な pull request 一覧
+#   hubot github show issue[s] -- GitHub の open な issue 一覧
 #
 # Notes:
 #   HUBOT_GITHUB_API allows you to set a custom URL path (for Github enterprise users)
@@ -88,3 +89,28 @@
               summary += "\n\t#{pull.html_url} #{pull.title} - #{pull.user.login}#{mentioned}\n"
           msg.send summary
       cb(repo)
+
+  robot.respond /github\s+show\s+issues?\s*([a-z0-9._/-]+)?$/i, (msg)->
+    repos = msg.match[3]
+    if repos
+      repos = []
+      for r in repo.split(",")
+        repos.push(r)
+    else
+      repos = robot.brain.get("github_default_target_repos")
+      unless repos
+        repos = []
+
+    for repo in repos
+      cb = (repo) ->
+        github.get "#{url_api_base}/repos/#{repo}/issues?state=open", (issues) ->
+          if issues.length == 0
+            summary = "#{repo}: issue はありません :+1:"
+          else
+            summary = "#{repo}: issue 一覧\n"
+            for issue in issues
+              continue if issue.html_url.match(/\/pulls?\//)
+              # cannot use label for a link see: https://github.com/slackhq/hubot-slack/issues/114
+              summary += "\n\t#{issue.html_url} #{issue.title} - #{issue.user.login}\n"
+          msg.send summary
+      cb(repo)


add comment

add comment

--- app/elements/aozora-bgm/aozora-bgm.coffee
+++ app/elements/aozora-bgm/aozora-bgm.coffee
@@ -61,7 +61,7 @@
     @async =>
       @toggleAttribute 'hidden', true
       @showed = false
-    , 475
+    , 475 # TODO HACK should use a callback event instead of async

   _musicNameChanged: ->
     @music = @app.resources.getResource 'music', @musicName


deleted. newscript

deleted. newscript

--- scripts/newscript.coffee
+++ scripts/newscript.coffee
@@ -1,10 +1,2 @@
-# Description:
-#   ミサワ　ネタ
-#
-# Commands:
-#   hubot まだある - get ミサワ ネタ
+:q

-module.exports = (robot) ->
-  robot.respond /まだある$/, (msg) ->
-    msg.send "http://livedoor.4.blogimg.jp/jigokuno_misawa/imgs/7/3/73de70ed.gif"
-


Fixed ref to templates

Fixed ref to templates

--- scripts/reportTab.coffee
+++ scripts/reportTab.coffee
@@ -1,7 +1,7 @@
 enableLayerTogglers = require './enableLayerTogglers.coffee'
 round = require('./utils.coffee').round
 ReportResults = require './reportResults.coffee'
-t = require('api/templates')
+t = require('../templates/templates.js')
 templates =
   reportLoading: t['node_modules/seasketch-reporting-api/reportLoading']
 JobItem = require './jobItem.coffee'


Added missing value for filters

Added missing value for filters

--- lib/hcommands/hGetThreads.coffee
+++ lib/hcommands/hGetThreads.coffee
@@ -132,7 +132,7 @@
     ).stream()
     convidDone = false
     stream.on "data", (hMessage) ->
-      if hFilter.checkFilterValidity(hMessage, filter).result
+      if hFilter.checkFilterValidity(hMessage, filter, {actor:context.actor}).result
         if filteredConvids.length is 0
           filteredConvids.push hMessage.convid
         else


Ensure object expects

Ensure object expects

Closes #179

--- lib/highlighted-area-view.coffee
+++ lib/highlighted-area-view.coffee
@@ -164,8 +164,10 @@

   highlightSelectionInEditor: (editor, regexSearch, regexFlags, originalEditor) ->
     return unless editor?
-    markerLayer = @editorToMarkerLayerMap[editor.id]['visibleMarkerLayer']
-    markerLayerForHiddenMarkers = @editorToMarkerLayerMap[editor.id]['hiddenMarkerLayer']
+    markerLayers =  @editorToMarkerLayerMap[editor.id]
+    return unless markerLayers?
+    markerLayer = markerLayers['visibleMarkerLayer']
+    markerLayerForHiddenMarkers = markerLayers['hiddenMarkerLayer']

     editor.scan new RegExp(regexSearch, regexFlags),
       (result) =>


Make repl input soft-wrapped

Make repl input soft-wrapped

Closes atom-haskell/ide-haskell#173

--- lib/ide-haskell-repl-view.coffee
+++ lib/ide-haskell-repl-view.coffee
@@ -42,6 +42,7 @@
     atom.views.views.set @editor, @editorElement
     atom.textEditors.add @editor
     @editor.setLineNumberGutterVisible(false)
+    @editor.setSoftWrapped(true)
     @editor.setGrammar \
       atom.grammars.grammarForScopeName 'source.haskell'


sort array in tests for travisci

sort array in tests for travisci

--- test/cases/support/server/fileTest.coffee
+++ test/cases/support/server/fileTest.coffee
@@ -67,7 +67,7 @@
     assert.deepEqual Tower.entriesSync(dir).sort(), expected

     Tower.entries dir, (error, entries) =>
-      assert.deepEqual entries, expected
+      assert.deepEqual entries.sort(), expected
       done()

   test 'absolutePath', ->


Stop options page link from blurring the help dialog iframe

--- pages/options.coffee
+++ pages/options.coffee
@@ -232,8 +232,6 @@

   activateHelpDialog = ->
     HelpDialog.show chrome.extension.getBackgroundPage().helpDialogHtml(true, true, "Command Listing"), frameId
-    # Prevent the "show help" link from retaining the focus when clicked.
-    document.activeElement.blur()

   saveOptions = ->
     Option.saveOptions()