Tutorial text is translated into spans

Tutorial text is translated into spans

--- app/lib/tutorial-steps.coffee
+++ app/lib/tutorial-steps.coffee
@@ -13,7 +13,7 @@

 tutorialSteps =
   first:
-    content: translate 'div', 'tutorial.first.content'
+    content: translate 'span', 'tutorial.first.content'
     next: ->
       if @classifier.surface.tool::name is 'bubble'
         'markBubble'
@@ -21,16 +21,16 @@
         'selectBubbleTool'

   selectBubbleTool:
-    content: translate 'div', 'tutorial.selectBubbleTool.content'
-    instruction: translate 'div', 'tutorial.selectBubbleTool.instruction'
+    content: translate 'span', 'tutorial.selectBubbleTool.content'
+    instruction: translate 'span', 'tutorial.selectBubbleTool.instruction'
     attachment: [0.5, 1, 'input[name="tool"][value="bubble"] + *', 0.5, 0]
     arrow: 'bottom'
     actionable: 'input[name="tool"][value="bubble"] + *'
     next: 'change input[name="tool"][value="bubble"]': 'markBubble'

   markBubble:
-    content: translate 'div', 'tutorial.markBubble.content'
-    instruction: translate 'div', 'tutorial.markBubble.instruction'
+    content: translate 'span', 'tutorial.markBubble.content'
+    instruction: translate 'span', 'tutorial.markBubble.instruction'
     attachment: [0, 0.5, '.marking-surface', 0.45, 0.75]
     arrow: 'left'

@@ -51,8 +51,8 @@
       'touchend .marking-surface': 'adjustBubbleMarking'

   adjustBubbleMarking:
-    content: translate 'div', 'tutorial.adjustBubbleMarking.content'
-    instruction: translate 'div', 'tutorial.adjustBubbleMarking.instruction'
+    content: translate 'span', 'tutorial.adjustBubbleMarking.content'
+    instruction: translate 'span', 'tutorial.adjustBubbleMarking.instruction'
     attachment: [0.33, 0.67, '.marking-surface', 0.25, 0.25]
     arrow: 'bottom'

@@ -64,8 +64,8 @@
       'touchend .marking-surface': 'selectClusterTool'

   selectClusterTool:
-    content: translate 'div', 'tutorial.selectClusterTool.content'
-    instruction: translate 'div', 'tutorial.selectClusterTool.instruction'
+    content: translate 'span', 'tutorial.selectClusterTool.content'
+    instruction: translate 'span', 'tutorial.selectClusterTool.instruction'
     attachment: [0.5, 1, 'input[name="tool"][value="cluster"] + *', 0.5, 0]
     arrow: 'bottom'
     actionable: 'input[name="tool"][value="cluster"] + *'
@@ -73,8 +73,8 @@
     next: 'change input[name="tool"][value="cluster"]': 'markCluster'

   markCluster:
-    content: translate 'div', 'tutorial.markCluster.content'
-    instruction: translate 'div', 'tutorial.markCluster.instruction'
+    content: translate 'span', 'tutorial.markCluster.content'
+    instruction: translate 'span', 'tutorial.markCluster.instruction'
     attachment: [1, 0.5, '.marking-surface', 0.6, 0.3]
     arrow: 'right'

@@ -97,8 +97,8 @@
       'touchend .marking-surface': 'selectEgoTool'

   selectEgoTool:
-    content: translate 'div', 'tutorial.selectEgoTool.content'
-    instruction: translate 'div', 'tutorial.selectEgoTool.instruction'
+    content: translate 'span', 'tutorial.selectEgoTool.content'
+    instruction: translate 'span', 'tutorial.selectEgoTool.instruction'
     attachment: [0.5, 1, 'input[name="tool"][value="ego"] + *', 0.5, 0]
     arrow: 'bottom'
     actionable: 'input[name="tool"][value="ego"] + *'
@@ -106,8 +106,8 @@
     next: 'change input[name="tool"][value="ego"]': 'markEgo'

   markEgo:
-    content: translate 'div', 'tutorial.markEgo.content'
-    instruction: translate 'div', 'tutorial.markEgo.instruction'
+    content: translate 'span', 'tutorial.markEgo.content'
+    instruction: translate 'span', 'tutorial.markEgo.instruction'
     attachment: [0.5, 0, '.marking-surface', (275 / 800), (75 / 400)]
     arrow: 'top'

@@ -130,24 +130,24 @@
       'touchend .marking-surface': 'callOutTalk'

   callOutTalk:
-    content: translate 'div', 'tutorial.callOutTalk.content'
+    content: translate 'span', 'tutorial.callOutTalk.content'
     attachment: [0, 0.5, 'a.discuss', 1, 0.5]
     arrow: 'left'
     next: 'callOutFavorite'

   callOutFavorite:
-    content: translate 'div', 'tutorial.callOutFavorite.content'
+    content: translate 'span', 'tutorial.callOutFavorite.content'
     attachment: [0, 0.5, 'button[name="favorite"]', 1, 0.5]
     arrow: 'left'
     next: 'callOutHelp'

   callOutHelp:
-    content: translate 'div', 'tutorial.callOutHelp.content'
+    content: translate 'span', 'tutorial.callOutHelp.content'
     attachment: [0, 0.5, 'button[name="help"]', 1, 0.5]
     arrow: 'left'
     next: 'theEnd'

   theEnd:
-    content: translate 'div', 'tutorial.theEnd.content'
+    content: translate 'span', 'tutorial.theEnd.content'

 module.exports = tutorialSteps


Verbose checking if external data is there.

--- app/models/data_source.coffee
+++ app/models/data_source.coffee
@@ -50,7 +50,12 @@
     (@get('source_type') is 'internal')

   isReady: =>
-    (@isInternal() and (not _.isUndefined(@get('source')))) or (@isExternal() and (not (@data?.isEmpty())))
+    if @data? and not @data.isEmpty()
+      dataReady = true
+    else
+      dataReady = false
+
+    (@isInternal() and (not _.isUndefined(@get('source')))) or (@isExternal() and dataReady)

   sourceName: =>
     if @isExternal()


In Safari, limit iterations of the command-parsing loop.

--- services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/SuggestionManager.coffee
+++ services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/SuggestionManager.coffee
@@ -1,11 +1,30 @@
 define [], () ->
+
+	browserIsSafari = () ->
+		userAgent = navigator.userAgent
+		(
+			userAgent.match(/.*Safari\/.*/) &&
+			!userAgent.match(/.*Chrome\/.*/) &&
+			!userAgent.match(/.*Chromium\/.*/)
+		)
+
+
 	class Parser
 		constructor: (@doc) ->

 		parse: () ->
+			limit = null
+			if browserIsSafari()
+				limit = 100
+
 			commands = []
 			seen = {}
+			iterations = 0
 			while command = @nextCommand()
+				iterations += 1
+				if limit && iterations > limit
+					return commands
+
 				docState = @doc

 				optionalArgs = 0


ui bug: closing last project now properly shows the project page (broken last summer by project reordering).

--- salvus/page/top_navbar.coffee
+++ salvus/page/top_navbar.coffee
@@ -145,6 +145,7 @@
         @pages[id]?.button.addClass("active")

     switch_to_next_available_page: (id) ->
+        #console.log('switch_to_next_available_page',id)
         # Switch to the next page after the page
         # with given id, unless there is no such page,
         # in which case, switch to the previous page.
@@ -161,8 +162,12 @@

     switch_to_prev_available_page: (id) ->
         # There is always a previous page, because of the project page.
+        #console.log("switch_to_prev_available_page")
         p = @pages[id]
         prev_button = p.button.prev()
+        if prev_button.length == 0
+            @switch_to_page('projects')
+            return
         prev = prev_button.find("a")
         id = prev.data('id')
         if id?


rm unuserd file

rm unuserd file

--- app/views/categories/1.coffee
+++ app/views/categories/1.coffee
@@ -1,12 +0,0 @@
-$ ->
-  $(document).on 'change', '#countries_select', (evt) ->
-    $.ajax 'update_cities',
-      type: 'GET'
-      dataType: 'script'
-      data: {
-        country_id: $("#countries_select option:selected").val()
-      }
-      error: (jqXHR, textStatus, errorThrown) ->
-        console.log("AJAX Error: #{textStatus}")
-      success: (data, textStatus, jqXHR) ->
-        console.log("Dynamic country select OK!")


Bugfix: Does not show has more button

Bugfix: Does not show has more button

The usersInRole counts is sometimes that exceed the limit.

--- packages/rocketchat-authorization/client/views/permissionsRole.coffee
+++ packages/rocketchat-authorization/client/views/permissionsRole.coffee
@@ -25,7 +25,7 @@
 		return Template.instance().usersInRole.get() && Template.instance().usersInRole.get().count() > 0

 	hasMore: ->
-		return Template.instance().limit?.get() is Template.instance().usersInRole.get().count()
+		return Template.instance().limit?.get() <= Template.instance().usersInRole.get().count()

 	isLoading: ->
 		return 'btn-loading' unless Template.instance().ready?.get()


Specs for overlay sizing when description.

--- spec/autocomplete-manager-integration-spec.coffee
+++ spec/autocomplete-manager-integration-spec.coffee
@@ -209,14 +209,36 @@
       beforeEach ->
         atom.config.set('autocomplete-plus.maxVisibleSuggestions', 2)

-      it "only shows the maxVisibleSuggestions in the suggestion popup", ->
-        triggerAutocompletion(editor, true, 'a')
-
-        runs ->
-          expect(editorView.querySelector('.autocomplete-plus')).toExist()
-          itemHeight = parseInt(getComputedStyle(editorView.querySelector('.autocomplete-plus li')).height)
-          expect(editorView.querySelectorAll('.autocomplete-plus li')).toHaveLength 4
-          expect(editorView.querySelector('.autocomplete-plus autocomplete-suggestion-list .suggestion-list-scroller').style['max-height']).toBe("#{2 * itemHeight}px")
+      describe "when a suggestion description is not specified", ->
+        it "only shows the maxVisibleSuggestions in the suggestion popup", ->
+          triggerAutocompletion(editor, true, 'a')
+
+          runs ->
+            expect(editorView.querySelector('.autocomplete-plus')).toExist()
+            itemHeight = parseInt(getComputedStyle(editorView.querySelector('.autocomplete-plus li')).height)
+            expect(editorView.querySelectorAll('.autocomplete-plus li')).toHaveLength 4
+
+            suggestionList = editorView.querySelector('.autocomplete-plus autocomplete-suggestion-list')
+            expect(suggestionList.offsetHeight).toBe(2 * itemHeight)
+            expect(suggestionList.querySelector('.suggestion-list-scroller').style['max-height']).toBe("#{2 * itemHeight}px")
+
+      describe "when a suggestion description is specified", ->
+        beforeEach ->
+          spyOn(provider, 'getSuggestions').andCallFake ->
+            list = ['ab', 'abc', 'abcd', 'abcde']
+            ({text, description: "#{text} yeah ok"} for text in list)
+
+        it "shows the maxVisibleSuggestions in the suggestion popup, but with extra height for the description", ->
+          triggerAutocompletion(editor, true, 'a')
+
+          runs ->
+            expect(editorView.querySelector('.autocomplete-plus')).toExist()
+            itemHeight = parseInt(getComputedStyle(editorView.querySelector('.autocomplete-plus li')).height)
+            expect(editorView.querySelectorAll('.autocomplete-plus li')).toHaveLength 4
+
+            suggestionList = editorView.querySelector('.autocomplete-plus autocomplete-suggestion-list')
+            expect(suggestionList.offsetHeight).toBe(3 * itemHeight)
+            expect(suggestionList.querySelector('.suggestion-list-scroller').style['max-height']).toBe("#{2 * itemHeight}px")

     describe "when match.snippet is used", ->
       beforeEach ->


Add ReactEditorView::lineElementForScreenRow shim

--- src/react-editor-view.coffee
+++ src/react-editor-view.coffee
@@ -239,3 +239,6 @@
       @component.setProps({placeholderText})
     else
       @props.placeholderText = placeholderText
+
+  lineElementForScreenRow: (screenRow) ->
+    $(@component.lineNodeForScreenRow(screenRow))


New classifier configuration

New classifier configuration

--- example-project/app/main.coffee
+++ example-project/app/main.coffee
@@ -24,44 +24,37 @@
     {name: 'Brian Carstensen'}
   ]

-#   classifier: new IdentificationClassifier
-#     options: [
-#       {value: 'wolf', label: 'Wolf', image: '//placehold.it/100.png'}
-#       {value: 'coyote', label: 'Coyote', image: '//placehold.it/100.png'}
-#       {value: 'cat', label: 'Cat', image: '//placehold.it/100.png'}
-#       {value: 'squirrel', label: 'Squirrel', image: '//placehold.it/100.png'}
-#     ]
+   classification: {
+    ###
+      descisionName: {
+        query: 'Mark the creatures in this image.'
+        choices: [
+          {
+            type: 'answer' # This is the default type.
+            value: 'nothing'
+            label: 'Nothing to mark'
+            next: '' # Answer-specific "next" value
+          }

-#   classifier2: new MarkingClassifier
-#     options: [
-#       {value: 'wolf', label: 'Wolf', image: '//placehold.it/100.png', tool: 'point'}
-#       {value: 'coyote', label: 'Coyote', image: '//placehold.it/100.png', tool: 'circle'}
-#       {value: 'cat', label: 'Cat', image: '//placehold.it/100.png', tool: 'ellipse'}
-#       {value: 'squirrel', label: 'Squirrel', image: '//placehold.it/100.png', tool: 'rect'}
-#     ]
+          {
+            type: 'point'
+            value: 'deer'
+            label: 'Deer'
+            image: './images/animals/deer.jpg'
+            # Per-marking details, rendered in tool controls:
+            details: [
+              {type: 'checkbox', value: 'eating', label: 'Eating'}
+            ]
+          }
+        ]

-#   classifier3: new DecisionTreeClassifier
-#     questions:
-#       FIRST:
-#         question: 'How many things are there?'
-#         answers: [
-#           {value: 0, label: 'Zero'}
-#           {value: 1, label: 'One', next: 'color'}
-#           {value: 'many', label: 'Several', next: 'averageColor'}
-#         ]
+        # Whole-image details, rendered below choices:
+        details: [
+          {name: 'distorted', label: 'This image is distorted' type: 'checkbox'}
+        ]

-#       color:
-#         question: 'What color is it?'
-#         answers: [
-#           {value: 'red', label: 'Red', image: '//placehold.it/100.png'}
-#           {value: 'green', label: 'Green', image: '//placehold.it/100.png'}
-#           {value: 'blue', label: 'Blue', image: '//placehold.it/100.png'}
-#         ]
-
-#       averageColor:
-#         question: 'What color are they, on average?'
-#         answers: [
-#           {value: 'red', label: 'Red', image: '//placehold.it/100.png'}
-#           {value: 'green', label: 'Green', image: '//placehold.it/100.png'}
-#           {value: 'blue', label: 'Blue', image: '//placehold.it/100.png'}
-#         ]
+        # Default "next" value:
+        next: ''
+      }
+    ###
+   }


Social: add a function for glancing messages into requests.coffee

--- workers/social/lib/social/models/socialapi/requests.coffee
+++ workers/social/lib/social/models/socialapi/requests.coffee
@@ -172,6 +172,13 @@
   url = "/activity/pin/remove"
   post url, data, callback

+glancePinnedPost = (data, callback)->
+  if not data.accountId or not data.messageId or not data.groupName
+    return callback { message: "Request is not valid"}
+
+  url = "/activity/pin/glance"
+  post url, data, callback
+
 followTopic = (data, callback)->
   if not data.accountId or not data.channelId
     return callback { message: "Request is not valid"}
@@ -286,6 +293,7 @@
     , wrapCallback callback

 module.exports = {
+  glancePinnedPost
   updateLastSeenTime
   fetchProfileFeed
   searchTopics


redis-brain requirement notice

redis-brain requirement notice

--- src/scripts/talkative.coffee
+++ src/scripts/talkative.coffee
@@ -2,6 +2,8 @@
 # - say something about <topic> - will say something he knows about the subject
 # - when asked <regexp_of_question> answer <response> - teach your bot to answer to <regexp_of_question> with <response>
 # - forget answers - remove every teached answer from bot brain
+#
+# requires redis-brain

 module.exports = (robot) ->


metadata name was accidentally being deleted on share

--- src/code/providers/document-store-provider.coffee
+++ src/code/providers/document-store-provider.coffee
@@ -225,7 +225,6 @@
           sharedDocumentId: data.id
           shareEditKey: runKey
           _permissions: 0
-        metadata?.name = data.docName
         callback null, data.id
       error: ->
         callback "Unable to save "+metadata.name


Clarify comment for setting the initial json

--- src/coffee/cilantro/models/context/manager.coffee
+++ src/coffee/cilantro/models/context/manager.coffee
@@ -40,7 +40,7 @@
             @upstream = new nodes.BranchNodeModel null,
                 manager: @

-            # Set trees with  and any time a successful sync occurs
+            # Set trees with initial model json and any time a successful sync occurs
             @set(@model.get('json'))

             @model.on 'sync', (model, resp, options) =>


Fix test class naming.

Fix test class naming.

--- src/spec/matcher.spec.coffee
+++ src/spec/matcher.spec.coffee
@@ -3,7 +3,7 @@
 Promise = require 'bluebird'
 {ExtendedLogger} = require 'sphere-node-utils'

-describe 'ApiClient', ->
+describe 'Matcher', ->
   beforeEach ->
     @logger = new ExtendedLogger()
     @matcher = new Matcher(@logger)


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/string_extensions.coffee
+++ src/string_extensions.coffee
@@ -79,7 +79,7 @@
 @methodOf String#

 Assumes the string is something like a file name and returns the
-contents of the string without the string witouh the extension.
+contents of the string without the extension.

 "neat.png".witouthExtension() => "neat"
 ###


string_extensions

--- src/string_extensions.coffee
+++ src/string_extensions.coffee
@@ -81,8 +81,18 @@
 ###*
 Returns a new string that is a more human readable version.

+

+"player_id".humanize()
+# => "Player"
+
+"player_ammo".humanize()
+# => "Player ammo"
+
+

+
 @name humanize
 @methodOf String#
+@returns {String} A new string. Removes _id and _ with "" and capitalizes the word.
 ###
 String::humanize = ->
   this.replace(/_id$/, "").replace(/_/g, " ").capitalize()


tasker invokes init before emiter

tasker invokes init before emiter

--- server/src/Core/Tasker.coffee
+++ server/src/Core/Tasker.coffee
@@ -48,6 +48,7 @@
             @_launchTask instance

     _launchTask: (task) ->
+        task.init?()
         name = task[EXEC_NAME]
         interval = task[EXEC_INTERVAL]
         run = EXEC_RUN


Updated class names for template.

Updated class names for template.

--- src/components/toggle-switch/toggle-switch.coffee
+++ src/components/toggle-switch/toggle-switch.coffee
@@ -255,9 +255,9 @@

 ToggleSwitch.template = "

             							<input type='checkbox' name='NAME' id='TOGGLE_ID' tabindex='-1'>
-
-

-

+
+

+

"


Consistency

Consistency

--- extras/Studio.framer/app.coffee
+++ extras/Studio.framer/app.coffee
@@ -30,19 +30,18 @@
 				lineHeight: "1"
 				textRendering: "optimizeLegibility"

-		mergedProps = _.merge(defaultProps, options)
-		@props = mergedProps
+		@props = _.merge(defaultProps, options)

 # Sheet
 class ShareComponent
 	constructor: (@shareInfo) ->

-		# When fixed is set to true, the sheet won't hide on resize
-		# This is triggered by a manual open / close action
+		# When fixed is set to true, the sheet won't hide on resize.
+		# This is triggered by a manual open / close action.
 		@options =
 			padding: 20
 			width: 250
-			hideWidth: 820
+			minWidth: 820
 			fixed: false

 		@render()
@@ -190,11 +189,11 @@
 					boxShadow: "0 0 0 1px rgba(0,0,0,.1)"
 			@_showPointer(@avatar)

-			# See if author name is available, otherwise fallback to Twitter handle
+			# If author name isn't available, fallback to Twitter handle
 			name = if @shareInfo.author then @shareInfo.author else "@#{@shareInfo.twitter}"
 			showAuthor("#{name}")

-		# If there's no Twitter handle, but there is an author. Just show author.
+		# If there's no twitter handle, show plain author name
 		if @shareInfo.author and !@shareInfo.twitter
 			showAuthor(@shareInfo.author)

@@ -257,7 +256,7 @@
 		@_showPointer(@download)

 	_checkCanvasSize: ->
-		if Canvas.width < @options.hideWidth then @_closeSheet() else @_openSheet()
+		if Canvas.width < @options.minWidth then @_closeSheet() else @_openSheet()

 	_startListening: ->
 		# Show regular cursor on sheet


fixed error the displayed date is fixed and is no longer the current date but the re entry date and the harvest date

--- app/assets/javascripts/backend/interventions_base.js.coffee
+++ app/assets/javascripts/backend/interventions_base.js.coffee
@@ -983,7 +983,7 @@

   displayWarningMessages = (warnings) =>
     for data in warnings
-      date = moment(data.next_possible_date).format('DD-MM-YYYY HH:mm')
+      date = moment(data.date).format('DD-MM-YYYY HH:mm')
       harvestWarning = $(".selector-value[value='#{data.id}']").closest('.controls')

       message = I18n.translate("front-end.intervention.nature.#{data.action}")


Fix String.prototype.replace() global flag deprecation warning

Fixes #120

--- app/assets/javascripts/browse_everything/behavior.js.coffee
+++ app/assets/javascripts/browse_everything/behavior.js.coffee
@@ -26,7 +26,7 @@
   toHiddenFields = (data) ->
     fields = $.param(data)
       .split('&')
-      .map (t) -> t.replace('+',' ','g').split('=',2)
+      .map (t) -> t.replace(/\+/g,' ').split('=',2)
     elements = $(fields).map () ->
       $("<input type='hidden'/>")
         .attr('name',decodeURIComponent(this[0]))


Use crypto module for token generation

Use crypto module for token generation

--- services/web/app/coffee/Features/Project/ProjectTokenGenerator.coffee
+++ services/web/app/coffee/Features/Project/ProjectTokenGenerator.coffee
@@ -1,12 +1,12 @@
+crypto = require 'crypto'
+
 module.exports = ProjectTokenGenerator =

 	readOnlyToken: () ->
 		length = 12
 		tokenAlpha = 'bcdfghjkmnpqrstvwxyz'
 		result = ''
-		for _n in [1..length]
-			i = Math.floor(Math.floor(Math.random() * tokenAlpha.length))
-			result += tokenAlpha[i]
+		crypto.randomBytes(length).map( (a) -> result += tokenAlpha[a % tokenAlpha.length] )
 		return result

 	readAndWriteToken: () ->


Fix <styles> placements

Fix <styles> placements

They should all go inside of `<template>`

--- snippets/polymer-element.cson
+++ snippets/polymer-element.cson
@@ -5,12 +5,12 @@
     <link rel="import" href="${1:../bower_components}/polymer/polymer.html">

     <dom-module id="$2">
-      <style>
-        :host {
-          $5
-        }
-      </style>
       <template>
+        <style>
+          :host {
+            $5
+          }
+        </style>
         $4
       </template>
       <script>
@@ -39,12 +39,12 @@
     <link rel="import" href="${1:../bower_components}/polymer/polymer.html">

     <dom-module id="$2">
-      <style>
-        :host {
-          $5
-        }
-      </style>
       <template>
+        <style>
+          :host {
+            $5
+          }
+        </style>
         $4
       </template>
       <script src="$3">
@@ -57,15 +57,15 @@
     <link rel="import" href="${1:../bower_components}/polymer/polymer.html">

     <dom-module id="$2">
-      <style>
-        :host {
-          $4
-        }
-        .content-wrapper > ::content {
-          $5
-        }
-      </style>
       <template>
+        <style>
+          :host {
+            $4
+          }
+          .content-wrapper > ::content {
+            $5
+          }
+        </style>
         $3
         <div class="content-wrapper">
           <content></content>


Updating windows_feature resource snippet

--- snippets/windows_feature.cson
+++ snippets/windows_feature.cson
@@ -1,4 +1,4 @@
 '.source.inspec':
   'Describe windows_feature':
     'prefix': 'windows_feature'
-    'body': "# http://inspec.io/docs/reference/resources/windows_feature/\ndescribe windows_feature('${1:name}') do\n  it { should${2:_not} ${3:exist} }${4}\nend"
+    'body': "# http://inspec.io/docs/reference/resources/windows_feature/\ndescribe windows_feature('${1:feature_name}') do\n  it { should${2:_not} be_installed }${3}\nend"


fix keygen bug

fix keygen bug

--- js/src/crypto/RsaKeyGenerator.coffee
+++ js/src/crypto/RsaKeyGenerator.coffee
@@ -15,7 +15,7 @@
   class RsaKeyGenerator

     generate: (params) ->
-      Forge.rsa.generateKeypair(params)
+      Forge.rsa.generateKeyPair(params)

     generateKeypair: ->
       params = { bits: RSA_KEY_SIZE, e: EXPONENT }


Format min/max/mean/sigma to 6 significant digits.

--- h2o-web/src/scripts/frame-view.coffee
+++ h2o-web/src/scripts/frame-view.coffee
@@ -1,9 +1,26 @@
-__formatFunctions = {}
-getFormatFunction = (precision) ->
-  if precision is -1
-    identity
+significantDigitsBeforeDecimal = (value) -> 1 + Math.floor Math.log(value) / Math.LN10
+
+formatToSignificantDigits = (digits, value) ->
+  if value is 0
+    0
   else
-    __formatFunctions[precision] or __formatFunctions[precision] = d3.format ".#{precision}f"
+    sd = significantDigitsBeforeDecimal value
+    if sd >= digits
+      value.toFixed 0
+    else
+      magnitude = Math.pow 10, digits - sd
+      Math.round(value * magnitude) / magnitude
+
+formatReal = do ->
+  __formatFunctions = {}
+  getFormatFunction = (precision) ->
+    if precision is -1
+      identity
+    else
+      __formatFunctions[precision] or __formatFunctions[precision] = d3.format ".#{precision}f"
+
+  (precision, value) ->
+    (getFormatFunction precision) value

 Steam.FrameView = (_, _frame) ->
   createSummaryRow = (attribute, columns) ->
@@ -24,10 +41,23 @@
               column.domain.length
             else
               column[attribute]
-        else
+        when 'real'
           switch attribute
             when 'cardinality'
               '-'
+            when 'min', 'max', 'mean'
+              formatReal column.precision, column[attribute]
+            when 'sigma'
+              formatToSignificantDigits 6, column[attribute]
+            else
+              column[attribute]
+
+        else # int
+          switch attribute
+            when 'cardinality'
+              '-'
+            when 'min', 'max', 'mean', 'sigma'
+              formatToSignificantDigits 6, column[attribute]
             else
               column[attribute]

@@ -45,7 +75,7 @@
             '-'
           else
             if column.type is 'real'
-              (getFormatFunction column.precision) value
+              formatReal column.precision, value
             else
               value

@@ -56,7 +86,7 @@
     for attribute in attributes
       rows.push createSummaryRow attribute, columns
     rows
-
+
   createDataRows = (offset, rowCount, columns) ->
     rows = []
     for index in [0 ... rowCount]


Closing terminal-status returns to previous location of cursor

--- lib/command-output-view.coffee
+++ lib/command-output-view.coffee
@@ -90,6 +90,7 @@
       @program.kill()

   open: ->
+    @lastLocation = atom.workspace.getActivePane()
     atom.workspaceView.prependToBottom(this) unless @hasParent()
     if lastOpenedView and lastOpenedView != this
       lastOpenedView.close()
@@ -99,6 +100,7 @@
     @cmdEditor.focus()

   close: ->
+    @lastLocation.activate()
     @detach()
     lastOpenedView = null


parallel ajax requests

parallel ajax requests

--- source/javascripts/all.coffee
+++ source/javascripts/all.coffee
@@ -3,74 +3,74 @@
 render = ->
   width       = $(document.body).width()
   height      = Math.min(500, width)
-  colors      = ['#1a1a1a', '#353535', '#555', '#757575', '#959595', '#b5b5b5', '#d5d5d5', '#f5f5f5']
-  color       = d3.scale.quantile().range colors
+  # colors      = ['#1a1a1a', '#353535', '#555', '#757575', '#959595', '#b5b5b5', '#d5d5d5', '#f5f5f5']
+  # color       = d3.scale.quantile().range colors
   projection  = d3.geo.albersUsa().scale(1).translate [ 0, 0 ]
   path        = d3.geo.path().projection(projection)
+  fill        = d3.scale.log().clamp(true).range ['#f1f1f1', '#0aafed']

   map = d3.select('body').append('svg')
     .attr('width', width)
     .attr('height', height)

-  d3.json '/data/recruiting.json', (usa) ->
   tip = d3.tip().attr('class', 'd3-tip').html (d) ->
     p = d.properties
     "
#{p.name} County

#{p.four_star || 0} ☆☆☆☆ athletes since 2002.
"
   map.call(tip)
+
+  $.when($.ajax('/data/recruiting.json'), $.ajax('/data/stadiums.csv')).then (r1, r2) ->
+    usa      = r1[0]
+    stadiums = d3.csv.parse(r2[0])
+
+    # Convert to GeoJSON
     states   = topojson.mesh usa, usa.objects.states, (a, b) -> a.id != b.id
     counties = topojson.feature usa, usa.objects.counties
     nation   = topojson.mesh usa, usa.objects.nation

+    fill.domain [0.1, d3.max(counties.features, (d) -> parseFloat(d.properties.four_star))]
+
+    # Auto scale map based on bounds
     projection.scale(1).translate([0, 0])
     b = path.bounds(nation)
     s = 1 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height)
     t = [(width - s * (b[1][0] + b[0][0])) / 2, (height - s * (b[1][1] + b[0][1])) / 2]
     projection.scale(s).translate(t)

+    # Add counties
     map.append('g')
       .attr('class', 'counties')
     .selectAll('path.county')
       .data(counties.features)
     .enter().append('path')
-      .attr('d', path)
       .attr('class', 'county')
       .style('fill', (d) -> fill(parseFloat(d.properties.four_star)))
       .attr('d', path)
       .on('mouseover', tip.show)
       .on('mouseout', tip.hide)

+    # Add states mesh
     map.append('path')
       .datum(states)
       .attr('class', 'states')
       .attr('d', path)

+    # Add nation mesh
     map.append('path')
       .datum(nation)
       .attr('class', 'nation')
       .attr('d', path)
-    # map.append('g')
-    #   .attr('class', 'nation')
-    # .selectAll('path.nation')
-    #   .data(nation)
-    # .enter().append('path')
-    #   .attr('d', path)
-    #   .attr('class', 'nation')

-  # svg.append("g")
-  #     .attr("class", "counties")
-  #   .selectAll("path")
-  #     .data(topojson.feature(us, us.objects.counties).features)
-  #   .enter().append("path")
-  #     .attr("d", path)
-  #     .style("fill", function(d) { return fill(path.area(d)); });
+    for stadium in stadiums
+      stadium.position = projection [stadium.lat, stadium.lon]

-  # svg.append("path")
-  #     .datum(topojson.mesh(us, us.objects.states, function(a, b) { return a.id !== b.id; }))
-  #     .attr("class", "states")
-  #     .attr("d", path);
-
-    # Auto scale map to fit within bounds
+    map.selectAll('.stadiums')
+      .data(stadiums)
+    .enter().append('circle')
+      .attr('cx', (d) -> d.position[0])
+      .attr('cy', (d) -> d.position[1])
+      .attr('r', 2)
+      .attr('class', 'stadium')

 $(render)


fix typo

fix typo

--- apps/galleries_institutions/components/filter_facet/partner_filter_facet.coffee
+++ apps/galleries_institutions/components/filter_facet/partner_filter_facet.coffee
@@ -16,7 +16,7 @@
     # Exclude items that were not specified in `allItems`.
     # Default count to zero for items that were not included in the response.
     @countItems = _.map @allItems, (item) ->
-      _.find(changed.countItems, id: item.id,) || _.extend {count: 0}, item
+      _.find(changed.countItems, id: item.id) || _.extend {count: 0}, item

   matcher: (query, callback) =>
     if query.length


Handling rollout of v2 API

Handling rollout of v2 API

--- designate.coffee
+++ designate.coffee
@@ -32,13 +32,13 @@
       d.resolve
         expiry: body.access.token.expires,
         token: body.access.token.id,
-        endpoint: designateEndpoint
+        endpoint: designateEndpoint+"v1/"
   d.promise

 listDomains = (token, endpoint) ->
   d = Q.defer()
   options =
-    url: endpoint + '/domains'
+    url: endpoint + 'domains/'
     json: true
     headers:
       'Accept': 'application/json'
@@ -53,7 +53,7 @@
 listRecords = (token, endpoint, domainId) ->
   d = Q.defer()
   options =
-    url: endpoint + '/domains/' + domainId + '/records'
+    url: endpoint + 'domains/' + domainId + '/records'
     json: true
     headers:
       'Accept': 'application/json'
@@ -68,7 +68,7 @@
 addRecord = (token, endpoint, domainId, record) ->
   d = Q.defer()
   options =
-    url: endpoint + '/domains/' + domainId + '/records'
+    url: endpoint + 'domains/' + domainId + '/records'
     json: true
     headers:
       'Accept': 'application/json'
@@ -85,7 +85,7 @@
 deleteRecord = (token, endpoint, domainId, recordId) ->
   d = Q.defer()
   options =
-    url: endpoint + '/domains/' + domainId + '/records/' + recordId
+    url: endpoint + 'domains/' + domainId + '/records/' + recordId
     headers:
       'X-Auth-Token': token
   request.del options, (error, response) ->


Update schema comment

Update schema comment

--- imports/schemas/incidentReport.coffee
+++ imports/schemas/incidentReport.coffee
@@ -63,8 +63,10 @@
     type: String
     allowedValues: ["day","precise"]
     optional: true
-  # Datetimes are treated as offset naive so the look the same from any
+  # Datetimes are treated as offset naive so the look they same from any
   # browser client and match the dates in their source documents.
+  # Internally this is done by working in UTC time since there
+  # is no timezone-naive datetime type.
   "dateRange.start":
     type: Date
     optional: true


Reinstated focus method per @mrusschen's comment

--- core/app/backbone/views/fact_relations/auto_complete_fact_relations_view.coffee
+++ core/app/backbone/views/fact_relations/auto_complete_fact_relations_view.coffee
@@ -25,6 +25,7 @@
       search_collection: => new FactRelationSearchResults([], fact_id: options.fact_id)
       placeholder: @placeholder(options.type)

+    @listenTo @_text_input_view, 'focus', @focus
     @listenTo @model, 'change', @queryChanges

   placeholder: (type) ->
@@ -78,6 +79,11 @@

   setQuery: (text) -> @model.set text: text

+  focus: ->
+    @$el.addClass 'active'
+
+    mp_track "Evidence: Search focus"
+
   reset: ->
     @setQuery ''
     @wheel.clear()


Loader: Fix compatibility with Webpack 2

--- engine/loader.coffee
+++ engine/loader.coffee
@@ -340,7 +340,7 @@
             script.async = true

             if process.browser
-                physics_engine_url = require("file?name=/libs/ammo.asm.js!./libs/ammo.asm.js")
+                physics_engine_url = require("file-loader?name=/libs/ammo.asm.js!./libs/ammo.asm.js")
             else
                 dirname =  __dirname.replace(/\\/g, '/')
                 physics_engine_url = 'file://' + dirname + "/libs/ammo.asm.js"


remove old blanket test helper

remove old blanket test helper

--- test/blanket-load_test.coffee
+++ test/blanket-load_test.coffee
@@ -1,5 +0,0 @@
-# this file requires all avaliable modules so blanket includes them in coverage
-matchesBlanket = (path) -> path.match /node_modules\/blanket/
-runningTestCoverage = Object.keys(require.cache).filter(matchesBlanket).length
-if runningTestCoverage
-  require('require-dir')("#{__dirname}/../src",{recurse:true, duplicates:true})


fixing object naming

fixing object naming

--- src/scripts/githooks/coreos_restart/config.coffee
+++ src/scripts/githooks/coreos_restart/config.coffee
@@ -29,7 +29,7 @@
     services = {}
     for name in names
       services[name] = yield pull_configuration
-        name
+        name: name
         path: join app.launch, name

     return services


Download Link : removed whitespace

Download Link : removed whitespace

--- client/app/Applications/Activity.kdapplication/views/activitylistheader.coffee
+++ client/app/Applications/Activity.kdapplication/views/activitylistheader.coffee
@@ -127,9 +127,8 @@
     message =
       """
       We successfuly saved your old files.

-      Your old files are at

-      your #{vms.first} VM  and in

-
+      Your old files are at your

+      #{vms.first} VM  and in

       /home/#{KD.whoami().profile.nickname}/#{folderName}  folder

       """


Rename Project.buildEditSession -> Project.open

--- spec/autocomplete-spec.coffee
+++ spec/autocomplete-spec.coffee
@@ -40,7 +40,7 @@

   beforeEach ->
     window.rootView = new RootView
-    editor = new Editor(editSession: project.buildEditSession('sample.js'))
+    editor = new Editor(editSession: project.open('sample.js'))
     atom.activatePackage('autocomplete')
     autocomplete = new AutocompleteView(editor)
     miniEditor = autocomplete.miniEditor


:white_check_mark: Test standAloneMinimapForEditor

--- spec/minimap-main-spec.coffee
+++ spec/minimap-main-spec.coffee
@@ -63,7 +63,7 @@
     it 'destroys all the minimap elements', ->
       expect(editorElement.shadowRoot.querySelector('atom-text-editor-minimap')).not.toExist()

-  ##    ########  ##       ##     ##  ######   #### ##    ##  ######
+  ##    ########  ##       ##     ##  ######   #### ##    ##  ######
   ##    ##     ## ##       ##     ## ##    ##   ##  ###   ## ##    ##
   ##    ##     ## ##       ##     ## ##         ##  ####  ## ##
   ##    ########  ##       ##     ## ##   ####  ##  ## ## ##  ######
@@ -74,6 +74,11 @@
   describe 'service', ->
     it 'returns the minimap main module', ->
       expect(minimapPackage.provideMinimapServiceV1()).toEqual(minimapPackage)
+
+    it 'creates standalone minimap with provided text editor', ->
+      textEditor = new TextEditor({})
+      standaloneMinimap = minimapPackage.standAloneMinimapForEditor(textEditor)
+      expect(standaloneMinimap.getTextEditor()).toEqual(textEditor)

   describe 'plugins', ->
     [registerHandler, unregisterHandler, plugin] = []


Add support for React Editor

Add support for React Editor

[Closes #15]

--- lib/highlight-line-view.coffee
+++ lib/highlight-line-view.coffee
@@ -1,4 +1,4 @@
-{EditorView, View} = require 'atom'
+{ReactEditorView, EditorView, View} = require 'atom'
 {$} = require 'atom'

 lines = []
@@ -152,24 +152,50 @@
   showHighlight: =>
     styleAttr = @makeLineStyleAttr()
     if styleAttr
-      cursorViews = @editorView.getCursorViews()
-      for cursorView in cursorViews
-        range = cursorView.getScreenPosition()
-        lineElement = @editorView.lineElementForScreenRow(range.row)
+      if @editorView.getCursorViews?
+        cursors = @editorView.getCursorViews()
+      else
+        editor = @editorView.getEditor()
+        cursors = editor.getCursors()
+      for cursor in cursors
+        range = cursor.getScreenPosition()
+        lineElement = @findLineElementForRow(@editorView, range.row)
         if selection = @editorView.editor.getSelection()
           if selection.isSingleScreenLine()
+            if @editorView.constructor.name is "ReactEditorView"
+              pos = $(lineElement).css("position")
+              topPX = $(lineElement).css("top")
+              styleAttr += "position: #{pos}; top: #{topPX}; width: 100%"
+
             $(lineElement).attr 'style', styleAttr
           else if atom.config.get('highlight-line.enableSelectionBorder')
             selectionStyleAttrs = @makeSelectionStyleAttr()
-            selections = @editorView.getSelectionViews()
+            selections = @editorView.editor.getSelections()
             for selection in selections
               selectionRange = selection.getScreenRange()
               start = selectionRange.start.row
               end = selectionRange.end.row
-              startLine = @editorView.lineElementForScreenRow(start)
-              endLine = @editorView.lineElementForScreenRow(end)
+
+              startLine = @findLineElementForRow(@editorView, start)
+              endLine = @findLineElementForRow(@editorView, end)
+              if @editorView.constructor.name is "ReactEditorView"
+                pos = $(startLine).css("position")
+                topPX = $(startLine).css("top")
+                selectionStyleAttrs[0] += "position: #{pos}; top: #{topPX}; width: 100%"
+                pos = $(endLine).css("position")
+                topPX = $(endLine).css("top")
+                selectionStyleAttrs[1] += "position: #{pos}; top: #{topPX}; width: 100%"
+
               $(startLine).attr 'style', selectionStyleAttrs[0]
               $(endLine).attr 'style', selectionStyleAttrs[1]
+
+
+  findLineElementForRow: (editorView, row) ->
+    if editorView.lineElementForScreenRow?
+      editorView.lineElementForScreenRow(row)
+    else
+      # For React Editor
+      editorView.find(".line[data-screen-row='#{row}']")

   wantedColor: (color) ->
     wantedColor = atom.config.get("highlight-line.#{color}")


added testing for immediate children

added testing for immediate children

--- test/api.traversing.coffee
+++ test/api.traversing.coffee
@@ -51,7 +51,12 @@
     it '(invalid selector) : should return empty', ->
       $('ul', fruits).children('.lulz').should.have.length 0

-    it 'should only match immediate children, not ancestors'
+    it 'should only match immediate children, not ancestors', ->
+      $fruits = $.load(fruits)
+      $fruits('.pear').append('
Green
');
+
+      $('ul', $fruits.html()).children('.green').length.should.equal 0
+

   describe '.next', ->


We don't even have to bother about this actually.

--- lib/client/autoform-slingshot.coffee
+++ lib/client/autoform-slingshot.coffee
@@ -132,13 +132,6 @@
         statusTracking.stop()
         if err
           console.error err
-        else
-          # Patch cache upload.
-          SlingshotAutoformFileCache.remove {
-            template: instance.data.atts.id
-            field: name
-            directive: directiveName
-          }

       # Wait for authorization and for transfer to start.
       statusTracking = Tracker.autorun =>


[remove] logic that didn't actually work from index_view.js.coffee

--- app/assets/javascripts/backbone/apps/addresses/index/index_view.js.coffee
+++ app/assets/javascripts/backbone/apps/addresses/index/index_view.js.coffee
@@ -108,7 +108,6 @@
       'btnSave': '.btn-save'
       'btnCancel': '.btn-cancel'
       'btnDelete': '.btn-delete'
-      'btnNewAddress': '.add-new a'

     modelEvents:
       'change:name': 'reRender'
@@ -120,7 +119,6 @@
       'click @ui.btnSave': '_clickSave'
       'click @ui.btnCancel': '_clickCancel'
       'click @ui.btnDelete': '_clickDelete'
-      'click @ui.btnNewAddress': '_clickNewAddress'

     serializeData: ->
       _.extend super,
@@ -314,10 +312,6 @@
       $target.addClass 'current'
       @ui.conversionPrelabel.toggle @collection.conversion isnt 'all'
       @ui.conversionLabel.text $target.text()
-
-    _clickNewAddress: (event) ->
-      event.preventDefault()
-      App.vent.trigger 'toggle:addresses:form'

   ##############################################################################


fix formatting

fix formatting

--- test/files/decode_pgp.iced
+++ test/files/decode_pgp.iced
@@ -294,10 +294,11 @@

 #============================================================================

-
 exports.public_key_with_pic = (T,cb) ->
   await KeyManager.import_from_armored_pgp { raw : keys.with_pic_1 } , defer err, km
   T.no_error err
   T.equal km.user_attributes?.length, 1, "We got a picture out, as expected"
   T.assert km.user_attributes?[0]?.data?, "..with actual picture data"
   cb()
+
+#============================================================================


Include comma as a word boundary

Include comma as a word boundary

--- lib/spell-check-handler.coffee
+++ lib/spell-check-handler.coffee
@@ -2,7 +2,7 @@

 module.exports =
   findMisspellings: (text) ->
-    wordRegex = /(?:^|[\s\[\]])([a-zA-Z']+)(?=[\s\.\[\]:]|$)/g
+    wordRegex = /(?:^|[\s\[\]])([a-zA-Z']+)(?=[\s\.\[\]:,]|$)/g
     row = 0
     misspellings = []
     for line in text.split('\n')


Add `pcss` and `sss` file extensions

Add `pcss` and `sss` file extensions

Why we need `pcss`: We don't,  but a lot of users are familiar with the `pcss` file extension convention for PostCSS.
Why we need `sss`: The [SugarSS](https://github.com/postcss/sugarss) syntax has a [syntax highlight plugin](https://atom.io/packages/language-postcss-sugarss) that only recognizes this extension...


Filter both local and global jasmine paths from stack traces

--- lib/jasmine-node/failure-tree.coffee
+++ lib/jasmine-node/failure-tree.coffee
@@ -32,10 +32,13 @@
       @filterStackTrace(item)

   filterJasmineLines: (stackTraceLines) ->
-    jasmineFilename = require.resolve('./jasmine-1.3.1')
+    jasmineFilenames = [require.resolve('./jasmine-1.3.1')]
+    try
+      jasmineFilenames.push(require.resolve('jasmine'))
+
     index = 0
     while index < stackTraceLines.length
-      if stackTraceLines[index].indexOf(jasmineFilename) isnt -1
+      if _.some(jasmineFilenames, (jasmineFilename) -> stackTraceLines[index].indexOf(jasmineFilename) isnt -1)
         stackTraceLines.splice(index, 1)
       else
         index++


Fixes scale variations between the search matches and the minimal

As there's a slightly different char width between the minimap font and
the editor font we'll retrieve both widths and compute the ratio to
properly scale the find results.

--- lib/minimap-find-results-view.coffee
+++ lib/minimap-find-results-view.coffee
@@ -14,8 +14,15 @@

   class MinimapFindResultsView extends FindResultsView
     attach: ->
-      @getMinimap()?.miniOverlayer.append(this)
-      @css '-webkit-tranform', 'scale3d(0.7,1,1)'
+      minimap = @getMinimap()
+      minimap.miniOverlayer.append(this)
+
+      # As there's a slightly different char width between the minimap font
+      # and the editor font we'll retrieve both widths and compute the ratio
+      # to properly scale the find results.
+      minimapWidth = minimap.miniEditorView.find('.lines').width()
+      editorWidth = @getEditor().find('.lines').width()
+      @css '-webkit-transform', "scale3d(#{minimapWidth / editorWidth},1,1)"

     getMinimap: ->
       minimapInstance.minimapForEditorView(@getEditor())


Fix some of the bindings

Fix some of the bindings

--- library/exposure/access.coffee
+++ library/exposure/access.coffee
@@ -100,5 +100,5 @@
             assert not _.isEmpty(content), "no content"
             session["x-authenticate-entity"] = content
             assert _.isFunction(session.save), noSave
-            session.save -> @derefernce container, ->
+            session.save => @dereference container, ->
                 return callback undefined, content


wording

wording

--- library/membrane/visual.coffee
+++ library/membrane/visual.coffee
@@ -126,7 +126,7 @@
     # JavaScript sources passed in as the remote objects. Please refer
     # to the implementation and the class for more information on it.
     inject: (context, subject, symbol) ->
-        assert caching = context.caching ?= new Object
+        assert caching = context.caching ?= new Object()
         scripts = -> assert context.scripts.push subject
         sources = -> assert context.sources.push compile()
         compile = -> subject.remote.compile caching, symbol


Allow composition only for abstract classes

--- library/nucleus/compose.coffee
+++ library/nucleus/compose.coffee
@@ -30,6 +30,7 @@
 logger = require "winston"
 events = require "events"
 colors = require "colors"
+assert = require "assert"
 nconf = require "nconf"
 https = require "https"
 http = require "http"
@@ -112,7 +113,9 @@
         foreign = compound.hierarchy()
         identify = compound.identify()
         duplicate = "Duplicate #{identify} compound"
-        throw new Error duplicate if compound in current
+        notAbstract = "The #{identify} is not abstract"
+        assert compound not in current, duplicate
+        assert compound.abstract?(), notAbstract
         cmp = (ersatz) -> (c) -> c.similarWith ersatz
         culrpit = (shape) -> not _.any commons, cmp shape
         commons = _.filter current, (x) -> _.any foreign, cmp x


add a useful wormhole into Service#spawn

--- library/nucleus/service.coffee
+++ library/nucleus/service.coffee
@@ -129,14 +129,15 @@
     # the router. This is invoked by the watcher when it discovers
     # new suitable services to register. This works asynchronously!
     # You need to take this into account, when overriding this one.
-    @spawn: (kernel, callback) ->
+    @spawn: (kernel, callback, alloc) ->
         noKernel = "no kernel supplied or given"
         noFunc = "got no valid callback function"
         assert _.isObject(kernel or null), noKernel
         assert _.isFunction(lazy = try @lazy() or 0)
         assert _.isFunction(callback or null), noFunc
+        alloc ?= => new this kernel, callback, alloc
         do => lazy.call this, kernel, callback # init
-        assert service = new this arguments... # new()
+        assert (service = alloc()).objectOf this or 0
         assert downstream = try service.downstream or 0
         message = "Spawned a new instance of %s service"
         firings = "Downstream spawning sequences in %s"


Fix typo - missing bracket

Fix typo - missing bracket

--- drivers/javascript/ast.coffee
+++ drivers/javascript/ast.coffee
@@ -89,7 +89,7 @@
         options = {} if not options?

         if callback? and typeof callback isnt 'function'
-            return Promise.reject(new err.RqlDriverError("If provided, the callback must be a function. Please use `run(connection[, options], callback])"))
+            return Promise.reject(new err.RqlDriverError("If provided, the callback must be a function. Please use `run(connection[, options][, callback])"))

         # Check if the arguments are valid types
         for own key of options


with luck this will be the end of my xdebug message processing problems

related to what happens when only half a message is received

--- lib/engines/dbgp/dbgp-instance.coffee
+++ lib/engines/dbgp/dbgp-instance.coffee
@@ -59,6 +59,8 @@
               when "init" then @onInit result
               when "response"
                 @parseResponse result
+      else
+        return buffer
     return buffer

   parseResponse: (data) =>


Fix VIDEO sign cleaning up too eagerly

Fix VIDEO sign cleaning up too eagerly

--- elements/stream-channel.coffee
+++ elements/stream-channel.coffee
@@ -1,4 +1,6 @@
-RTCConnection = (leagueId) ->
+activeSessions = {}
+
+RTCConnection = (leagueId, element) ->
   connection = new RTCMultiConnection(leagueId)
   onMessageCallbacks = {}
   socket = io.connect('http://localhost:5555/')
@@ -6,8 +8,9 @@
   socket.on 'message', (data) ->
     return if data.sender == connection.userid
     frameId = data.message?.sessionid
-    extra = connection.sessionDescriptions[frameId]?.extra
-    extra.lastMessage = new Date() if extra
+    if frameId
+      element.fire("new-stream", frameId) unless activeSessions[frameId]
+      activeSessions[frameId] = new Date()

     if onMessageCallbacks[data.channel]
       onMessageCallbacks[data.channel](data.message)
@@ -38,13 +41,11 @@
   connection.connect()

 clearOldSessions = (connection) ->
-  for frameId of connection.sessionDescriptions
-    if connection.sessionDescriptions[frameId].extra.lastMessage
-      diff = new Date() - connection.sessionDescriptions[frameId].extra.lastMessage
-      delete connection.sessionDescriptions[frameId] if diff > 10000
+  for frameId, val of activeSessions
+    diff = new Date() - val
+    if diff > 10000
+      delete activeSessions[frameId]
       this.fire('stream-closed', frameId)
-    else
-      connection.sessionDescriptions[frameId].extra.lastMessage = new Date()

 Polymer
   is: 'stream-channel',
@@ -52,8 +53,6 @@
     leagueId: String
   },
   ready: ->
-    connection = RTCConnection(this.leagueId)
-    _this = @
+    connection = RTCConnection(this.leagueId, @)
     connection.onNewSession = (e) ->
-      _this.fire("new-stream", e.sessionid)
     setInterval(clearOldSessions.bind(@, connection), 10000)


Don't update selection after indenting visually

This allows the indention keybindings to be used multiple times without
clobbering the selection.

--- lib/operators/indent-operators.coffee
+++ lib/operators/indent-operators.coffee
@@ -10,7 +10,6 @@
   # Returns nothing.
   execute: (count=1) ->
     @indent(count)
-    @vimState.activateCommandMode()

   # Protected: Indents or outdents the text selected by the given motion.
   #
@@ -20,6 +19,7 @@
   # Returns nothing.
   indent: (count, direction='indent') ->
     row = @editor.getCursorScreenRow()
+    mode = @vimState.mode

     @motion.select(count)
     if direction == 'indent'
@@ -29,8 +29,10 @@
     else if direction == 'auto'
       @editor.autoIndentSelectedRows()

-    @editor.setCursorScreenPosition([row, 0])
-    @editor.moveCursorToFirstCharacterOfLine()
+    if mode != 'visual'
+      @editor.setCursorScreenPosition([row, 0])
+      @editor.moveCursorToFirstCharacterOfLine()
+      @vimState.activateCommandMode()

 #
 # It outdents everything selected by the following motion.
@@ -43,7 +45,6 @@
   # Returns nothing.
   execute: (count=1) ->
     @indent(count, 'outdent')
-    @vimState.activateCommandMode()

 #
 # It autoindents everything selected by the following motion.
@@ -56,6 +57,5 @@
   # Returns nothing.
   execute: (count=1) ->
     @indent(count, 'auto')
-    @vimState.activateCommandMode()

 module.exports = {Indent, Outdent, Autoindent}


improve function naming

improve function naming

--- long-polling/lib/server.coffee
+++ long-polling/lib/server.coffee
@@ -63,7 +63,7 @@
   query q, [channel, ts], cb

-handler = (channel, last_event_id, cb)->
+fetch_events = (channel, last_event_id, cb)->
     if last_event_id.substr(0, 3) == 'rt-'
       last_event_id = last_event_id.substr(3)
       events_since_time(channel, last_event_id, cb)
@@ -141,7 +141,7 @@
       clear_waiting()

     handle_subscription = (c, message)->
-      handler channel, last_event_id, (err, evts)->
+      fetch_events channel, last_event_id, (err, evts)->
         return http_error 500, 'Failed to get event data' if err
         abort_processing = write res, evts, true
         last_event_id = evts[evts.length-1].id if (evts and evts.length > 0)
@@ -150,7 +150,7 @@
           clear_waiting()
           res.end()

-    handler channel, last_event_id, (err, evts)->
+    fetch_events channel, last_event_id, (err, evts)->
       return http_error res, 500, 'Failed to get event data: ' + err if err

       last_event_id = evts[evts.length-1].id if (evts and evts.length > 0)


checkArguments should resolve with no value.

--- src/ArgumentsValidator.coffee
+++ src/ArgumentsValidator.coffee
@@ -45,6 +45,7 @@
         if checker
           Promise.fromCallback (fn) ->
             checker args[idx], fn
+      .return()
     .asCallback cb

   # @private


add parentheses and return statement to example code

--- readme-src.coffee
+++ readme-src.coffee
@@ -1474,7 +1474,7 @@

 ```js
   Bacon.when(
-    [tick, keyEvent], function(_, k) { handleKeyEvent(k); handleTick },
+    [tick, keyEvent], function(_, k) { handleKeyEvent(k); return handleTick(); },
     [tick], handleTick)
 ```


Remove slide upload limit

Remove slide upload limit

--- routes/api.coffee
+++ routes/api.coffee
@@ -113,9 +113,6 @@
     req.flash 'error', 'Could not find user!'
     return res.redirect '/admin'
   user = users.getUsers()[user]
-  if !user.data.admin and user.data.slides.length >= user.data.maxSlides
-    req.flash 'error', 'Slide limit reached!'
-    return res.redirect '/admin'
   user.addSlide data, (err) ->
     users.save()
     storage.setItemSync('lastmodified', Date.now());


Add spell check underline to front marker layer

--- services/web/public/coffee/ide/editor/directives/aceEditor/spell-check/HighlightedWordManager.coffee
+++ services/web/public/coffee/ide/editor/directives/aceEditor/spell-check/HighlightedWordManager.coffee
@@ -21,7 +21,7 @@
 				highlight.row, highlight.column,
 				highlight.row, highlight.column + highlight.word.length
 			)
-			highlight.markerId = @editor.getSession().addMarker range, "spelling-highlight"
+			highlight.markerId = @editor.getSession().addMarker range, "spelling-highlight", null, true
 			@highlights.rows[highlight.row] ||= []
 			@highlights.rows[highlight.row].push highlight


resurrection.account: don't use wrapper & scroll view for list controller views

--- client/Account/AppView.coffee
+++ client/Account/AppView.coffee
@@ -50,9 +50,12 @@
     listViewClass   = if listClasses[type] then listClasses[type] else KDListView
     controllerClass = if listClasses["#{type}Controller"] then listClasses["#{type}Controller"]

-    view       = new listViewClass cssClass : type, delegate: this
-    controller = new controllerClass {view}  if controllerClass
-    @addSubView view
+    @addSubView view = new listViewClass cssClass : type, delegate: this
+    if controllerClass
+      controller   = new controllerClass
+        view       : view
+        wrapper    : no
+        scrollView : no

 class AccountsSwappable extends KDView
   constructor:(options,data)->


pricint : after payment, if new user, route him to create an account

--- client/Pricing/AppView.coffee
+++ client/Pricing/AppView.coffee
@@ -94,6 +94,11 @@
         title    : "Go to your environment"
         callback : ->
           KD.singleton("router").handleRoute "/Environments"
+    else
+      me = KD.whoami()
+      me.on "tokenCreated", (token) ->
+        KD.singleton('appManager').open 'Login', (app) ->
+          app.prepareFinishRegistrationForm token.token

   showGroupCreated: (group, subscription) ->


English is spoken.

English is spoken.

--- client/views/selection.coffee
+++ client/views/selection.coffee
@@ -17,12 +17,12 @@
   set = (to) ->
     ((b.closest ".containment").find ".record_selector").prop "checked", to
   select_on_click = ->
-    (b.text "Alle auswählen").click (x) ->
+    (b.text "Select all").click (x) ->
       x.preventDefault()
       unselect_on_click()
       set true
   unselect_on_click = ->
-    (b.text "Alle abwählen").click (x) ->
+    (b.text "Unselect all").click (x) ->
       x.preventDefault()
       select_on_click()
       set false


forEach added to memory store, passes through to lru

--- src/cache/memory_store.coffee
+++ src/cache/memory_store.coffee
@@ -20,7 +20,6 @@
     @cache = new LRU(normalized_options)

   set: (key, value, callback) =>
-#    console.log 'set, ', key, value
     return callback?(null, value) or @ if value._orm_never_cache # skip cache
     @cache.set(key, value)
     callback?(null, value)
@@ -28,12 +27,10 @@

   get: (key, callback) =>
     value = @cache.get(key)
-#    console.log 'get, ', key, value
     callback?(null, value)
     return value

   destroy: (key, callback) =>
-#    console.log 'destroy, ', key
     @cache.del(key)
     callback?()
     return @
@@ -48,3 +45,6 @@
     key = inflection.underscore(key)
     return key.toLowerCase() if key.indexOf('_') < 0
     return inflection.camelize(key)
+
+  forEach: (callback) => @cache.forEach(callback)
+


Do not get `View#events` prototype chain if they don’t exist.

--- src/chaplin/views/view.coffee
+++ src/chaplin/views/view.coffee
@@ -180,6 +180,7 @@
     if events
       @_delegateEvents events
       return
+    return unless @events
     for classEvents in utils.getAllPropertyVersions this, 'events'
       if typeof classEvents is 'function'
         throw new TypeError 'View#delegateEvents: functions are not supported'


removed unused assignment

removed unused assignment

--- src/commands/lifecycle.coffee
+++ src/commands/lifecycle.coffee
@@ -129,9 +129,8 @@

   rem: (msg) ->

-    user = msg.message.user.id
     targetingSelf = msg.match[0] is '!rem'
-    target = if targetingSelf then user else msg.match[1].trim()
+    target = if targetingSelf then msg.message.user.id else msg.match[1].trim()

     if targetingSelf or (not targetingSelf and @auth.hasRole(msg.envelope.user, 'officer'))


Makes bahn.de query for many rides

Makes bahn.de query for many rides

--- src/connectors/bahn.de.coffee
+++ src/connectors/bahn.de.coffee
@@ -67,7 +67,7 @@
             dest_id    = stations[0].id
             #log.notice dest_id
             if orig_id != dest_id
-              fin_url = "http://#{details.url_host}:#{details.url_port}/#{details.url_path}/connection?fromId=#{orig_id}&toId=#{dest_id}&fromType=STATION&toType=STATION&num=1"
+              fin_url = "http://#{details.url_host}:#{details.url_port}/#{details.url_path}/connection?fromId=#{orig_id}&toId=#{dest_id}&fromType=STATION&toType=STATION&num=9"
               log.debug fin_url
               run [fin_url]
             else


fixed console statements in safari

fixed console statements in safari

--- src/core/console/print.coffee
+++ src/core/console/print.coffee
@@ -1,5 +1,6 @@
-ie   = require "../../client/ie.js"
-wiki = require "./wiki.coffee"
+ie    = require "../../client/ie.js"
+touch = require "../../client/touch.coffee"
+wiki  = require "./wiki.coffee"

 icon = "http://d3plus.org/assets/img/favicon.ico"

@@ -64,8 +65,9 @@
         e.indexOf("d3plus.js:") < 0 and
         e.indexOf("d3plus.min.js:") < 0
       if stack.length and stack[0].length
-        splitter = (if window.chrome then "at " else "@")
-        url = stack[0].split(splitter)[1]
+        splitter = if window.chrome then "at " else "@"
+        url = stack[0]
+        url = url.split(splitter)[1] if url.indexOf(splitter) >= 0
         stack = url.split(":")
         stack.pop()  if stack.length is 3
         line = stack.pop()


Return absolute paths from $native.traverseTree()

Previously relative paths were generated even though
things like fs.list() and fs.listTree() would just
recombine them with the root path.

Closes #391

--- lib/load-paths-handler.coffee
+++ lib/load-paths-handler.coffee
@@ -13,8 +13,10 @@
         return true if _.contains(ignoredNames, segment)
       repo?.isPathIgnored(fs.join(rootPath, path))
     onFile = (path) ->
+      path = path.substring(rootPath.length + 1)
       paths.push(path) unless isIgnored(path)
     onDirectory = (path) ->
+      path = path.substring(rootPath.length + 1)
       not isIgnored(path)
     fs.traverseTree(rootPath, onFile, onDirectory)


fix(specs): Lazily require CategoryStore to fix broken tests

--- src/flux/models/thread.coffee
+++ src/flux/models/thread.coffee
@@ -6,7 +6,6 @@
 Contact = require './contact'
 Actions = require '../actions'
 Attributes = require '../attributes'
-CategoryStore = require '../stores/category-store'

 Function::getter = (prop, get) ->
   Object.defineProperty @prototype, prop, {get, configurable: yes}
@@ -113,8 +112,10 @@

   sortedLabels: ->
     return [] unless @labels
+    out = []

-    out = []
+    CategoryStore = require '../stores/category-store'
+
     isImportant = (l) -> l.name is 'important'
     isStandardCategory = (l) -> l.name in CategoryStore.StandardCategoryNames
     isUnhiddenStandardLabel = (l) ->


Update cards-es.coffee

Update cards-es.coffee

--- coffeescripts/cards-es.coffee
+++ coffeescripts/cards-es.coffee
@@ -906,7 +906,7 @@
             text: """TIE Advanced only.%LINEBREAK%When attacking with your primary weapon, if you have a target lock on the defender, you may add 1 %CRIT% result to your roll.  If you do, you cannot spend target locks during this attack."""
         "Ion Cannon Battery":
             text: """Attack (energy): Spend 2 energy from this card to perform this attack.  If this attack hits, the defender suffers 1 critical damage and receives 1 ion token.  Then cancel all dice results."""
-
+
     modification_translations =
         "Stealth Device":
             name: "Dispositivo de Sigilo"


Stepped okSubmits date

Stepped okSubmits date

--- server/api/dashboard.coffee
+++ server/api/dashboard.coffee
@@ -56,7 +56,7 @@
 export default dashboard = () ->
     queries =
         # remember that months start from 0
-        ok: {ok: 1, lastSubmitTime: {$gt: new Date(2017, 8, 25)}},
+        ok: {ok: 1, lastSubmitTime: {$gt: new Date(2017, 9, 4)}},
         wa: {solved: 0, ok: 0, ignored: 0, attempts: {$gt: 0}},
         ig: {ignored: 1},
         ac: {solved: 1}


Test grouping parser output into divs

Test grouping parser output into divs

--- spec/chattifier.spec.coffee
+++ spec/chattifier.spec.coffee
@@ -56,24 +56,11 @@
         toEqual link

   it "tests removing blockquote elements and preserving its HTML content", ->
-    # create mock documentument containing blockquote elements
-    # outer blockquote
-    bq1 = document.createElement 'blockquote'
-    p = document.createElement 'p'
-    p.textContent = 'Outer blockquote'
-    bq1.appendChild p
-    # inner blockquote
-    bq2 = document.createElement 'blockquote'
-    p = document.createElement 'p'
-    p.textContent = 'Inner blockquote'
-    bq2.appendChild p
-    bq1.appendChild bq2
-    node.appendChild bq1
-
-    # sanity test
-    html = "

Outer blockquote

Inner blockquote

"
-    expect(node.innerHTML).
-      toEqual html
+    # create mock document containing blockquote elements
+    html = "

Outer blockquote
" +
+           "

Inner blockquote
" +
+           "

"
+    node.innerHTML = html

     # run chattifier
     chattifier.removeBlockquotes()
@@ -86,3 +73,50 @@
     expect(node.innerHTML).
       toEqual html

+  describe "the HTML output should be grouped into divs regardless if", ->
+    it "has a header element as the topmost element, or if", ->
+      # create mock document of the following structure
+      h = "h" + Chattifier.headerStartLevel
+      html = "<" + h + ">
First
</" + h + ">" +
+             "<" + h + ">
Second
</" + h + ">"
+      node.innerHTML = html
+
+      # run chattifier
+      chattifier.groupIntoDivs()
+
+      # test output
+      html = '

' +
+             '
' +
+             '<' + h + '>
First
</' + h + '>
' +
+             '
' +
+             '<' + h + '>
Second
</' + h + '>
'
+      expect(node.innerHTML).
+        toEqual html
+
+    it "has a paragraph element as the topmost element", ->
+      # create mock document of the following structure
+      h = "h" + Chattifier.headerStartLevel
+      html = "
Zero
" +
+             "<" + h + ">
First
</" + h + ">" +
+             "<" + h + ">
Second
</" + h + ">"
+      node.innerHTML = html
+
+      # run chattifier
+      chattifier.groupIntoDivs()
+
+      # test output
+      html = '
' +
+             '
Zero

' +
+             '
' +
+             '<' + h + '>
First
</' + h + '>
' +
+             '
' +
+             '<' + h + '>
Second
</' + h + '>
'
+      expect(node.innerHTML).
+        toEqual html
+


Call save on EditSession instead of TextBuffer

--- spec/whitespace-spec.coffee
+++ spec/whitespace-spec.coffee
@@ -56,7 +56,7 @@
     config.set("whitespace.removeTrailingWhitespace", false)

     editor.insertText "don't trim me "
-    editor.getBuffer().save()
+    editor.save()
     expect(editor.getText()).toBe "don't trim me \n"

   describe "whitespace.ensureSingleTrailingNewline config", ->


Missing change in previous commit

Missing change in previous commit

--- engine/fetch_assets.coffee
+++ engine/fetch_assets.coffee
@@ -72,7 +72,7 @@
             else
                 scene = mesh_object.original_scene or mesh_object.scene
                 base = scene.data_dir + '/scenes/'
-                uri = base + scene.name + '/' + file_name + '.mesh'
+                uri = base + scene.original_scene_name + '/' + file_name + '.mesh'
                 fetch(uri).then (response)->
                     if not response.ok
                         return Promise.reject "Mesh '#{mesh_object.name}' could not be loaded from URL '#{uri}' with error '#{response.status} #{response.statusText}'"


Server: login referenceError fix and return null on success

--- servers/lib/server/index.coffee
+++ servers/lib/server/index.coffee
@@ -233,9 +233,9 @@
       appId   : 'NewKoding'
       version : '2.0'
     info.account.fetchOrCreateAppStorage storageOptions, (err, appStorage) ->
-      return res.send 500, "Internal error"  if err
-      res.cookie 'clientId', response.replacementToken
-      res.send 200, 'ok'
+      return res.send 500, 'Internal error'  if err
+      res.cookie 'clientId', info.replacementToken
+      res.send 200, null

 app.post '/:name?/Optout', (req, res) ->
   res.cookie 'useOldKoding', 'true'


Collaboration: Change google api drive authorization route

--- servers/lib/server/index.coffee
+++ servers/lib/server/index.coffee
@@ -133,7 +133,7 @@
     next()

-app.get "/-/google-api",(req, res)->
+app.get '/-/google-api/authorize/drive',(req, res)->
   ggl = require("googleapis")
   gsc = KONFIG.googleapiServiceAccount
   eml = gsc.serviceAccountEmail


No, you're tired.

No, you're tired.

--- generate-docs.coffee
+++ generate-docs.coffee
@@ -106,11 +106,11 @@
 			some = commentLines.some (line) -> line.match implementsPattern
 			if some

-				package_ = packages[hookName] ?= typeAndName
+				package_ = packages[typeAndName.name] ?= typeAndName
 				(package_.typesAndFilenames ?= []).push
 					type: typeAndName.type, filename: filename

-		package_ for name, package_ of packages
+		package_ for _, package_ of packages

 	hookInformation = {}
 	for filename, {commentLines} of sources


add high acc

add high acc

--- components/cms/lib/App.coffee
+++ components/cms/lib/App.coffee
@@ -47,11 +47,14 @@
     startGeoTracking: ->
       that = this
       if navigator.geolocation
-        setInterval ->
-          navigator.geolocation.getCurrentPosition (position)->
-            that.position = position
-            that.vent.trigger "newPosition"
-        , 3000
+        success = (position)->
+          that.position = position
+          that.vent.trigger "newPosition"
+        error = (err)->
+          console.log err
+        navigator.geolocation.watchPosition success, error,
+          enableHighAccuracy: true
+          maximumAge: 0

     initUpload: ->
       $('#upload').change ->


Send the text of the flash to the trigger

--- vendor/assets/javascripts/ajaxify_rails.js.coffee
+++ vendor/assets/javascripts/ajaxify_rails.js.coffee
@@ -246,7 +246,7 @@
     if flashes and flashes[this]
       $("##{this}").html flashes[this]
       $("##{this}").show()
-      $(document).trigger 'ajaxify:flash_displayed', [this]
+      $(document).trigger 'ajaxify:flash_displayed', [this, flashes[this] ]

     else
       $("##{this}").hide()


error on import failure

error on import failure

--- app/context.coffee
+++ app/context.coffee
@@ -92,12 +92,12 @@
     vars = module.context_vars
     if _.isFunction vars
       vars = vars.call context
-    [name, vars]
+    [name, vars ? {}]

   _.object _.filter _.map(context.modules, module_vars), ([n, f]) -> f

 collect_context_fns = (context) ->
-  _.object _.filter _.map(context.modules, (module, name) -> [name, module.context_fns]), ([n, f]) -> f
+  _.object _.filter _.map(context.modules, (module, name) -> [name, module.context_fns ? {}]), ([n, f]) -> f

 is_run_context = (o) ->
   o?.component_list?
@@ -196,7 +196,12 @@
   if lastSegment = '*'
     wildcard = true
     segments.pop()
-  value = _.reduce segments, ((result, key) -> result[key]), obj
+  try
+    value = _.reduce segments, ((result, key) -> result[key]), obj
+  catch
+    value = null
+  unless value?
+    throw new Error("can't import #{path}")
   if wildcard
     _.extend target, value
   else


JLog: Block all events

JLog: Block all events

--- workers/social/lib/social/models/log/index.coffee
+++ workers/social/lib/social/models/log/index.coffee
@@ -16,34 +16,37 @@
     sharedMethods   :
       instance      : []
       static        : []
-    indexes:
-      username : 1
-      ip       : 1
-    schema                :
-      type                :
-        type              : String
-        required          : yes
-        set               : (value)-> value.toLowerCase()
-      ip                  :
-        type              : String
-        required          : yes
-        default           : "127.0.0.1"
-      username            :
-        type              : String
-        required          : yes
-        default           : "guest"
-      createdAt           :
-        type              : Date
-        default           : -> new Date
-      success             :
-        type              : Boolean
-        default           : true
-      severity            :
-        type              : Number
-        default           : 5
-      payload             :
-        type              : String
-        required          : no
+    sharedEvents    :
+      static        : []
+      instance      : []
+    indexes         :
+      username      : 1
+      ip            : 1
+    schema          :
+      type          :
+        type        : String
+        required    : yes
+        set         : (value)-> value.toLowerCase()
+      ip            :
+        type        : String
+        required    : yes
+        default     : "127.0.0.1"
+      username      :
+        type        : String
+        required    : yes
+        default     : "guest"
+      createdAt     :
+        type        : Date
+        default     : -> new Date
+      success       :
+        type        : Boolean
+        default     : true
+      severity      :
+        type        : Number
+        default     : 5
+      payload       :
+        type        : String
+        required    : no

   @log = (data, callback)->
     log = new JLog data


Add event-kit to exports

Add event-kit to exports

--- exports/atom.coffee
+++ exports/atom.coffee
@@ -1,4 +1,5 @@
 {Point, Range} = require 'text-buffer'
+{Emitter, Disposable, CompositeDisposable} = require 'event-kit'
 {deprecate} = require 'grim'

 module.exports =
@@ -7,6 +8,9 @@
   GitRepository: require '../src/git-repository'
   Point: Point
   Range: Range
+  Emitter: Emitter
+  Disposable: Disposable
+  CompositeDisposable: CompositeDisposable

 # The following classes can't be used from a Task handler and should therefore
 # only be exported when not running as a child node process


Updated credit card validation check

Updated credit card validation check

--- app/assets/javascripts/sprangular/controllers/checkout/deliveryAndPayment.coffee
+++ app/assets/javascripts/sprangular/controllers/checkout/deliveryAndPayment.coffee
@@ -12,7 +12,7 @@

   $scope.advance = ->
     order = $scope.order
-    return if order.creditCard.isInvalid()
+    return unless order.creditCard.id? || order.creditCard.isValid()

     $scope.processing = true


Clean app.coffee

Clean app.coffee

--- app/src/app.coffee
+++ app/src/app.coffee
@@ -38,9 +38,6 @@

       @devicesManager.on 'LW.SetupCardLaunched', (event, data) ->
         self.router.go('/onboarding/management/welcome')
-
-
-

       @devicesManager.start()
       @router.go('/')


Added problems link to navbar

Added problems link to navbar

--- picoCTF-web/web/coffee/navbar.coffee
+++ picoCTF-web/web/coffee/navbar.coffee
@@ -4,6 +4,7 @@
   About: "/about"

 teacherLoggedIn =
+  Problems: "/problems"
   Shell: "/shell"
   Scoreboard: "/scoreboard"
   Classroom: "/classroom"
@@ -27,6 +28,7 @@
     Logout: "#"

 userLoggedIn =
+  Problems: "/problems"
   Shell: "/shell"
   Team: "/team"
   Chat: "/chat"


Allow passing any args to App#fetch alias

--- shared/app.coffee
+++ shared/app.coffee
@@ -25,8 +25,8 @@
   postInitialize: noop

   # @shared
-  fetch: (spec, callback) ->
-    @fetcher.fetch(spec, callback)
+  fetch: (args...) ->
+    @fetcher.fetch.apply(@fetcher, args)

   # @client
   bootstrapData: (modelMap) ->


Mixed up apply and call

Mixed up apply and call

--- drivers/javascript/net.coffee
+++ drivers/javascript/net.coffee
@@ -204,7 +204,7 @@
             if cb?
                 cb(args...)

-        noreplyWait = (not opts.noreplyWait?) or opts.noreplyWait
+        noreplyWait = ((not opts.noreplyWait?) or opts.noreplyWait) and @open
         if noreplyWait
             @noreplyWait(wrappedCb)
         else
@@ -413,7 +413,7 @@

         # This would simply be super(opts, wrappedCb), if we were not in the varar
         # anonymous function
-        TcpConnection.__super__.close.apply(this, opts, wrappedCb)
+        TcpConnection.__super__.close.call(this, opts, wrappedCb)
     )

     cancel: () ->


updating js driver for changed handshake

--- drivers/javascript/net.coffee
+++ drivers/javascript/net.coffee
@@ -7,6 +7,7 @@

 protodef = require('./proto-def')
 protoVersion = protodef.VersionDummy.Version.V0_3
+protoProtocol = protodef.VersionDummy.Protocol.JSON
 protoQueryType = protodef.Query.QueryType
 protoResponseType = protodef.Response.ResponseType

@@ -35,7 +36,6 @@
         @port = host.port || @DEFAULT_PORT
         @db = host.db # left undefined if this is not set
         @authKey = host.authKey || @DEFAULT_AUTH_KEY
-        @wire_protocol = 'json'
         @timeout = host.timeout || @DEFAULT_TIMEOUT

         @outstandingCallbacks = {}
@@ -311,8 +311,9 @@
             @write buf

             # Send the protocol type that we will be using to communicate with the server
-            buf = new Buffer(@wire_protocol, 'ascii')
-            @write buf
+            buf = new Buffer(4)
+            buf.writeUInt32LE(protoProtocol, 0)
+            @rawSocket.write buf

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


Bazinga :exclamation:

Bazinga :exclamation:

--- scripts/entrance.coffee
+++ scripts/entrance.coffee
@@ -6,5 +6,5 @@
     # If its dusya optionally follwed by ANYTHING
     if /^dusya/.test(username)
       msg.send "DEES NUTS"
-    else if username == 'anonuser'
+    else if /^anonuser/.test(username)
       msg.send "Bazinga!"


Adds !haha

Adds !haha

--- scripts/triggers.coffee
+++ scripts/triggers.coffee
@@ -48,6 +48,7 @@
   '!tableflippin' : "http://i.imgur.com/xBQOzc4.gif"
   '!goal'         : "GOOOOOOOOOOOOOOOOOOOOOOAAAAAAAAAAAAAAAAALLLLLLLLLL!!!!!!!"
   '!unstoppable'  : "I am unstoppable!!! http://i.imgur.com/ALHS4Za.png"
+  '!haha'         : "http://i.imgur.com/CVhoCwr.jpg"

 # Bot Info
 nick = process.env.HUBOT_IRC_NICK?.toLowerCase() ? "hubot"


Make output path configurable

Make output path configurable

--- rss.plugin.coffee
+++ rss.plugin.coffee
@@ -7,17 +7,18 @@

     config:
       collection: 'html'
+      url: '/rss.xml'

     writeAfter: ->
       {docpad} = @
       {site} = docpad.getTemplateData()
       feedCollection = docpad.getCollection @config.collection
-      feedPath = docpad.getConfig().outPath+'/rss.xml'
+      feedPath = docpad.getConfig().outPath + @config.url
       feed = new RSS
         title: site.title
         description: site.description
         site_url: site.url
-        feed_url: site.url + '/rss.xml'
+        feed_url: site.url + @config.url
         author: site.author
         pubDate: site.date.toISOString()

@@ -31,4 +32,4 @@
           date: document.date.toISOString()

       fs.writeFileSync feedPath, feed.xml(true)
-      docpad.log 'debug', "Wrote the rss.xml file to: #{feedPath}"
+      docpad.log 'debug', "Wrote the RSS xml file to: #{feedPath}"


Make sure that material bin slugs are unique

--- app/assets/javascripts/components/materials_bin/materials_bin.js.coffee
+++ app/assets/javascripts/components/materials_bin/materials_bin.js.coffee
@@ -10,7 +10,7 @@
     addSlugs = (list) =>
       for item in list
         if item.category
-          item.slug = item.category.toLowerCase().replace /\W/g, '-'
+          item.slug = @generateSlug item.category
           if item.children
             addSlugs item.children
     addSlugs @props.materials
@@ -52,6 +52,14 @@

   isSlugSelected: (column, slug) ->
     @state.selectedSlugs[column] is slug
+
+  generateSlug: (name) ->
+    @_isSlugTaken = {} unless @_isSlugTaken?
+    slug = name.toLowerCase().replace /\W/g, '-'
+    while @_isSlugTaken[slug]
+      slug += '-'
+    @_isSlugTaken[slug] = true
+    slug

   # Transforms @props.materials hash into array of arrays representing columns and their rows.
   # Raw form of @props.materials doesn't work well with table view.


ContextLayoutComponent

ContextLayoutComponent

--- app/context.coffee
+++ app/context.coffee
@@ -165,16 +165,22 @@

 ContextComponent = React.createIdentityClass
   displayName: 'ContextComponent'
-  mixins: [ContextRegisteringMixin, React.ObservableMixin]
-  get_observable: -> @props.model
+  mixins: [ContextRegisteringMixin]
   propTypes:
     ctx: (c) -> throw new Error("context required") unless is_run_context c['ctx']
-    # TODO type
-    model: React.PropTypes.object.isRequired
-    layout: React.PropTypes.func.isRequired
-    layout_props: React.PropTypes.object
   render: ->
-    @props.layout _.extend {children: @state.value}, @props.layout_props
+    ContextLayoutComponent {ctx: @props.ctx}
+
+
+ContextLayoutComponent = React.createClass
+  displayName: 'ContextLayoutComponent'
+  mixins: [React.ObservableMixin]
+  propTypes:
+    ctx: (c) -> throw new Error("context required") unless is_run_context c['ctx']
+  get_observable: -> @props.ctx.component_list.model
+  render: ->
+    ctx = @props.ctx
+    ctx.layout _.extend {children: @state.value}, ctx.layout_props

 TopLevelContextComponent = React.createClass
   displayName: 'TopLevelContextComponent'
@@ -331,11 +337,7 @@
 create_nested_context = (parent, overrides) ->
   new_context = _.extend Object.create(parent), {layout: React.SimpleLayoutComponent}, overrides
   new_context.component_list = component_list()
-  new_context.component = ContextComponent
-    ctx: new_context
-    model: new_context.component_list.model
-    layout: new_context.layout
-    layout_props: new_context.layout_props
+  new_context.component = ContextComponent ctx: new_context

   new_context


place pieces in piece directory

place pieces in piece directory

--- app/js/main.coffee
+++ app/js/main.coffee
@@ -1,6 +1,11 @@
 player = @Player

-t1 = ->
+pieces = {}
+
+piece = (name, def) ->
+  pieces[name] = def
+
+piece 'notes', ->
   player.note 'c4'
   player.note 'e4', start: 1/2
   player.note 'g4', start: 1
@@ -9,7 +14,7 @@
   player.note 'e4', start: 2.5, gain: 0.2
   player.note 'g4', start: 3, gain: 0.2

-t2 = ->
+piece 'arpeggiated chords', ->
   player.chord 'C4', pick: '0121212'
   player.rest 2
   player.chord 'F4', pick: '0121212'
@@ -18,7 +23,7 @@
   player.rest 2
   player.chord 'C4', pick: '1202120', duration: 10

-t3 = ->
+piece 'chord progression', ->
   player.progression 'I Ib Ic ii IV iii IVb V7 V7b V7c Ic Ib I'
   , pick: '0121'
   , chord_separation: 0
@@ -28,24 +33,6 @@
   , chord_separation: .5
   , gain: .5

-t4 = ->
-  for track_number in [0...5]
-    break unless track_number == 0
-    chord = ['C4', 'G4', 'D5', 'F5', 'E6'][track_number]
-    player.with_track (t) ->
-      # player.rest track_number * 5
-      gain = 1
-      tempo = 5
-      for i in [1..100]
-        player.note chord, gain: gain, start: Math.pow(1 + .1, i)
-        # player.rest 1 * tempo
-        tempo *= .9
-        # gain *= .9
-
 @play = ->
   player.rewind()
-  t1()
-
-# Meteor.startup ->
-#   player.onload ->
-#     t3()
+  pieces['chord progression']()


Correction chemin accessControl

Correction chemin accessControl

--- server/api/index.coffee
+++ server/api/index.coffee
@@ -1,6 +1,6 @@
 express = require('express')
 app     = express()
-access  = require "../../serveur/accessControl"
+access  = require "../accessControl"
 db      = require "../db"
 utils   = require "../utils"


Disable downloadContests

Disable downloadContests

--- server/cron/cron.coffee
+++ server/cron/cron.coffee
@@ -12,7 +12,7 @@
 jobUntilIgnored = new Cron.CronJob('59 */3 * * * *', downloadSubmits.runUntilIgnored, null, true);
 jobLast = new Cron.CronJob('*/30 * * * * *', downloadSubmits.runLast, null, true);

-jobContests = new Cron.CronJob('0 */10 * * * *', downloadContests.run, null, true);
+#jobContests = new Cron.CronJob('0 */10 * * * *', downloadContests.run, null, true);

 jobCf = new Cron.CronJob('0 0 * * * *', updateCf, null, true);


actually raise the blob limit

actually raise the blob limit

--- salvus/hub.coffee
+++ salvus/hub.coffee
@@ -6318,10 +6318,8 @@
 # Blobs
 ########################################

-# See note below about 12MB taking 26s once in production -- until that gets fixed, this must be kept small.
-# The drawback is that large images can't be rendered, etc.
-MAX_BLOB_SIZE = 1000000
-MAX_BLOB_SIZE_HUMAN = "1MB"
+MAX_BLOB_SIZE = 15000000
+MAX_BLOB_SIZE_HUMAN = "15B"

 blobs = {}