Cloudsdale.MessageController = Ember.Controller.extend

  content: null

  text: ( () ->
    text = @content.get('content') || ""
    text = text.replace(/\s/g, ' ')
    text = text.replace(/(\\r\\n|\\n|\\r)/g, '<br/>')
    return text
  ).property('content.content')

  avatar: ( () ->
    @content.get('author').get('avatar') if @content.get('author')
  ).property('content.author.avatar')

  name: ( () ->
    @content.get('author').get('displayName') if @content.get('author')
  ).property('content.author.displayName')

  handle: ( () ->
    @content.get('author').get('username') if @content.get('author')
  ).property('content.author.username')

  createdAt: ( () ->
    console.log @content.get('createdAt')
    @content.get('createdAt')
  ).property('content.createdAt')

  updatedAt: ( () ->
    @content.get('updatedAt')
  ).property('content.updatedAt')

  timestamp: ( () ->
    @content.get('timestamp')
  ).property('content.timestamp')

Cloudsdale.MessageController = Ember.Controller.extend

  content: null

  text: ( () ->
    text = @content.get('content') || ""
    text = text.replace(/\s(?=\s)/g, ' ')
    text = text.replace(/(\\r\\n|\\n|\\r)/g, '<br/>')
    return text
  ).property('content.content')

  avatar: ( () ->
    @content.get('author').get('avatar') if @content.get('author')
  ).property('content.author.avatar')

  name: ( () ->
    @content.get('author').get('displayName') if @content.get('author')
  ).property('content.author.displayName')

  handle: ( () ->
    @content.get('author').get('username') if @content.get('author')
  ).property('content.author.username')

  createdAt: ( () ->
    console.log @content.get('createdAt')
    @content.get('createdAt')
  ).property('content.createdAt')

  updatedAt: ( () ->
    @content.get('updatedAt')
  ).property('content.updatedAt')

  timestamp: ( () ->
    @content.get('timestamp')
  ).property('content.timestamp')

Use regex lookahead to sort out the issue with breaking words.


###
  Toggles the activation state of a survey based on the 'active' ReactiveVar
  on the instance
  @param [Object] instance, Blaze instance
###
activate = (instance) ->
  activeState = instance.active
  activeState.set not activeState.get()
  props =
    active: activeState.get()
  instance.data.survey.save(props)
    .then (survey) ->
      instance.activating.set true
      survey.setUserACL(activeState.get())
    .then ->
      instance.activating.set false
      instance.data.surveyState.set activeState.get()
      state = (if activeState.get() then "activated" else "deactivated")
      toastr.success("You have " + state + " your survey.")
    .fail (error) ->
      toastr.error error.message

module.exports = activate

###
  Toggles the activation state of a survey based on the 'active' ReactiveVar
  on the instance
  @param [Object] instance, Blaze instance
###
activate = (instance) ->
  activeState = instance.active
  activeState.set not activeState.get()
  props =
    active: activeState.get()
  instance.activating.set true
  instance.data.survey.save(props)
    .then (survey) ->
      instance.activating.set false
      instance.data.surveyState.set activeState.get()
      state = (if activeState.get() then "activated" else "deactivated")
      toastr.success("You have " + state + " your survey.")
    .fail (error) ->
      toastr.error error.message

module.exports = activate

Remove call to setACL method when survey is activated


Improve Table of Contents nested list handling


# # Kissmetrics Batch

class BatchKissmetricsClient
  @HOST: 'api.kissmetrics.com'

  constructor: (@queue) ->
    @_validate_queue @queue

  add: (timestamp, data) ->
    data.timestamp = timestamp
    @_transformData data

    @queue.add data

  get: ->
    @queue.get()

  process: ->
    queue = @get()

  _transformData: (data) ->
    data.identity = data._p
    delete data._p

    if data.type is 'record'
      data.event = data._n
      delete data._n

    if data.type is 'alias'
      data.alias = data._n
      delete data._n

  _validate_queue: ->
    for method in ['add', 'get']
      unless typeof @queue[method] is 'function'
        throw new Error "Missing method: #{required_method}"

module.exports = BatchKissmetricsClient

# # Kissmetrics Batch

class BatchKissmetricsClient
  @HOST: 'api.kissmetrics.com'

  constructor: (@queue) ->
    @_validate_queue @queue

  add: (timestamp, data) ->
    data.timestamp = timestamp
    @_transformData data

    @queue.add data

  get: ->
    @queue.get()

  process: ->
    queue = @get()

  _transformData: (data) ->
    data.identity = data._p
    delete data._p

    if data.type is 'record'
      data.event = data._n
      delete data._n

    if data.type is 'alias'
      data.alias = data._n
      delete data._n

    delete data.type

  _validate_queue: ->
    for method in ['add', 'get']
      unless typeof @queue[method] is 'function'
        throw new Error "Missing method: #{required_method}"

module.exports = BatchKissmetricsClient

Delete data.type once it's used to transform batch data


packages: [
  "atom-beautify"
  "atomic-chrome"
  "close-tags"
  "date"
  "file-icons"
  "git-history"
  "git-plus"
  "git-time-machine"
  "language-eco"
  "language-elixir"
  "language-haml"
  "language-rspec"
  "linter"
  "linter-write-good"
  "merge-conflicts"
  "package-sync"
  "rails-snippets"
  "rails-transporter"
  "ruby-test"
  "split-diff"
]

packages: [
  "atom-beautify"
  "atomic-chrome"
  "close-tags"
  "date"
  "file-icons"
  "git-history"
  "git-plus"
  "git-time-machine"
  "language-eco"
  "language-elixir"
  "language-haml"
  "language-rspec"
  "linter"
  "linter-write-good"
  "merge-conflicts"
  "package-sync"
  "pane-layout-plus"
  "rails-snippets"
  "rails-transporter"
  "ruby-test"
  "split-diff"
]

Add back Atom `pane-layout-plus` package

To get keyboard navigation among panes with CTRL + <number>


class window.UserStatisticsView extends Backbone.Marionette.ItemView
  className: 'statistics'
  template: 'users/statistics'

  initialize: ->
    @listenTo @model, 'change', @render

Update statistics when model changes

Update statistics when model changes


Template.reactiveTable.onRendered ->
  if @data.settings.keyboardFocus
    attrs = tabindex: '0'
    @$('tbody > tr').attr(attrs)

Template.reactiveTable.events
  'click tbody > tr': (event, instance) ->
    instance.$(event.currentTarget).blur()

Template.reactiveTable.onRendered ->
  if @data.settings.keyboardFocus
    @autorun =>
      if @context.ready.get()
        Meteor.defer =>
          @$('tbody > tr').attr(tabindex: '0')

Template.reactiveTable.events
  'click tbody > tr': (event, instance) ->
    instance.$(event.currentTarget).blur()

Add tabindex attr to table rows after table is loaded


###
# Invite is a named function that will replace /invite commands
# @param {Object} message - The message object
###

class Invite
	constructor: (command, params, item) ->
		if command isnt 'invite' or not Match.test params, String
			return

		username = params.trim()
		if username is ''
			return

		username = username.replace('@', '')

		user = Meteor.users.findOne({ username: username })
		currentUser = Meteor.users.findOne Meteor.userId()

		if not user?
			console.log 'notify user_doesnt_exist'
			RocketChat.Notifications.notifyUser Meteor.userId(), 'message', {
				_id: Random.id()
				rid: item.rid
				ts: new Date
				msg: TAPi18n.__('User_doesnt_exist', { postProcess: 'sprintf', sprintf: [ username ] }, currentUser.language)
			}
			return

		# cancel if the user is already in this room
		if RocketChat.models.Rooms.findOneByIdContainigUsername(item.rid, user.username)?
			RocketChat.Notifications.notifyUser Meteor.userId(), 'message', {
				_id: Random.id()
				rid: item.rid
				ts: new Date
				msg: TAPi18n.__('Username_is_already_in_here', { postProcess: 'sprintf', sprintf: [ username ] }, currentUser.language)
			}
			return

		Meteor.runAsUser user._id, ->
			Meteor.call 'joinRoom', item.rid

RocketChat.slashCommands.add 'invite', Invite

###
# Invite is a named function that will replace /invite commands
# @param {Object} message - The message object
###

class Invite
	constructor: (command, params, item) ->
		if command isnt 'invite' or not Match.test params, String
			return

		username = params.trim()
		if username is ''
			return

		username = username.replace('@', '')

		user = Meteor.users.findOne({ username: username })
		currentUser = Meteor.users.findOne Meteor.userId()

		if not user?
			console.log 'notify user_doesnt_exist'
			RocketChat.Notifications.notifyUser Meteor.userId(), 'message', {
				_id: Random.id()
				rid: item.rid
				ts: new Date
				msg: TAPi18n.__('User_doesnt_exist', { postProcess: 'sprintf', sprintf: [ username ] }, currentUser.language)
			}
			return

		# cancel if the user is already in this room
		if RocketChat.models.Rooms.findOneByIdContainigUsername(item.rid, user.username)?
			RocketChat.Notifications.notifyUser Meteor.userId(), 'message', {
				_id: Random.id()
				rid: item.rid
				ts: new Date
				msg: TAPi18n.__('Username_is_already_in_here', { postProcess: 'sprintf', sprintf: [ username ] }, currentUser.language)
			}
			return

		Meteor.call 'addUserToRoom',
			rid: item.rid
			username: user.username

RocketChat.slashCommands.add 'invite', Invite

Change /invite to use addUserToRoom instead joinRoom


_       = require 'lodash'
request = require 'request'
deepPluck = require 'deep-pluck'

isError = (errorCode) ->
  if errorCode? and errorCode.toString() isnt '0' then true else false

createErrorMsg = (body, codeKey, msgKey) ->
  [code, msg] = [deepPluck(body, codeKey)[0], deepPluck(body, msgKey)[0]]
  if isError(code) then "#{code} - #{msg}" else null

parseResponse = (body) ->
  body = JSON.parse body
  if body.StatusCode?
    [err, data] = [createErrorMsg(body, 'StatusCode', 'Message'), body.ResponseData]
  else
    [err, data] = [createErrorMsg(body, 'errorCode', 'errorText'), body]
  [err, data]

module.exports = (url, raw, deferred) ->
  request.get { url }, (err, response, body) ->
    unless err or raw
      [err, body] = parseResponse body
    if err then deferred.reject err
    else deferred.resolve body

_         = require 'lodash'
request   = require 'request'
keyfinder = require 'keyfinder'

isError = (errorCode) ->
  if errorCode? and errorCode.toString() isnt '0' then true else false

createErrorMsg = (body, codeKey, msgKey) ->
  [code, msg] = [keyfinder(body, codeKey)[0], keyfinder(body, msgKey)[0]]
  if isError(code) then "#{code} - #{msg}" else null

parseResponse = (body) ->
  body = JSON.parse body
  if body.StatusCode?
    [err, data] = [createErrorMsg(body, 'StatusCode', 'Message'), body.ResponseData]
  else
    [err, data] = [createErrorMsg(body, 'errorCode', 'errorText'), body]
  [err, data]

module.exports = (url, raw, deferred) ->
  request.get { url }, (err, response, body) ->
    unless err or raw
      [err, body] = parseResponse body
    if err then deferred.reject err
    else deferred.resolve body

Replace deep-pluck with keyfinder module


Spine = require 'spine'

class Toolbox extends Spine.Controller

  events:
    'click .tool' : 'selection'
    'click .remove-tools': 'clearDashboard'

  constructor: ->
    super

  render: =>
    @html require('views/toolbox')(@) if @el.html

  clearDashboard: (e) =>
    @trigger 'remove-all-tools'

  selection: (e) =>
    e.preventDefault()
    selected = $(e.currentTarget).attr('data-id')
    @trigger 'add-new-tool', selected

module.exports = Toolbox

Add spine require to toolbox to make it pass tests on linux


angular.module("grumbles")
  .controller "FormCtrl", ($http, Output) ->
    @submit = ->
      return unless @command

      split_command = @command.split " "

      verb         = split_command[0]
      entity       = split_command[1]
      other_entity = split_command[2]

      path  = "/#{verb}/#{entity}"
      path += "/#{other_entity}" if other_entity?

      $http.post(path)
        .success (data, status, headers, config) ->
          Output.add data

        .error (data, status, headers, config) ->
          console.error "Everything sucks ...", data

    this

angular.module("grumbles")
  .controller "FormCtrl", ($http, Output) ->
    @submit = ->
      return unless @command

      split_command = @command.split " "

      verb         = split_command[0]
      entity       = split_command[1]
      other_entity = split_command[2]

      path  = "/#{verb}/#{entity}"
      path += "/#{other_entity}" if other_entity?

      $http.post(path)
        .success (data, status, headers, config) =>
          Output.add data
          @command = ""

        .error (data, status, headers, config) ->
          console.error "Everything sucks ...", data

    this

Reset command input on successful commands


$ ->
  window.initPickers = ->
    base_options =
      format: "yyyy-mm-dd hh:ii"
      autoclose: true
      todayBtn: true
      viewSelect: 'month'
      minView: 'day'
      language: I18n.locale

    search_form_options = _.defaults({pickerPosition: "bottom-left datetimepicker-bottom-left-custom"}, base_options)
    search_form_options_gt = _.defaults({initialDate: new Date(new Date().setHours(0,0,0,0))}, search_form_options)
    search_form_options_lt = _.defaults({initialDate: new Date(new Date().setHours(23,59,59,999))}, search_form_options)
    $('#search_form input.datepicker[name*="_at_gteq]"]').datetimepicker search_form_options_gt
    $('#search_form input.datepicker[name*="_at_lteq]"]').datetimepicker search_form_options_lt

    date_picker_options = _.defaults({format: "yyyy-mm-dd", minView: 2}, base_options)
    $('.simple_form input.date_picker').datetimepicker date_picker_options

    $('.simple_form input.datetime_picker').datetimepicker base_options

    time_picker_options = _.defaults({format: "hh:ii"}, base_options)
    $('.simple_form input.time_picker').datetimepicker time_picker_options

  initPickers()

$ ->
  window.initPickers = ->
    base_options =
      format: "yyyy-mm-dd hh:ii"
      autoclose: true
      todayBtn: true
      viewSelect: 'month'
      minView: 'day'
      language: I18n.locale
      weekStart: 1

    search_form_options = _.defaults({pickerPosition: "bottom-left datetimepicker-bottom-left-custom"}, base_options)
    search_form_options_gt = _.defaults({initialDate: new Date(new Date().setHours(0,0,0,0))}, search_form_options)
    search_form_options_lt = _.defaults({initialDate: new Date(new Date().setHours(23,59,59,999))}, search_form_options)
    $('#search_form input.datepicker[name*="_at_gteq]"]').datetimepicker search_form_options_gt
    $('#search_form input.datepicker[name*="_at_lteq]"]').datetimepicker search_form_options_lt

    date_picker_options = _.defaults({format: "yyyy-mm-dd", minView: 2}, base_options)
    $('.simple_form input.date_picker').datetimepicker date_picker_options

    $('.simple_form input.datetime_picker').datetimepicker base_options

    time_picker_options = _.defaults({format: "hh:ii"}, base_options)
    $('.simple_form input.time_picker').datetimepicker time_picker_options

  initPickers()

Set datepicker start weekday to Monday

Set datepicker start weekday to Monday


scrollbarWidth = 0
FactlinkJailRoot.loaded_promise.then ->
  # Create the measurement nod; see http://davidwalsh.name/detect-scrollbar-width
  scrollDiv = document.createElement("div");
  $(scrollDiv).css(
    width: "100px"
    height: "100px"
    overflow: "scroll"
    position: "absolute"
    top: "-9999px"
  )
  document.body.appendChild(scrollDiv)

  scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth

  document.body.removeChild(scrollDiv)
  console.log 'scrollbar width: ', scrollbarWidth

FactlinkJailRoot.on 'modalOpened', ->
  document.documentElement.setAttribute('data-factlink-suppress-scrolling', '')
FactlinkJailRoot.on 'modalClosed', -> document.documentElement.removeAttribute('data-factlink-suppress-scrolling')

Implement a scrollbar width detector

Implement a scrollbar width detector


goog.provide 'app.react.pages.Home'

class app.react.pages.Home

  ###*
    @param {app.Routes} routes
    @param {app.songs.Store} songsStore
    @param {app.react.Touch} touch
    @constructor
  ###
  constructor: (routes, songsStore, touch) ->
    {div,ul,li} = React.DOM
    {a} = touch.scroll 'a'

    @create = React.createClass

      render: ->
        div className: 'home',
          ul null, songsStore.all().map (song, i) ->
            li key: i,
              a href: routes.mySong.createUrl(song),
                "#{song.name} [#{song.artist}]"
          a
            className: 'btn btn-default'
            href: routes.myNewSong.createUrl()
          , Home.MSG_ADD_NEW_SONG

  @MSG_ADD_NEW_SONG: goog.getMsg 'add new song'

goog.provide 'app.react.pages.Home'

class app.react.pages.Home

  ###*
    @param {app.Routes} routes
    @param {app.songs.Store} songsStore
    @param {app.react.Touch} touch
    @constructor
  ###
  constructor: (routes, songsStore, touch) ->
    {div,ul,li,br} = React.DOM
    {a,button} = touch.scroll 'a', 'button'

    @create = React.createClass

      render: ->
        div className: 'home',
          ul null, songsStore.all().map (song, i) ->
            li key: i,
              a href: routes.mySong.createUrl(song),
                "#{song.name} [#{song.artist}]"
          a
            className: 'btn btn-default'
            href: routes.myNewSong.createUrl()
          , Home.MSG_ADD_NEW_SONG
          button
            className: 'btn btn-default'
            href: routes.myNewSong.createUrl()
            onPointerUp: @onResetPointerUp
          , Home.MSG_RESET

      onResetPointerUp: (e) ->
        reset = confirm 'Do you really want reset everything?'
        return if !reset
        window.localStorage.removeItem 'songary::songs'
        window.location.reload true

  @MSG_ADD_NEW_SONG: goog.getMsg 'add new song'
  @MSG_RESET: goog.getMsg 'reset'

Add dev reset storage button.

Add dev reset storage button.


[
	{
		title: ".atom"
		icon: "atom-icon"
		paths: [
			"~/.atom"
		]
		devMode: true
	}
	{
		title: ".files"
		icon: "terminal-icon"
		paths: [
			"~/.files"
		]
		devMode: true
	}
	{
		title: "language-roff"
		icon: "manpage-icon"
		paths: [
			"~/Labs/language-roff"
		]
		devMode: true
	}
	{
		title: "file-icons"
		icon: "atom-icon"
		paths: [
			"~/Labs/file-icons"
		]
		devMode: true
	}
	{
		title: "Utils"
		icon: "icon-tools"
		paths: [
			"~/Labs/Utils"
		]
		devMode: true
	}
	{
		title: "YASR"
		icon: "emacs-icon"
		paths: [
			"~/Labs/YASR"
		]
		devMode: true
	}
]

[
	{
		title: ".atom"
		icon: "atom-icon"
		paths: [
			"~/.atom"
		]
		devMode: true
	}
	{
		title: ".files"
		icon: "terminal-icon"
		paths: [
			"~/.files"
		]
		devMode: true
	}
	{
		title: "language-roff"
		icon: "manpage-icon"
		paths: [
			"~/Labs/language-roff"
		]
		devMode: true
	}
	{
		title: "file-icons"
		icon: "atom-icon"
		paths: [
			"~/Labs/file-icons/atom"
			"~/Labs/file-icons/source"
		]
		devMode: true
	}
	{
		title: "Utils"
		icon: "icon-tools"
		paths: [
			"~/Labs/Utils"
		]
		devMode: true
	}
	{
		title: "YASR"
		icon: "emacs-icon"
		paths: [
			"~/Labs/YASR"
		]
		devMode: true
	}
]

Update project paths for File-Icons

Update project paths for File-Icons


#
# main.coffee
#
# Role: start the app
#
# Responsibility:
# * load top-level modules
# * initalize game based on query string
# * render and append to body of HTML
# * run tests if local
#

# Preamble
# TODO: server-side include underscore, underscore.string, jquery

{my} = require './my'
sys = require 'sys'

if not my.online
  rx = require './render/rx_mock'
else
  _.mixin(_.str.exports())
  if my.reactive_debug
    rx = require '../../reactive-coffee/src/reactive'
    console.log "WARNING: Loading local copy of reactive-coffee"
  else
    rx = require 'reactive-coffee'

# Dependencies

{game} = require './game'
{render} = require './render'

world = game(rx, {file: 'example', level: 0})

main = ->
  $('body').append(
    render(world) if my.online
  )

# Instantiate our main view
$(main)
# Run Tests
{test} = require('./test') if my.test
test(rx) if my.test

#
# main.coffee
#
# Role: start the app
#
# Responsibility:
# * load top-level modules
# * initalize game based on query string
# * render and append to body of HTML
# * run tests if local
#

# Preamble
# TODO: server-side include underscore, underscore.string, jquery

{my} = require './my'
sys = require 'sys'
queryString = require 'query-string'

if not my.online
  rx = require './render/rx_mock'
else
  _.mixin(_.str.exports())
  if my.reactive_debug
    rx = require '../../reactive-coffee/src/reactive'
    console.log "WARNING: Loading local copy of reactive-coffee"
  else
    rx = require 'reactive-coffee'

# Dependencies

{game} = require './game'
{render} = require './render'

default_query = {file: 'example', level: 0}
parsed_query = queryString.parse(location.search)

world = game rx, my.extend(default_query, parsed_query)

main = ->
  $('body').append(
    render(world) if my.online
  )

# Instantiate our main view
$(main)
# Run Tests
{test} = require('./test') if my.test
test(rx) if my.test

Use query string to select game

Use query string to select game


"use strict"

os = require 'os'

exports.info = (req, res, next) ->
  return res.status(403).end() if req.usr not in ['DNT', 'Pingdom']

  res.json 200,
    app:
      uptime: process.uptime()
      memory: process.memoryUsage()
    os:
      uptime: os.uptime()
      loadavg: os.loadavg()
      totalmem: os.totalmem()
      freemem: os.freemem()

exports.gc = (req, res, next) ->
  return res.status(403).end() if req.usr isnt 'DNT'

  global.gc() if typeof global.gc is 'function'
  res.end()

"use strict"

os = require 'os'

exports.info = (req, res, next) ->
  return res.status(403).end() if req.usr isnt 'DNT'

  res.json 200,
    app:
      uptime: process.uptime()
      memory: process.memoryUsage()
    os:
      uptime: os.uptime()
      loadavg: os.loadavg()
      totalmem: os.totalmem()
      freemem: os.freemem()

exports.gc = (req, res, next) ->
  return res.status(403).end() if req.usr isnt 'DNT'

  global.gc() if typeof global.gc is 'function'
  res.end()

Remove access for pingdom for normal sys info call


"*":
  editor:
    showIndentGuide: true
    fontFamily: "Inconsolata"
    invisibles: {}
    scrollPastEnd: true
    softWrap: true
    softWrapAtPreferredLineLength: true
    preferredLineLength: 100
  core:
    ignoredNames: [
      ".bundle"
      ".git"
      "log"
      "repositories"
      "tmp"
      "vendor"
    ]
    hideGitIgnoredFiles: true
    disabledPackages: [
      "background-tips"
      "exception-reporting"
      "metrics"
      "latexer"
    ]
  "spell-check":
    grammars: [
      "text.plain"
      "source.gfm"
      "text.git-commit"
    ]
  welcome:
    showOnStartup: false
  "release-notes":
    viewedVersion: "0.89.0"
  "autocomplete-bibtex":
    bibtex: [
      "/Users/briandanielak/Documents/bibtex/2015-10-21-zotero-library/2015-10-21-zotero-library.bib"
    ]
  "autocomplete-plus": {}
  Zen:
    softWrap: true
    typewriter: true
    minimap: true
    width: 140
  "markdown-table-formatter": {}
  latex: {}
  "make-runner": {}

Add make-runner package to Atom

Add make-runner package to Atom


Base = require './base.coffee'
Backbone = require 'backbone'
Backbone.LocalStorage = require 'backbone.localstorage'
Block = require '../models/block.coffee'

module.exports = class RecentConnections extends Backbone.Collection
  model: Block

  localStorage: new Backbone.LocalStorage RecentConnections

  shove: (model) ->
    @create(model.toJSON())

  unshove: (model) ->
    @sync('delete', @get model.id)

Base = require './base.coffee'
Backbone = require 'backbone'
Backbone.LocalStorage = require 'backbone.localstorage'
Block = require '../models/block.coffee'

module.exports = class RecentConnections extends Backbone.Collection
  model: Block

  localStorage: new Backbone.LocalStorage RecentConnections

  shove: (model) ->
    @create(model.toJSON())
    @unshift @pop()

  unshove: (model) ->
    @sync('delete', @get model.id)

Move created record to the top of the stack


define ['backbone', 'utils', 'backboneAnalytics'], (Backbone, Utils) ->
  Backbone.Router.extend

    initialize: () ->
      @route '', 'homeView'
      @route /([^\/]+)\/([^\/]+)\/([^\/]+)\/([^\/]+)\/([^\/]+)(?:\/([^\/]+))?(?:\/([^\/]+))?\/?/, 'routesView'

    homeView: () =>
      Reitti.Event.trigger 'home'

    routesView: (from, to, departArrive, datetime, transportTypes, routeIndex, legIndex) =>
      routeIndex = 0 if !routeIndex or routeIndex is ''
      Reitti.Event.trigger 'routes:find',
        from: Utils.decodeURIComponent(from)
        to: Utils.decodeURIComponent(to)
        date: if datetime is 'now' then 'now' else Utils.parseDateTimeFromMachines(datetime)
        arrivalOrDeparture: departArrive
        transportTypes: transportTypes.split(',')
        routeIndex: parseInt(routeIndex, 10)
        legIndex: if legIndex? then parseInt(legIndex, 10) else undefined

    navigateToRoutes: (params) ->
      path = [Utils.encodeURIComponent(params.from),
              Utils.encodeURIComponent(params.to),
              params.arrivalOrDeparture,
              if params.date is 'now' then 'now' else Utils.formatDateTimeForMachines(params.date),
              params.transportTypes.join(',')]
      if params.routeIndex?
        path.push params.routeIndex
        if params.legIndex? then path.push params.legIndex

      @navigate '/' + path.join('/'), trigger: true

define ['backbone', 'utils', 'backboneAnalytics'], (Backbone, Utils) ->
  Backbone.Router.extend

    initialize: () ->
      @route '', 'homeView'
      @route /([^\/]+)\/([^\/]+)\/([^\/]+)\/([^\/]+)\/([^\/]+)(?:\/([^\/]+))?(?:\/([^\/]+))?\/?/, 'routesView'

    homeView: () =>
      Reitti.Event.trigger 'home'

    routesView: (from, to, departArrive, datetime, transportTypes, routeIndex, legIndex) =>
      routeIndex = 0 if !routeIndex or routeIndex is ''
      Reitti.Event.trigger 'routes:find',
        from: Utils.decodeURIComponent(from)
        to: Utils.decodeURIComponent(to)
        date: if datetime is 'now' then 'now' else Utils.parseDateTimeFromMachines(datetime)
        arrivalOrDeparture: departArrive
        transportTypes: transportTypes.split(',')
        routeIndex: parseInt(routeIndex, 10)
        legIndex: if legIndex? and legIndex.length then parseInt(legIndex, 10) else undefined

    navigateToRoutes: (params) ->
      path = [Utils.encodeURIComponent(params.from),
              Utils.encodeURIComponent(params.to),
              params.arrivalOrDeparture,
              if params.date is 'now' then 'now' else Utils.formatDateTimeForMachines(params.date),
              params.transportTypes.join(',')]
      if params.routeIndex?
        path.push params.routeIndex
        if params.legIndex? then path.push params.legIndex

      @navigate '/' + path.join('/'), trigger: true

Check that legIndex isn't empty.

Check that legIndex isn't empty.


module.exports = (grunt) ->
  grunt.initConfig
    pkg: grunt.file.readJSON('package.json')

    coffee:
      glob_to_multiple:
        expand: true
        cwd: 'src'
        src: ['*.coffee']
        dest: 'lib'
        ext: '.js'

    coffeelint:
      options:
        max_line_length:
          level: 'ignore'

      src: ['src/**/*.coffee']
      test: ['spec/**/*.coffee']
      gruntfile: ['Gruntfile.coffee']

    shell:
      rebuild:
        command: 'npm build .'
        options:
          stdout: true
          stderr: true
          failOnError: true

      test:
        command: 'node --harmony_collections node_modules/.bin/jasmine-focused --coffee --captureExceptions --forceexit spec'
        options:
          stdout: true
          stderr: true
          failOnError: true

  grunt.loadNpmTasks('grunt-contrib-coffee')
  grunt.loadNpmTasks('grunt-shell')
  grunt.loadNpmTasks('grunt-coffeelint')
  grunt.registerTask 'clean', ->
    rm = require('rimraf').sync
    rm('lib')
    rm('build')
  grunt.registerTask('lint', ['coffeelint'])
  grunt.registerTask('default', ['lint', 'coffee', 'shell:rebuild'])
  grunt.registerTask('test', ['default', 'shell:test'])
  grunt.registerTask('prepublish', ['clean', 'coffee', 'lint', 'shell:rebuild'])

module.exports = (grunt) ->
  grunt.initConfig
    pkg: grunt.file.readJSON('package.json')

    coffee:
      glob_to_multiple:
        expand: true
        cwd: 'src'
        src: ['*.coffee']
        dest: 'lib'
        ext: '.js'

    coffeelint:
      options:
        max_line_length:
          level: 'ignore'

      src: ['src/**/*.coffee']
      test: ['spec/**/*.coffee']
      gruntfile: ['Gruntfile.coffee']

    shell:
      rebuild:
        command: 'npm build .'
        options:
          stdout: true
          stderr: true
          failOnError: true

      test:
        command: 'node node_modules/jasmine-focused/bin/jasmine-focused --coffee --captureExceptions --forceexit spec'
        options:
          stdout: true
          stderr: true
          failOnError: true

  grunt.loadNpmTasks('grunt-contrib-coffee')
  grunt.loadNpmTasks('grunt-shell')
  grunt.loadNpmTasks('grunt-coffeelint')
  grunt.registerTask 'clean', ->
    rm = require('rimraf').sync
    rm('lib')
    rm('build')
  grunt.registerTask('lint', ['coffeelint'])
  grunt.registerTask('default', ['lint', 'coffee', 'shell:rebuild'])
  grunt.registerTask('test', ['default', 'shell:test'])
  grunt.registerTask('prepublish', ['clean', 'coffee', 'lint', 'shell:rebuild'])

Tweak test command for Windows

Tweak test command for Windows


# Hay que bindear tanto cuando se carga la página como cuando turbolinks la
# pide (el page:change)
bindearTodo = ->
  # mejora el estilo default de los file uploaders
  $("form.carta :file").filestyle(
    buttonText: 'Subir',
    classText: 'span9 filestyle',
    classButton: 'span3 filestyle'
  )

$(document)
  .on 'page:change', ->
    bindearTodo()

# TODO bindear 36 = inicio y 35 = fin para primera y última carta
# TODO testear que estén los tags
$(document)
  .on 'keydown', (tecla) ->
    Turbolinks.visit((
      switch tecla.which
        when 37 then $('#anterior')
        when 39 then $('#siguiente')
      ).attr('href'))

jQuery ->
  bindearTodo()

# Hay que bindear tanto cuando se carga la página como cuando turbolinks la
# pide (el page:change)
bindearTodo = ->
  # mejora el estilo default de los file uploaders
  $("form.carta :file").filestyle(
    buttonText: 'Subir',
    classText: 'span9 filestyle',
    classButton: 'span3 filestyle'
  )

$(document)
  .on 'page:change', ->
    bindearTodo()

# TODO bindear 36 = inicio y 35 = fin para primera y última carta
# TODO testear que estén los tags
$(document)
  .on 'keydown', (tecla) ->
    Turbolinks.visit((
      unless tecla.altKey
        switch tecla.which
          when 37 then $('#anterior')
          when 39 then $('#siguiente')
        ).attr('href'))

jQuery ->
  bindearTodo()

Fix conflicto con alt + cursor

Fix conflicto con alt + cursor


# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

roundUpBy = (value, round_to) ->
  return round_to * Math.ceil(value / round_to)

$ ->
  animateMetric = $(".metric-box strong").each (index) ->
    $this = $(this)
    starting_point = 0
    $target_count = parseInt($this.text().replace(/\,/g, ''))

    # set the test to 0
    $this.counter = starting_point

    tween = createjs.Tween.get($this).to( {counter: $target_count}, (1200 + index * 1000) , createjs.Ease.quintOut)

    tween.addEventListener 'change', (event) ->
      # if the number is under 90 of the target, increment number by thousands
      if $this.counter < $target_count * 0.7
        $this.counter = roundUpBy($this.counter, 1000)
      else if $this.counter < $target_count * 0.8
        $this.counter = roundUpBy($this.counter, 100)
      else if $this.counter < $target_count * 0.99
        $this.counter = roundUpBy($this.counter, 10)
      $this.text(Math.round($this.counter).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","))
      return

# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

roundUpBy = (value, round_to) ->
  return round_to * Math.ceil(value / round_to)

$ ->
  animateMetric = $(".metric-box strong").each (index) ->
    $this = $(this)
    starting_point = 0
    $target_count = parseInt($this.text().replace(/\,/g, ''))

    # set the test to 0
    $this.counter = starting_point

    tween = createjs.Tween.get($this).to( {counter: $target_count}, (1200 + index * 800) , createjs.Ease.quintOut)

    tween.addEventListener 'change', (event) ->
      # if the number is under 90 of the target, increment number by thousands
      if $this.counter < $target_count * 0.7
        $this.counter = roundUpBy($this.counter, 1000)
      else if $this.counter < $target_count * 0.8
        $this.counter = roundUpBy($this.counter, 100)
      else if $this.counter < $target_count * 0.99
        $this.counter = roundUpBy($this.counter, 10)
      $this.text(Math.round($this.counter).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","))
      return

Make the stepped animation finish closer together


fs = require 'fs'
path = require 'path'
yeoman = require 'yeoman-generator'
semver = require 'semver'

module.exports = class SlideGenerator extends yeoman.generators.NamedBase

    files: ->
        appPath = process.cwd()
        fullPath = path.join appPath, '/slides/list.json'
        list = require fullPath

        if @options.markdown
            @filename = "#{@_.slugify(@name)}.md"
            @log.info 'Using Markdown.'

            if @options.notes
                @template 'slide-withnotes.md', "slides/#{@filename}"
            else
                @template 'slide.md', "slides/#{@filename}"

        else
            @filename = "#{@_.slugify(@name)}.html"
            @log.info 'Using HTML.'

            if @options.notes
                @template 'slide-withnotes.html', "slides/#{@filename}"
            else
                @template 'slide.html', "slides/#{@filename}"

        if @options.markdown and @options.attributes
            list.push filename: @filename, attr: 'data-background': '#ff0000'
        else
            list.push @filename

        fs.writeFileSync fullPath, JSON.stringify list, null, 4

fs = require 'fs'
path = require 'path'
yeoman = require 'yeoman-generator'
semver = require 'semver'

module.exports = class SlideGenerator extends yeoman.generators.NamedBase
    constructor: (args, options, config) ->
        super args, options, config
        @option 'notes',
            desc: 'Include speaker notes'
            type: Boolean
            default: false
        @option 'markdown',
            desc: 'Use markdown'
            type: Boolean
            default: false
        @option 'attributes',
            desc: 'Include (data-)attributes on markdown section. This only works combinded with --markdown.'
            type: Boolean
            default: false

    files: ->
        appPath = process.cwd()
        fullPath = path.join appPath, '/slides/list.json'
        list = require fullPath

        if @options.markdown
            @filename = "#{@_.slugify(@name)}.md"
            @log.info 'Using Markdown.'

            if @options.notes
                @template 'slide-withnotes.md', "slides/#{@filename}"
            else
                @template 'slide.md', "slides/#{@filename}"

        else
            @filename = "#{@_.slugify(@name)}.html"
            @log.info 'Using HTML.'

            if @options.notes
                @template 'slide-withnotes.html', "slides/#{@filename}"
            else
                @template 'slide.html', "slides/#{@filename}"

        if @options.markdown and @options.attributes
            list.push filename: @filename, attr: 'data-background': '#ff0000'
        else
            list.push @filename

        fs.writeFileSync fullPath, JSON.stringify list, null, 4

Declare options for --help usage.

Declare options for --help usage.


'.platform-darwin .editor':
  'ctrl-shift-u': 'encoding-selector:show'

'.platform-win32 .editor':
  'ctrl-shift-u': 'encoding-selector:show'

'.platform-linux .editor':
  'ctrl-u': 'encoding-selector:show'

'.platform-darwin atom-text-editor':
  'ctrl-shift-u': 'encoding-selector:show'

'.platform-win32 atom-text-editor':
  'ctrl-shift-u': 'encoding-selector:show'

'.platform-linux atom-text-editor':
  'ctrl-u': 'encoding-selector:show'

Fix deprecated selectors in keymap

Fix deprecated selectors in keymap


"*":
  "atom-ctags": {}
  "autocomplete-plus":
    enableAutoActivation: false
  core:
    audioBeep: false
    disabledPackages: [
      "exception-reporting"
    ]
    ignoredNames: [
      ".bundle"
      ".git"
      "log"
      "repositories"
      "tmp"
    ]
    themes: [
      "atom-dark-ui"
      "solarized-dark-syntax"
    ]
  editor:
    fontFamily: "Menlo"
    invisibles: {}
    scrollPastEnd: true
    showIndentGuide: true
    softWrapAtPreferredLineLength: true
  "git-diff-details":
    closeAfterCopy: true
  "git-history":
    showDiff: false
  "git-plus":
    openInPane: false
    verboseCommit: true
    wordDiff: false
  "merge-conflicts": {}
  "ruby-test":
    rspecFileCommand: "spring rspec --tty {relative_path}"
    rspecSingleCommand: "spring rspec --tty {relative_path}:{line_number}"
    shell: "zsh"
  welcome:
    showOnStartup: false

"*":
  "atom-ctags": {}
  "autocomplete-plus":
    enableAutoActivation: false
  core:
    audioBeep: false
    disabledPackages: [
      "exception-reporting"
    ]
    ignoredNames: [
      ".bundle"
      ".git"
      "log"
      "repositories"
      "tmp"
    ]
    themes: [
      "atom-dark-ui"
      "solarized-dark-syntax"
    ]
  editor:
    fontFamily: "Menlo"
    invisibles: {}
    scrollPastEnd: true
    showIndentGuide: true
    softWrapAtPreferredLineLength: true
  "git-diff-details":
    closeAfterCopy: true
  "git-history":
    showDiff: false
  "git-plus":
    openInPane: false
    verboseCommit: true
    wordDiff: false
  "merge-conflicts": {}
  "ruby-test":
    rspecFileCommand: "spring rspec --tty {relative_path}"
    rspecSingleCommand: "spring rspec --tty {relative_path}:{line_number}"
    shell: "zsh"
    specFramework: "rspec"
  welcome:
    showOnStartup: false

Add Atom ruby-test preferred spec framework


Rubocop = require '../../lib/linter/rubocop'

describe 'Rubocop', ->
  rubocop = null

  beforeEach ->
    rubocop = new Rubocop('/path/to/target.rb')

  describe 'buildCommand', ->
    originalRubocopPath = atom.config.get('atom-lint.rubocop.path')

    afterEach ->
      atom.config.set('atom-lint.rubocop.path', originalRubocopPath)

    describe 'when the target file path is "/path/to/target.rb"', ->
      describe 'and config "atom-lint.rubocop.path" is "/path/to/rubocop"', ->
        it 'returns ["/path/to/rubocop", "--format", "json", "/path/to/target.rb"]', ->
          atom.config.set('atom-lint.rubocop.path', '/path/to/rubocop')
          expect(rubocop.buildCommand())
            .toEqual(['/path/to/rubocop', '--format', 'json', '/path/to/target.rb'])

      describe 'and config "atom-lint.rubocop.path" is not set', ->
        it 'returns ["rubocop", "--format", "json", "/path/to/target.rb"]', ->
          atom.config.set('atom-lint.rubocop.path', null)
          expect(rubocop.buildCommand())
            .toEqual(['rubocop', '--format', 'json', '/path/to/target.rb'])

Rubocop = require '../../lib/linter/rubocop'

describe 'Rubocop', ->
  rubocop = null

  beforeEach ->
    rubocop = new Rubocop('/path/to/target.rb')

  describe 'buildCommand', ->
    originalRubocopPath = atom.config.get('atom-lint.rubocop.path')

    afterEach ->
      atom.config.set('atom-lint.rubocop.path', originalRubocopPath)

    describe 'when the target file path is "/path/to/target.rb"', ->
      describe 'and config "atom-lint.rubocop.path" is "/path/to/rubocop"', ->
        it 'returns ["/path/to/rubocop", "--format", "json", "/path/to/target.rb"]', ->
          atom.config.set('atom-lint.rubocop.path', '/path/to/rubocop')
          expect(rubocop.buildCommand())
            .toEqual(['/path/to/rubocop', '--force-exclusion', '--format', 'json', '/path/to/target.rb'])

      describe 'and config "atom-lint.rubocop.path" is not set', ->
        it 'returns ["rubocop", "--format", "json", "/path/to/target.rb"]', ->
          atom.config.set('atom-lint.rubocop.path', null)
          expect(rubocop.buildCommand())
            .toEqual(['rubocop', '--force-exclusion', '--format', 'json', '/path/to/target.rb'])

Fix spec file to enable --force-exclusion option in RuboCop


{fork} = require('child_process')
prerenderUrl = 'http://127.0.0.1:' + (process.env.PORT or 3000)

module.exports = (app) ->
  # Start up prerender server
  child = fork('server/prerender/server')
  process.on 'exit', ->
    child.kill()

  # Set up Prerender middleware and link to server
  middleware = require('prerender-node')
  middleware.set('prerenderServiceUrl', prerenderUrl)
  app.use(middleware)

{fork} = require('child_process')
prerenderUrl = 'http://127.0.0.1:' + (process.env.PORT or 3000)

module.exports = (app) ->
  # Check if Prerender is available
  try
    require.resolve('prerender')
    require.resolve('prerender-node')
  catch
    return

  # Start up prerender server
  child = fork('server/prerender/server')
  process.on 'exit', ->
    child.kill()

  # Set up Prerender middleware and link to server
  middleware = require('prerender-node')
  middleware.set('prerenderServiceUrl', prerenderUrl)
  app.use(middleware)

Check if pretender is available

Check if pretender is available


_ = require('lodash')
Promise = require('bluebird')

IS_BROWSER = window?

if (IS_BROWSER)
	# The browser mock assumes global fetch prototypes exist
	realFetchModule = require('fetch-ponyfill')({ Promise })
	global.Promise = Promise
	global.Headers = realFetchModule.Headers
	global.Request = realFetchModule.Request
	global.Response = realFetchModule.Response

fetchMock = require('fetch-mock').sandbox(Promise)
fetchMock.patch = (matcher, response, options) ->
	options = _.assign({}, options, { method: 'PATCH' })
	@mock(matcher, response, options)

utils = require('../lib/utils')
utils.fetch = fetchMock.fetchMock

getToken = require('resin-token')
getRequest = require('../lib/request')

dataDirectory = null
if not IS_BROWSER
	settings = require('resin-settings-client')
	dataDirectory = settings.get('dataDirectory')

getCustomRequest = (opts) ->
	opts = _.assign({}, opts, { dataDirectory, debug: false, isBrowser: IS_BROWSER })
	getRequest(opts)

module.exports = ->
	IS_BROWSER: IS_BROWSER
	fetchMock: fetchMock
	token: getToken({ dataDirectory })
	request: getCustomRequest()
	getCustomRequest: getCustomRequest

_ = require('lodash')
Promise = require('bluebird')

IS_BROWSER = window?

if (IS_BROWSER)
	# The browser mock assumes global fetch prototypes exist
	realFetchModule = require('fetch-ponyfill')({ Promise })
	global.Promise = Promise
	global.Headers = realFetchModule.Headers
	global.Request = realFetchModule.Request
	global.Response = realFetchModule.Response

fetchMock = require('fetch-mock').sandbox(Promise)
fetchMock.fetchMock.Promise = Promise
fetchMock.patch = (matcher, response, options) ->
	options = _.assign({}, options, { method: 'PATCH' })
	@mock(matcher, response, options)

utils = require('../lib/utils')
utils.fetch = fetchMock.fetchMock

getToken = require('resin-token')
getRequest = require('../lib/request')

dataDirectory = null
if not IS_BROWSER
	settings = require('resin-settings-client')
	dataDirectory = settings.get('dataDirectory')

getCustomRequest = (opts) ->
	opts = _.assign({}, opts, { dataDirectory, debug: false, isBrowser: IS_BROWSER })
	getRequest(opts)

module.exports = ->
	IS_BROWSER: IS_BROWSER
	fetchMock: fetchMock
	token: getToken({ dataDirectory })
	request: getCustomRequest()
	getCustomRequest: getCustomRequest

Fix bug in fetch-mock that breaks custom Promise usage


passport = require 'passport'
debug = require('debug')('meshblu-google-authenticator:routes')
url = require 'url'

class Router
  constructor: (@app) ->

  register: =>
    @app.get  '/', (request, response) => response.status(200).send status: 'online'

    @app.get '/login', @storeCallbackUrl, passport.authenticate 'google', scope: ['profile', 'email']

    @app.get '/oauthcallback', passport.authenticate('google', { failureRedirect: '/login' }), @afterPassportLogin

  afterPassportLogin: (request, response) =>
    {callbackUrl} = request.cookies
    delete request.cookies.callbackUrl
    return response.status(401).send(new Error 'Invalid User') unless request.user
    return response.status(201).send(request.user) unless callbackUrl?
    uriParams = url.parse callbackUrl
    uriParams.query ?= {}
    uriParams.query.uuid = request.user.uuid
    uriParams.query.token = request.user.token
    return response.redirect(url.format uriParams)

  defaultRoute: (request, response) =>
    response.render 'index'

  storeCallbackUrl: (request, response, next) =>
    if request.query.callbackUrl?
      request.cookies.callbackUrl = request.query.callbackUrl
    else
      delete request.cookies.callbackUrl
    next()

module.exports = Router

passport = require 'passport'
debug = require('debug')('meshblu-google-authenticator:routes')
url = require 'url'

class Router
  constructor: (@app) ->

  register: =>
    @app.get  '/', (request, response) => response.status(200).send status: 'online'

    @app.get '/login', @storeCallbackUrl, passport.authenticate 'google', scope: ['profile', 'email']

    @app.get '/oauthcallback', passport.authenticate('google', { failureRedirect: '/login' }), @afterPassportLogin

  afterPassportLogin: (request, response) =>
    {callbackUrl} = request.cookies
    response.cookie 'callbackUrl', null, maxAge: -1
    return response.status(401).send(new Error 'Invalid User') unless request.user
    return response.status(201).send(request.user) unless callbackUrl?
    uriParams = url.parse callbackUrl
    uriParams.query ?= {}
    uriParams.query.uuid = request.user.uuid
    uriParams.query.token = request.user.token
    return response.redirect(url.format uriParams)

  defaultRoute: (request, response) =>
    response.render 'index'

  storeCallbackUrl: (request, response, next) =>
    if request.query.callbackUrl?
      response.cookie 'callbackUrl', request.query.callbackUrl, maxAge: 60 * 60 * 1000
    else
      response.cookie 'callbackUrl', null, maxAge: -1
    next()

module.exports = Router

Use the undocumented cookies api

Use the undocumented cookies api


MergeConflictsView = require './merge-conflicts-view'
SideView = require './side-view'
NavigationView = require './navigation-view'
Conflict = require './conflict'

module.exports =

  activate: (state) ->
    atom.workspaceView.command "merge-conflicts:detect", ->
      MergeConflictsView.detect()

    atom.workspaceView.eachEditorView (view) ->
      if view.attached and view.getPane()?
        for c in Conflict.all(view.getEditor())
          oursView = new SideView(c.ours)
          oursView.installIn view

          theirsView = new SideView(c.theirs)
          theirsView.installIn view

          navView = new NavigationView(c)
          navView.installIn view

  deactivate: ->

  serialize: ->

MergeConflictsView = require './merge-conflicts-view'
SideView = require './side-view'
NavigationView = require './navigation-view'
Conflict = require './conflict'

module.exports =

  activate: (state) ->
    atom.workspaceView.command "merge-conflicts:detect", ->
      MergeConflictsView.detect()

    atom.workspaceView.eachEditorView (view) ->
      if view.attached and view.getPane()?
        for c in Conflict.all(view.getEditor())
          oursView = new SideView(c.ours, view)
          theirsView = new SideView(c.theirs, view)
          navView = new NavigationView(c, view)

  deactivate: ->

  serialize: ->

Use the new CoveringView API in MergeConflict.


$ ->
  $('.reminder_active').on 'change', ->
    $('.reminder_days_before').prop "disabled", !@.checked

  select2_options =
    theme: 'bootstrap'
    placeholder: 'Selecione os usuários'
    maximumSelectionLength: 7

  $('.select_users').select2 select2_options

  $('.js-account').click (e)->
    path = '/main_account.json'
    account_id = $(@).data('account-id')

    $.getJSON(path, { account_id: account_id })
      .done (data)->
        console.log data

$ ->
  $('.reminder_active').on 'change', ->
    $('.reminder_days_before').prop "disabled", !@.checked

  $('.public').on 'change', ->
    $('.select_users').prop "disabled", !@.checked

  select2_options =
    theme: 'bootstrap'
    placeholder: 'Selecione os usuários'
    maximumSelectionLength: 7

  $('.select_users').select2 select2_options

  $('.js-account').click (e)->
    path = '/main_account.json'
    account_id = $(@).data('account-id')

    $.getJSON(path, { account_id: account_id })
      .done (data)->
        console.log data

Add disable select_users when public is false


kd = require 'kd'
KDCustomHTMLView = kd.CustomHTMLView
KodingSwitch = require 'app/commonviews/kodingswitch'
CustomLinkView = require 'app/customlinkview'
module.exports = class IDEChatHeadWatchItemView extends KDCustomHTMLView

  constructor: (options = {}, data) ->

    options.partial ?= 'Watch'

    super options, data

    { delegate, isWatching } = @getOptions()

    @addSubView new KodingSwitch
      cssClass     : 'tiny'
      defaultValue : isWatching
      callback     : delegate.bound 'setWatchState'

    @addSubView new CustomLinkView
      title        : ''
      cssClass     : 'info'
      href         : 'http://learn.koding.com/guides/collaboration/#what-does-quot-watch-quot-mode-mean-'
      target       : '_blank'

Delete white spaces at end of file

Delete white spaces at end of file


'use strict'

@start = (limit) ->
  window.startDate = new Date().getTime()
  window.elapsedSeconds = 0
  window.seconds = 0
  window.minutes = 0
  window.limit = limit
  window.timerID = setInterval(timeCounter, 1000)
  return

@stop = ->
  clearInterval timerID
  return

timeCounter = ->
  if elapsedSeconds >= limit
    stop()
    return

  time = new Date().getTime() - startDate

  window.elapsedSeconds = parseInt(Math.floor(time / 100) / 10)

  allTheTime = elapsedSeconds
  minutes = parseInt(allTheTime/60)
  allTheTime -= minutes * 60
  seconds = parseInt(allTheTime)

  document.getElementById('seconds').innerHTML = seconds
  document.getElementById('minutes').innerHTML = minutes

  return

'use strict'

@start = (limit) ->
  window.startDate = new Date().getTime()
  window.elapsedSeconds = 0
  window.seconds = 0
  window.minutes = 0
  window.limit = limit
  window.timerID = setInterval(timeCounter, 1000)
  return

@stop = ->
  clearInterval timerID
  return

timeCounter = ->
  if elapsedSeconds >= limit
    stop()
    return

  time = new Date().getTime() - startDate

  window.elapsedSeconds = parseInt(Math.floor(time / 100) / 10)

  allTheTime = elapsedSeconds
  minutes = parseInt(allTheTime/60)
  allTheTime -= minutes * 60
  seconds = parseInt(allTheTime)

  minutes = '0' + minutes if minutes < 10
  seconds = '0' + seconds if seconds < 10

  document.getElementById('seconds').innerHTML = seconds
  document.getElementById('minutes').innerHTML = minutes

  return

Adjust minutes and seconds counters to have a zero on the left when they are less than 10.


jQuery ->
  ($ '#account-next-step').on 'click', (e) ->
    do e.preventDefault
    do ($ '#account-form').submit

  if ($ '#user_qae_info_source_other').length
    toggleOther = (checkbox) ->
      if checkbox.is(':checked')
        ($ '#qae_info_source_other').removeClass('visuallyhidden')
      else
        ($ '#qae_info_source_other').addClass('visuallyhidden')

    toggleOther($ '#user_qae_info_source_other')

    ($ '#user_qae_info_source_other').on 'change', ->
      toggleOther($ @)

jQuery ->
  ($ '#account-next-step').on 'click', (e) ->
    do e.preventDefault
    do ($ '#account-form').submit

  if $('#user_qae_info_source').size() > 0
    toggleOther = (select) ->
      if select.val() == 'other'
        ($ '#qae_info_source_other').removeClass('visuallyhidden')
      else
        ($ '#qae_info_source_other').addClass('visuallyhidden')

    toggleOther($ '#user_qae_info_source')

    ($ '#user_qae_info_source').on 'change', ->
      toggleOther($ @)

Fix "How did you hear about The Queen's Awards?" conditional JS


class window.DP.Realtime
  init: ->
    if typeof Pusher == 'function'
      @pusher = new Pusher(DP.PUSHER_KEY)
      @channel = @pusher.subscribe DP.Round.url
      @channel.bind('new:charge', _.bind(@newCharge, this))
      console.log(["Subscribing to real-time", @pusher, @channel])

  newCharge: ->
    console.log(["REAL-TIME: New Charge", arguments])
    @reloadDonations()

  reloadDonations: (data)->
    if !data
      $.get('/round_status/' + DP.Round.url, {}, @renderDonations)
    else
      @renderDonations(data)

  renderDonations: (data)->
    console.log(["Round status", data])
    $('.donations').html(data.donations_template)
    $('.payment-info').html(data.payment_info_template)
    @secondsLeft = data.seconds_left
    if data.closed
      window.location.href = window.location.href

  renderTimer: ->
    if @secondsLeft <= 0
      window.location.href = window.location.href

    $timer = $('.timer')
    minutes = Math.floor(@secondsLeft / 60)
    seconds = @secondsLeft % 60
    if seconds <= 9
      seconds = "0" + seconds
    $timer.html(minutes + ":" + seconds + " time left")
    @secondsLeft -= 1

class window.DP.Realtime
  constructor: ->
    if typeof Pusher == 'function'
      @pusher = new Pusher(DP.PUSHER_KEY)
      @channel = @pusher.subscribe DP.Round.url
      @channel.bind('new:charge', _.bind(@newCharge, this))
      console.log(["Subscribing to real-time", @pusher, @channel])

  newCharge: ->
    console.log(["REAL-TIME: New Charge", arguments])
    @reloadDonations()

  reloadDonations: (data)->
    if !data
      $.get('/round_status/' + DP.Round.url, {}, @renderDonations)
    else
      @renderDonations(data)

  renderDonations: (data)->
    console.log(["Round status", data])
    $('.donations').html(data.donations_template)
    $('.payment-info').html(data.payment_info_template)
    @secondsLeft = data.seconds_left
    if data.closed
      window.location.href = window.location.href

  renderTimer: ->
    if @secondsLeft <= 0
      window.location.href = window.location.href

    $timer = $('.timer')
    minutes = Math.floor(@secondsLeft / 60)
    seconds = @secondsLeft % 60
    if seconds <= 9
      seconds = "0" + seconds
    $timer.html(minutes + ":" + seconds + " time left")
    @secondsLeft -= 1

Use constructor instead of init

Use constructor instead of init


$ ->
  saveSequence = (sequence) ->
    if sequence?
      localStorage.setItem('sequence', sequence)
    true

  loadSequence = ->
    localStorage.getItem('sequence')

  input    = $("input#fragment")
  button   = $("#methods button")
  sequence = loadSequence()

  if sequence?
    input.val(sequence)

    unless window.location.search
      button.click()

  button.on "click", ->
    val = input.val()
    saveSequence(val)

  false

$ ->
  saveSequence = (sequence) ->
    if sequence?
      localStorage.setItem('sequence', sequence)
    true

  loadSequence = ->
    localStorage.getItem('sequence')

  button = $("#methods button")
  input  = $("input#fragment")

  $(window).on "load", (e) ->
    search = window.location.search

    if search
      val = input.val()
      saveSequence(val)
    else
      sequence = loadSequence()

      if sequence?
        input.val(sequence)
        button.click()

  button.on "click", ->
    val = input.val()
    saveSequence(val)

  false

Save sequence if location.search exists

Save sequence if location.search exists

ブラウザで直接アドレス(URL)を指定した場合も、
次からはその画面を開けるようにするために、location.search を見て検索条件を保持するようにした


child_process = require 'child_process'

module.exports =
	activate: (state) ->
		atom.commands.add 'atom-workspace', 'wp-phptidy:run': => @run()

	run: ->
		editor = atom.workspace.getActivePaneItem()
		editor.save()

		file = editor?.buffer.file
		filepath = file?.path

		if filepath.length
		  child_process.exec(__dirname + '/../vendor/wp-phptidy.php replace ' + filepath)

child_process = require 'child_process'

module.exports =
	activate: (state) ->
		atom.commands.add 'atom-workspace', 'wp-phptidy:run': => @run()

	run: ->
		editor = atom.workspace.getActivePaneItem()
		editor.save()

		file = editor?.buffer.file
		filepath = file?.path

		if filepath.length
		  child_process.exec('php ' + __dirname + '/../vendor/wp-phptidy.php replace ' + filepath)

Fix for executing PHP on Windows

Fix for executing PHP on Windows


Crafty.c 'Mine',
  init: ->
    @requires 'Color, Enemy'

  mine: (attr = {}) ->
    @attr _.defaults(attr,
      w: 25, h: 25, health: 200)
    @origin 'center'
    @color '#555555'

    @enemy()
    this

Crafty.c 'Mine',
  init: ->
    @requires 'Color, Enemy'

  mine: (attr = {}) ->
    @attr _.defaults(attr,
      w: 25, h: 25, health: 200)
    @origin 'center'
    @color '#111111'

    @enemy()
    this

Increase contrast of mine agains background


window.Game = class Game
  constructor: (grid, moves, status, winner) ->
    console.log 'Game ctor'
    @gameBoard = new GameBoard($('#canvas'), $('#canvasOverlay'), {
      grid: grid,
      moves: moves,
      winner: winner,
      afterMoveAnimation: $.proxy(this.afterMove, this)
    })
    @setFinished(winner) if status == 'finished'

  afterMove: ->
    gameBoard = @gameBoard
    console.log 'afterMove'
    if gameBoard.nextColour == 1
      gameBoard.activate false
      console.log gameBoard.grid
      game = this
      $.ajax {
        dataType: "json",
        type: "POST",
        contentType: "application/json",
        data: JSON.stringify { grid: gameBoard.grid, moves: gameBoard.moves }
        beforeSend: (xhr) -> xhr.setRequestHeader("X-Http-Method-Override", "PUT")
        success: (result) ->
          console.log result
          new_move = result.moves[result.moves.length - 1]
          if result.status == 'finished'
            game.setFinished(result.winner)
          else
            gameBoard.move new_move[1]
            gameBoard.activate true
      }

  setFinished: (winner) ->
    if winner
      $('.messagePanel').text "Game over, #{winner} won"
    else
      $('.messagePanel').text "Game over, drawn"
    @gameBoard.activate false

window.Game = class Game
  constructor: (grid, moves, status, winner) ->
    console.log 'Game ctor'
    @gameBoard = new GameBoard($('#canvas'), $('#canvasOverlay'), {
      grid: grid,
      moves: moves,
      winner: winner,
      afterMoveAnimation: $.proxy(this.afterMove, this)
    })
    @setFinished(winner) if status == 'finished'

  afterMove: ->
    gameBoard = @gameBoard
    console.log 'afterMove'
    if gameBoard.nextColour == 1
      gameBoard.activate false
      console.log gameBoard.grid
      game = this
      $.ajax {
        dataType: "json",
        type: "POST",
        contentType: "application/json",
        data: JSON.stringify { grid: gameBoard.grid, moves: gameBoard.moves }
        beforeSend: (xhr) -> xhr.setRequestHeader("X-Http-Method-Override", "PUT")
        success: (result) ->
          console.log result
          new_move = result.moves[result.moves.length - 1]
          if result.status == 'finished'
            gameBoard.move new_move[1] if result.winner == 'yellow'
            game.setFinished(result.winner)
          else
            gameBoard.move new_move[1]
            gameBoard.activate true
      }

  setFinished: (winner) ->
    if winner
      $('.messagePanel').text "Game over, #{winner} won"
    else
      $('.messagePanel').text "Game over, drawn"
    @gameBoard.activate false

Fix bug - yellows last move not displayed when he wins


'use strict'

class Game

    constructor: ->
        peer = new Peer 'server', {host: 'localhost', port: 9999}
        conn = peer.connect 'device'

        conn.on 'open', =>
            conn.send 'Conneced.'
        conn.on 'data', (id) =>
            console.log id

        @resizeWindow()
        $(window).resize =>
            @resizeWindow()

        dartsUi = new DartsUi $('#darts-ui')[0]
        dartsUi.setListener (score, ratio) ->
            console.log score + ', ' + ratio + ' = ' + score * ratio

    resizeWindow: ->
        bodyHeight = $('body').height()
        headerHeight = $('.header').height() + 11
        footerHeight = $('.footer').height() + 11
        canvasHeight = bodyHeight - headerHeight - footerHeight - 20
        $('#darts-ui').width(canvasHeight).height(canvasHeight)

window.Game = Game

'use strict'

class Game

    constructor: ->
        peer = new Peer 'server', {host: 'localhost', port: 9999}
        conn = peer.connect 'device'

        conn.on 'open', =>
            conn.send 'Conneced.'
        conn.on 'data', (id) =>
            console.log id

        @resizeWindow()
        $(window).resize =>
            @resizeWindow()

        dartsUi = new DartsUi $('#darts-ui')[0]
        dartsUi.setListener (score, ratio) ->
            console.log score + ', ' + ratio + ' = ' + score * ratio

    resizeWindow: ->
        bodyHeight = $('body').height()
        headerHeight = $('.header').height() + 11
        footerHeight = $('.footer').height() + 11
        canvasHeight = bodyHeight - headerHeight - footerHeight
        length = (Math.min $('body').width(), canvasHeight) - 20
        $('#darts-ui').width(length).height(length)

window.Game = Game

Change darts-ui size to fit screen

Change darts-ui size to fit screen


window.Echotron ||= {}
Echotron.Echoes ||= {}
Echotron.Echoes.foreground ||= []
Echotron.Echoes.midground  ||= []
Echotron.Echoes.background ||= []

class Echotron.Echo extends THREE.Object3D
  uniformAttrs: {}

  # Override, calling super. Setup your Echo however you need.
  constructor: ->
    super
    @active = yes
    @initUniforms()

  # Setup list of uniforms sent to shaders.
  initUniforms: ->
    @uniforms = {}
    for name, type of @uniformAttrs
      @uniforms[name] =
        type:  type
        value: null

      # Define an accessor property on the prototype
      unless name of this
        do (name, type) =>
          Object.defineProperty @constructor::, name,
            get: -> @uniforms[name].value
            set: (val) -> @uniforms[name].value = val

    return

  # Tells this layer to start to die. It will no longer receive song events,
  # and will be pruned when @alive() returns false.
  kill: ->
    @active = no

  # Called by LayerStack
  expired: ->
    not @active and not @alive()

  # Override. Should return false when the layer can be destoryed.
  alive: -> @active

  # Override. Do stuff on beats.
  onBeat: ->

  # Override. Do stuff on bars.
  onBar: ->

  # Override. Do stuff on segment.
  onSegment: ->

  # Override. Do stuff on bars.
  onTatum: ->

  # Override. Update state per frame.
  update: (elapsed) ->

window.Echotron ||= {}
Echotron.Echoes ||= {}
Echotron.Echoes.foreground ||= []
Echotron.Echoes.midground  ||= []
Echotron.Echoes.background ||= []

class Echotron.Echo extends THREE.Object3D
  uniformAttrs: {}

  # Override, calling super. Setup your Echo however you need.
  constructor: ->
    super
    @active = yes
    @initUniforms()

    # Call a non-constructor init function.
    @initialize?()

  # Setup list of uniforms sent to shaders.
  initUniforms: ->
    @uniforms = {}
    for name, type of @uniformAttrs
      @uniforms[name] =
        type:  type
        value: null

      # Define an accessor property on the prototype
      unless name of this
        do (name, type) =>
          Object.defineProperty @constructor::, name,
            get: -> @uniforms[name].value
            set: (val) -> @uniforms[name].value = val

    return

  # Tells this layer to start to die. It will no longer receive song events,
  # and will be pruned when @alive() returns false.
  kill: ->
    @active = no

  # Called by LayerStack
  expired: ->
    not @active and not @alive()

  # Override. Should return false when the layer can be destoryed.
  alive: -> @active

  # Override. Do stuff on beats.
  onBeat: ->

  # Override. Do stuff on bars.
  onBar: ->

  # Override. Do stuff on segment.
  onSegment: ->

  # Override. Do stuff on bars.
  onTatum: ->

  # Override. Update state per frame.
  update: (elapsed) ->

Initialize can be implemented instead of implementing the constructor on a layer. Meaning super isn't required.


program = require 'commander'

program
  .command('new [name]')
  .description('create a new app and/or extension')
  .usage('[name] [options]')
  .option('-t, --template [name]', 'template to use')
  .option('-c, --config [config file]', 'config file to use')
  .action (name, opts={}) ->
    if not name
      return console.log 'Name of project required'
    require('./generator') name, opts

program
  .command('watch [name]')
  .description('watch for changes and reload')
  .action (opts={}) ->
    require('./watch') opts

help = -> console.log program.helpInformation()

program.parse process.argv

help() unless program.args.length

program = require('commander')
  .version(require('../package.json').version)

help = -> console.log program.helpInformation()

program
  .command('new [name]')
  .description('create a new app and/or extension')
  .usage('[name] [options]')
  .option('-t, --template [name]', 'template to use')
  .option('-c, --config [config file]', 'config file to use')
  .action (name, opts={}) ->
    if not name
      return console.log 'Name of project required'
    require('./generator') name, opts

program
  .command('watch [name]')
  .description('watch for changes and reload')
  .action (opts={}) ->
    require('./watch') opts

program
  .command('install')
  .description('install an app or extension')
  .option('-b, --browser [location]', 'Path to browser to use')
  .action (opts={}) ->
    switch process.platform
      when 'darwin'
        {exec} = require 'child_process'
        browser = opts.browser or 'Google\\ Chrome'
        exec "pkill #{browser}", ->
          exec "open -a #{browser} --args --load-extension=#{process.cwd()}"
      else
        console.log 'Unable to install extensions on your platform'

program.parse process.argv

help() unless program.args.length

Add command to automatically install extensions.


Rectangle = require './drawing-tools/rectangle'
Details = require './tasks/details'

module.exports =
  id: 'bhl'
  background: 'background.jpg'

  producer: 'Missouri Botanical Garden & Zooniverse'
  title: 'Illustrated Life'
  summary: 'Help catalogue scientific illustrations'
  description: 'Short description'

  pages: [{
    'About': '''

All about the project

This is where we\'ll go into detail.

Lorem ipsum dolor sir amet.

Break it into sections, add pictures, whatever.

    '''
  }]

  tasks:
    illustration:
      type: 'drawing'
      question: 'Draw rectangles around the illustrations on this page.'
      choices: [{
        type: Rectangle
        label: 'Mark the illustrations'
        color: '#333333'
      }]
      next: 'details'
    details:
      type: 'details'
      question: 'Add information about the illustrations.'
      choices: [{
        label: 'Type'
        value: ''
      },{
        label: 'Artist'
        value: ''
      }]
      next: 'details'

  firstTask: 'illustration'

Rectangle = require './drawing-tools/rectangle'
Details = require './tasks/details'

module.exports =
  id: 'bhl'
  background: 'background.jpg'

  producer: 'Missouri Botanical Garden & Zooniverse'
  title: 'Illustrated Life'
  summary: 'Help catalogue scientific illustrations'
  description: 'Short description'

  pages: [{
    'About': '''

All about the project

This is where we\'ll go into detail.

Lorem ipsum dolor sir amet.

Break it into sections, add pictures, whatever.

    '''
  }]

  tasks:
    illustrations:
      type: 'radio'
      question: 'Are there any illustrations on this page?'
      choices: [{
        label: 'Yes'
        value: 'yes'
        next: 'illustration'
      },{
        label: 'No'
        value: 'no'
      }]
    illustration:
      type: 'drawing'
      question: 'Draw rectangles around the illustrations on this page.'
      choices: [{
        type: Rectangle
        label: 'Mark the illustrations'
        color: '#333333'
      }]
      next: 'details'
    details:
      type: 'details'
      question: 'Add information about the illustrations.'
      choices: [{
        label: 'Type'
        value: ''
      },{
        label: 'Artist'
        value: ''
      }]
      next: 'details'

  firstTask: 'illustrations'

Add 'Are there any illustrations?' question


module.exports.listen = (port) ->
  createApp().listen port

createApp = () ->
  express = require 'express'
  bodyParser = require 'body-parser'
  errors = require './errors'

  allowCrossDomain = (request, response, next) ->
    response.header 'Access-Control-Allow-Origin', '*'
    response.header(
      'Access-Control-Allow-Methods',
      'GET,PUT,POST,DELETE,OPTIONS'
    )
    response.header(
      'Access-Control-Allow-Headers',
      'Content-Type, Content-Length, X-Requested-With'
    )
    #response.header('Access-Control-Allow-Credentials', 'true')
    if 'OPTIONS' == request.method
      response.send 200
    else
      next()

  defaultHeaders = (request, response, next) ->
    response.header 'Content-Type', 'application/json; charset=utf-8'
    next()

  serverErrorHandling = (err, request, response, next) ->
    if err
      if err instanceof errors.HttpError
        response.send err.statusCode, err.message
      else
        response.send 500

  jsonParser = (request, response, next) ->
    bodyParser.json() request, response, (err) ->
      if err
        next new errors.BadRequest {error: 'Invalid JSON'}
      next(err)

  app = express()
  app.use allowCrossDomain
  app.use defaultHeaders
  app.use jsonParser
  app.use require './request_handler'

  require('./api')(app)

  app.use serverErrorHandling

  return app

module.exports.listen = (port) ->
  createApp().listen port

createApp = () ->
  express = require 'express'
  bodyParser = require 'body-parser'
  errors = require './errors'

  allowCrossDomain = (request, response, next) ->
    response.header 'Access-Control-Allow-Origin', '*'
    response.header(
      'Access-Control-Allow-Methods',
      'GET,PUT,POST,DELETE,OPTIONS'
    )
    response.header(
      'Access-Control-Allow-Headers',
      'Content-Type, Content-Length, X-Requested-With'
    )
    #response.header('Access-Control-Allow-Credentials', 'true')
    if 'OPTIONS' == request.method
      response.send 200
    else
      next()

  defaultHeaders = (request, response, next) ->
    response.header 'Content-Type', 'application/json; charset=utf-8'
    next()

  serverErrorHandling = (err, request, response, next) ->
    if err
      if err instanceof errors.HttpError
        response.send err.statusCode, err.message
      else
        response.send 500

  jsonParser = (request, response, next) ->
    bodyParser.json() request, response, (err) ->
      if err
        next new errors.BadRequest {error: 'Invalid JSON'}
      else
        next()

  app = express()
  app.use allowCrossDomain
  app.use defaultHeaders
  app.use jsonParser
  app.use require './request_handler'

  require('./api')(app)

  app.use serverErrorHandling

  return app

Fix the console logging from invalid json


module.exports = {

  name: "JSX"
  namespace: "jsx"
  fallback: ['js']

  ###
  Supported Grammars
  ###
  grammars: [
    "JSX"
    "JavaScript (JSX)"
    "Babel ES6 JavaScript"
    "JavaScript with JSX"
  ]

  ###
  Supported extensions
  ###
  extensions: [
    "jsx",
    "js"
  ]

  defaultBeautifier: "JS Beautify"

  options:
    e4x:
      type: 'boolean'
      default: true
      description: "Support e4x/jsx syntax"

}

module.exports = {

  name: "JSX"
  namespace: "jsx"
  fallback: ['js']

  ###
  Supported Grammars
  ###
  grammars: [
    "JSX"
    "JavaScript (JSX)"
    "Babel ES6 JavaScript"
    "JavaScript with JSX"
  ]

  ###
  Supported extensions
  ###
  extensions: [
    "jsx",
    "js"
  ]

  defaultBeautifier: "Pretty Diff"

  options:
    e4x:
      type: 'boolean'
      default: true
      description: "Support e4x/jsx syntax"

}

Change JSX default beautifier back to Pretty Diff


AtomPackage = require './atom-package'
Package = require './package'

### Internal: Loads and resolves packages. ###

module.exports =
class ThemePackage extends AtomPackage

  getType: -> 'theme'

  getStylesheetType: -> 'theme'

  enable: ->
    atom.config.pushAtKeyPath('core.themes', @metadata.name)

  disable: ->
    atom.config.removeAtKeyPath('core.themes', @metadata.name)

  load: ->
    @measure 'loadTime', =>
      try
        @metadata ?= Package.loadMetadata(@path)
      catch e
        console.warn "Failed to load theme named '#{@name}'", e.stack ? e
    this

  activate: ->
    @measure 'activateTime', =>
      @loadStylesheets()
      @activateNow()

AtomPackage = require './atom-package'
Package = require './package'

### Internal: Loads and resolves packages. ###

module.exports =
class ThemePackage extends AtomPackage

  getType: -> 'theme'

  getStylesheetType: -> 'theme'

  enable: ->
    themes = atom.config.get('core.themes')
    themes = [@metadata.name].concat(themes)
    atom.config.set('core.themes', themes)

  disable: ->
    atom.config.removeAtKeyPath('core.themes', @metadata.name)

  load: ->
    @measure 'loadTime', =>
      try
        @metadata ?= Package.loadMetadata(@path)
      catch e
        console.warn "Failed to load theme named '#{@name}'", e.stack ? e
    this

  activate: ->
    @measure 'activateTime', =>
      @loadStylesheets()
      @activateNow()

Prepend newly enabled themes, not append


React              = require 'react'
{PureRenderMixin}  = require('react/addons').addons
cx                 = require 'classname'
styleMixin         = require 'mixins/style-mixin'

module.exports = React.createClass
  mixins: [
    styleMixin require('./style.scss')
    PureRenderMixin
  ]

  getIconTypeClass: ->
    if @props.type?
      "cc-icon-#{@props.type}"
    else
      ''
  render: ->
    className = cx
      'cc-icon':                 yes
      "#{@props.size or ''}":    yes
      "#{do @getIconTypeClass}": yes

Add an empty line to separate methods

Add an empty line to separate methods


gulp = require 'gulp'

coffee = require 'gulp-coffee'
concat = require 'gulp-concat'
gutil = require 'gulp-util'
uglify = require 'gulp-uglify'
wrap = require 'gulp-wrap-umd'

gulp.task 'build', ->
	sink = concat('main.js')

	gulp.src('lib/base64-binary.js')
		.pipe(sink, end: false)

	gulp.src('src/validateSSH.coffee')
		.pipe(coffee(bare: true)).on('error', gutil.log)
		.pipe(sink)

	sink
		.pipe(wrap
			exports: 'validateOpenSSHKey'
		)
		.pipe(uglify())
		.pipe(gulp.dest('./dist/'))

gulp.task 'default', ->
	gulp.run 'build'

	gulp.watch [
		'lib/base64-binary.js',
		'src/validateSSH.coffee'
	], (event) ->
		gulp.run 'build'

gulp = require 'gulp'

coffee = require 'gulp-coffee'
concat = require 'gulp-concat'
gutil = require 'gulp-util'
uglify = require 'gulp-uglify'
wrap = require 'gulp-wrap-umd'

gulp.task 'caffeinate', ->
	gulp.src('src/*.coffee')
		.pipe(coffee(bare: true)).on('error', gutil.log)
		.pipe(gulp.dest('./tmp/build'))

	gulp.src('test/*.coffee')
		.pipe(coffee()).on('error', gutil.log)
		.pipe(gulp.dest('./tmp'))

gulp.task 'build', [ 'caffeinate' ], ->
	gulp.src([ 'lib/*.js', 'tmp/build/*.js' ])
		.pipe(concat('main.js'))
		.pipe(wrap
			exports: 'validateOpenSSHKey'
		)
		.pipe(uglify())
		.pipe(gulp.dest('./dist/'))

gulp.task 'default', ->
	gulp.run 'build'

	gulp.watch [
		'lib/base64-binary.js',
		'src/validateSSH.coffee'
	], (event) ->
		gulp.run 'build'

Enforce order of build tasks.

Enforce order of build tasks.

Fixes issue with race condition on build.


'.text.restructuredtext':
  'image':
    'prefix': 'image'
    'body': '.. image:: ${1:path}\n$0'
  'link':
    'prefix': 'link'
    'body': '\\`${1:Title} <${2:http://link}>\\`_$0'
  'section 1':
    'prefix': 'sec'
    'body': '${1:subsection name}\n================$0\n'
  'section 2':
    'prefix': 'subs'
    'body': '${1:subsection name}\n****************$0\n'
  'section 3':
    'prefix': 'sss'
    'body': '${1:subsection name}\n----------------$0\n'
  'code block':
    'prefix': 'code'
    'body': '.. code-block::\n\n\t$1'

Add snippet for inserting a vanilla code-block


class PG.Legend

  defaults:
    className: "legend"

  constructor: (container, @graphs, options) ->
    @container = $(container)
    @options = $.extend @defaults, options
    @element = $("

").addClass(@options.className)
    @container.append @element

    @legend = new Rickshaw.Graph.Legend
      graph: @graphs[0]
      element: @element.get(0)
      naturalOrder: yes

    instance = @
    @graphSeries = {}
    for line, i in @legend.lines
      $label = $(line.element).find("span").first()
      $label.attr "rel", line.series.name
      @graphSeries[line.series.name] =
        series   : _.map @graphs, (graph) -> graph.series[graph.series.length - 1 - i]
        disabled : no
      $label.on "click", ->
        instance.toggle $(this)

  toggle: ($label) ->
    $line = $label.parent(".line")
    name = $label.attr("rel")
    graphSeries = @graphSeries[name]

    if graphSeries.disabled
      graphSeries.disabled = no
      series.disabled = no for series in graphSeries.series
      $label.removeClass "#{@options.className}__label_disabled"
      $line.removeClass "disabled"
    else
      return if _.every(_.pluck(_.without(@graphSeries, graphSeries), "disabled"))
      graphSeries.disabled = yes
      series.disabled = yes for series in graphSeries.series
      $label.addClass "#{@options.className}__label_disabled"
      $line.addClass "disabled"
    @updateGraphs()

  updateGraphs: ->
    graph.update() for graph in @graphs

class PG.Legend

  defaults:
    className: "legend"

  constructor: (container, @graphs, options) ->
    @container = $(container)
    @options = $.extend @defaults, options
    @element = $("

").addClass(@options.className)
    @container.append @element

    @legend = new Rickshaw.Graph.Legend
      graph: @graphs[0]
      element: @element.get(0)
      naturalOrder: yes

    instance = @
    @graphSeries = {}
    for line, i in @legend.lines
      $label = $(line.element).find("span").first()
      $label.attr "rel", line.series.name
      @graphSeries[line.series.name] =
        series   : _.map @graphs, (graph) -> graph.series[i]
        disabled : no
      $label.on "click", ->
        instance.toggle $(this)

  toggle: ($label) ->
    $line = $label.parent(".line")
    name = $label.attr("rel")
    graphSeries = @graphSeries[name]

    if graphSeries.disabled
      graphSeries.disabled = no
      series.disabled = no for series in graphSeries.series
      $label.removeClass "#{@options.className}__label_disabled"
      $line.removeClass "disabled"
    else
      return if _.every(_.pluck(_.without(@graphSeries, graphSeries), "disabled"))
      graphSeries.disabled = yes
      series.disabled = yes for series in graphSeries.series
      $label.addClass "#{@options.className}__label_disabled"
      $line.addClass "disabled"
    @updateGraphs()

  updateGraphs: ->
    graph.update() for graph in @graphs

Make graphs <-> series mapping use naturalOrder too


# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

roundUpBy = (value, round_to) ->
  return round_to * Math.ceil(value / round_to)

$ ->
  metricsInview = new (Waypoint.Inview)(
    element: $('.metric-box')[0]
    enter: (direction) ->
      $(".metric-box strong").each (index) ->
        $this = $(this)
        $target_count = parseInt($this.text().replace(/\,/g, ''))

        jQuery(counter: 0).animate { counter: $target_count },
          duration: 400 + index * 200
          easing: "easeInOutQuint"
          step: ->
            $this.text Math.ceil(@counter).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
          complete: ->
            jQuery(counter: $target_count).animate { counter: (3 + $target_count) },
              duration: 1300 + index * 600
              easing: "easeOutQuint"
              step: ->
                $this.text Math.ceil(@counter).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
                return
            return
        return
      # only run this once
      this.destroy()
  )

# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

roundUpBy = (value, round_to) ->
  return round_to * Math.ceil(value / round_to)

$ ->
  metricsInview = new (Waypoint.Inview)(
    element: $('.metric-box')[0]
    enter: (direction) ->
      $(".metric-box strong").each (index) ->
        $this = $(this)
        $target_count = parseInt($this.text().replace(/\,/g, ''))

        jQuery(counter: 0).animate { counter: $target_count },
          duration: 400 + index * 200
          easing: "easeInOutQuint"
          step: ->
            $this.text Math.ceil(@counter).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
          complete: ->
            jQuery(counter: $target_count).animate { counter: (40 + $target_count) },
              duration: 400
              easing: "easeOutQuint"
              step: ->
                $this.text Math.ceil(@counter).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
                return
            return
        return
      # only run this once
      this.destroy()
  )

Make the easing smoother at the end

Make the easing smoother at the end


window.App ||= {}

App.Visualization = require './visualization.js'
App.Story         = require './story.js'
App.Trix          = require 'script!trix'

$(document).ready ->

  # Activate tooltips
  $('[data-toggle="tooltip"]').tooltip()

  $body = $('body')

  # visualizations
  if $body.hasClass 'visualizations'
    # /visualizations/:id
    # /visualizations/:id/edit
    appVisualization = new App.Visualization $('body').data('visualization-id'), $body.hasClass('edit')
    appVisualization.render()
    $( window ).resize appVisualization.resize
  # stories
  else if $body.hasClass 'stories'
    # /stories/:id
    # /stories/:id/edit
    appStory = new App.Story $('body').data('story-id'), $('body').data('visualization-id'), $body.hasClass('edit')
    appStory.render()
    $( window ).resize appStory.resize

  # Add file input feedback
  # based on http://www.abeautifulsite.net/whipping-file-inputs-into-shape-with-bootstrap-3/
  $(document).on 'change', '.btn-file :file', () ->
      label     = $(this).val().replace(/\\/g, '/').replace(/.*\//, '')
      $(this).parent().siblings('.btn-file-output').html label

window.App ||= {}

App.Visualization = require './visualization.js'
App.Story         = require './story.js'
App.Trix          = require 'script!trix'

$(document).ready ->

  $body = $('body')

  # visualizations
  if $body.hasClass 'visualizations'
    # /visualizations/:id
    # /visualizations/:id/edit
    appVisualization = new App.Visualization $('body').data('visualization-id'), $body.hasClass('edit')
    appVisualization.render()
    $( window ).resize appVisualization.resize
  # stories
  else if $body.hasClass 'stories'
    # /stories/:id
    # /stories/:id/edit
    appStory = new App.Story $('body').data('story-id'), $('body').data('visualization-id'), $body.hasClass('edit')
    appStory.render()
    $( window ).resize appStory.resize

  # Activate tooltips
  $('[data-toggle="tooltip"]').tooltip()

  # Setup select-all checkbox in Chapter new/edit
  $('#relations_select_all').change (e) ->
    $('.table tbody input[type=checkbox]').prop 'checked', $(this).prop('checked')

  # Add file input feedback
  # based on http://www.abeautifulsite.net/whipping-file-inputs-into-shape-with-bootstrap-3/
  $(document).on 'change', '.btn-file :file', () ->
      label     = $(this).val().replace(/\\/g, '/').replace(/.*\//, '')
      $(this).parent().siblings('.btn-file-output').html label

Implement global selection in relations table from New Chapter

Closes #136


noflo = require "noflo"

class DuplicateProperty extends noflo.Component
    constructor: ->
        @properties = {}

        @inPorts =
            property: new noflo.ArrayPort()
            in: new noflo.Port()
        @outPorts =
            out: new noflo.Port()

        @inPorts.property.on "data", (data) =>
            @setProperty data

        @inPorts.in.on "begingroup", (group) =>
            @outPorts.out.beginGroup group
        @inPorts.in.on "data", (data) =>
            @addProperties data
        @inPorts.in.on "endgroup", =>
            @outPorts.out.endGroup()
        @inPorts.in.on "disconnect", =>
            @outPorts.out.disconnect()

    setProperty: (prop) ->
        if typeof prop is "object"
            @prop = prop
            return

        propParts = prop.split "="
        @properties[propParts[0]] = propParts[1]

    addProperties: (object) ->
        for original, newprop of @properties
            object[newprop] = object[original]

        @outPorts.out.send object

exports.getComponent = -> new DuplicateProperty

noflo = require "noflo"

class DuplicateProperty extends noflo.Component
    constructor: ->
        @properties = {}
        @separator = '/'

        @inPorts =
            property: new noflo.ArrayPort()
            separator: new noflo.Port()
            in: new noflo.Port()
        @outPorts =
            out: new noflo.Port()

        @inPorts.property.on "data", (data) =>
            @setProperty data
        @inPorts.separator.on "data", (data) =>
            @separator = data

        @inPorts.in.on "begingroup", (group) =>
            @outPorts.out.beginGroup group
        @inPorts.in.on "data", (data) =>
            @addProperties data
        @inPorts.in.on "endgroup", =>
            @outPorts.out.endGroup()
        @inPorts.in.on "disconnect", =>
            @outPorts.out.disconnect()

    setProperty: (prop) ->
        if typeof prop is "object"
            @prop = prop
            return

        propParts = prop.split "="
        if propParts.length > 2
            @properties[propParts.pop()] = propParts
            return

        @properties[propParts[1]] = propParts[0]

    addProperties: (object) ->
        for newprop, original of @properties
            if typeof original is "string"
                object[newprop] = object[original]
                continue

            newValues = []
            for originalProp in original
                newValues.push object[originalProp]
            object[newprop] = newValues.join @separator

        @outPorts.out.send object

exports.getComponent = -> new DuplicateProperty

Support for merging multiple properties into one


events = require "events"

class Port extends events.EventEmitter
    constructor: (name) ->
        @name = name
        @socket = null
        @from = null

    attach: (socket) ->
        throw new Error "#{@name}: Socket already attached #{@socket.getId()} - #{socket.getId()}" if @socket
        @socket = socket

        @attachSocket socket

    attachSocket: (socket) ->
        @emit "attach", socket

        @from = socket.from
        socket.on "connect", =>
            @emit "connect", socket
        socket.on "data", (data) =>
            @emit "data", data
        socket.on "disconnect", =>
            @emit "disconnect", socket

    detach: (socket) ->
        @emit "detach", @socket
        @from = null
        @socket = null

    send: (data, id) ->
        return @socket.send data if @isConnected()

        @socket.once "connect", =>
            @socket.send data
        @socket.connect id

    connect: (id) ->
        throw new Error "No connection available" unless @socket
        @socket.connect id

    disconnect: ->
        return unless @socket
        @socket.disconnect()

    isConnected: ->
        unless @socket
            return false
        @socket.isConnected()

exports.Port = Port

events = require "events"

class Port extends events.EventEmitter
    constructor: (name) ->
        @name = name
        @socket = null
        @from = null

    attach: (socket) ->
        throw new Error "#{@name}: Socket already attached #{@socket.getId()} - #{socket.getId()}" if @socket
        @socket = socket

        @attachSocket socket

    attachSocket: (socket) ->
        @emit "attach", socket

        @from = socket.from
        socket.on "connect", =>
            @emit "connect", socket
        socket.on "data", (data) =>
            @emit "data", data
        socket.on "disconnect", =>
            @emit "disconnect", socket

    detach: (socket) ->
        @emit "detach", @socket
        @from = null
        @socket = null

    send: (data, id) ->
        throw new Error "No connection available" unless @socket

        return @socket.send data if @isConnected()

        @socket.once "connect", =>
            @socket.send data
        @socket.connect id

    connect: (id) ->
        throw new Error "No connection available" unless @socket
        @socket.connect id

    disconnect: ->
        return unless @socket
        @socket.disconnect()

    isConnected: ->
        unless @socket
            return false
        @socket.isConnected()

exports.Port = Port

Throw an error if sending to an unattached port


$.fn.edit = ->
  form = new Phalange( el: @ )
  @

class Phalange extends Backbone.View
  initialize: ->
    @text = @$el.text()

  events:
    "click": "append"
    "submit": "submit"
    "blur": "submit"

  submit: ->
    @text = @_input().val()
    @$el.trigger 'phalange:submit', @text
    @hideForm()
    @setText()

  setText: ->
    @$el.text @_input().val()

  hideForm: ->
    @_phalange().hide()

  append: ->
    @$el.text ''
    @$el.append @_$form() unless @_phalange_present()

  _phalange_present: ->
    @_phalange().length is 1

  _phalange: ->
    @$el.find('.phalange-form')

  _input: ->
    @$el.find('input')

  _$form: ->
    template = """
      <form class= 'phalange-form' action='javascript:void(0)'>
        <input type='text' value="#{@text}">
        </input>
      </form>
    """
    $(template)

module?.exports = Phalange

$.fn.edit = ->
  form = new Phalange( el: @ )
  @

class Phalange extends Backbone.View
  initialize: ->
    @text = @$el.text()

  events:
    "click": "append"
    "submit": "submit"
    "blur input": "submit"

  submit: ->
    @text = @_input().val()
    @$el.trigger 'phalange:submit', @text
    @hideForm()
    @setText()

  setText: ->
    @$el.text @_input().val()

  hideForm: ->
    @_phalange().hide()

  append: ->
    @$el.text ''
    @$el.append @_$form() unless @_phalange_present()

  _phalange_present: ->
    @_phalange().length is 1

  _phalange: ->
    @$el.find('.phalange-form')

  _input: ->
    @$el.find('input')

  _$form: ->
    template = """
      <form class= 'phalange-form' action='javascript:void(0)'>
        <input type='text' value="#{@text}">
        </input>
      </form>
    """
    $(template)

if module?
  module.exports = Phalange
else
  window.Phalange = Phalange

Add to window when in the browser, listen for blur


class EditorPane extends Pane

  constructor: (options = {}, data) ->

    options.cssClass = KD.utils.curry "editor-pane", options.cssClass

    super options, data

    @createEditor()

  createEditor: ->
    {file, content} = @getOptions()
    isLocalFile     = no

    unless file instanceof FSFile
      return new Error "File must be an instance of FSFile"

    unless content
      return new Error "You must pass file content to EditorPane"

    @ace = new Ace { delegate : this }, file
    @addSubView @ace
    @ace.once "ace.ready", =>
      @getEditor().setValue content, 1
      @ace.setReadOnly yes  if @getOptions().readOnly

  getEditor: ->
    return @ace.editor

  getValue: ->
    return  @getEditor().getSession().getValue()

class EditorPane extends Pane

  constructor: (options = {}, data) ->

    options.cssClass = KD.utils.curry "editor-pane", options.cssClass

    super options, data

    @createEditor()

  createEditor: ->
    {file, content} = @getOptions()
    isLocalFile     = no

    unless file instanceof FSFile
      return new Error "File must be an instance of FSFile"

    unless content
      return new Error "You must pass file content to EditorPane"

    @ace = new AceView { delegate: this }, file
    @addSubView @ace
    @ace.once "ace.ready", =>
      @getEditor().setValue content, 1
      @ace.setReadOnly yes  if @getOptions().readOnly

  getEditor: ->
    return @ace.editor

  getValue: ->
    return  @getEditor().getSession().getValue()

Use AceView which is bundled editor of Koding for EditorPane.


$(document).ready ->
  # Photo grid
  photoGrid = $(".photo-grid")
  photoGrid.on "reload:grid", ->
    opts = wookmarkOptions(calculateGridWidth())
    photoGrid.find(".photo, .user-block").wookmark(opts)

  photoGrid.trigger "reload:grid"

  $(window).resize ->
    photoGrid.trigger "reload:grid"

  # Description size tweaking on photo show
  image = $(".display .image img")
  description = image.siblings(".description")
  if image.length > 0
    image.on "resize:description", ->
      if description.length > 0
        description.innerWidth(image.width())
        if description.is(":hidden")
          description.fadeIn()

    $(".display").imagesLoaded ->
      image.trigger "resize:description"

    $(window).resize ->
      image.trigger "resize:description"

$(document).ready ->
  # Photo grid
  photoGrid = $(".photo-grid")
  photoGrid.on "reload:grid", ->
    opts = wookmarkOptions(calculateGridWidth())
    photoGrid.find(".photo, .user-block").wookmark(opts)

  photoGrid.imagesLoaded ->
    photoGrid.trigger "reload:grid"

  $(window).resize ->
    photoGrid.trigger "reload:grid"

  # Description size tweaking on photo show
  image = $(".display .image img")
  description = image.siblings(".description")
  if image.length > 0
    image.on "resize:description", ->
      if description.length > 0
        description.innerWidth(image.width())
        if description.is(":hidden")
          description.fadeIn()

    $(".display").imagesLoaded ->
      image.trigger "resize:description"

    $(window).resize ->
      image.trigger "resize:description"

Fix for photo grid overlap

Fix for photo grid overlap


CSV = require('csv')
Q = require('q')

argv = require('optimist')
  .usage('Usage: $0 --types product-types.csv --attributes product-types-attributes.csv')
  .demand(['types', 'attributes'])
  .argv

ProductTypeGenerator = require('../main').ProductTypeGenerator

###
Reads a CSV file by given path and returns a promise for the result.
@param {string} path The path of the CSV file.
@return Promise of csv read result.
###
readCsvPromise = (path) ->
  deferred = Q.defer()
  CSV().from.path(path)
  .to (data) ->
    deferred.resolve(data)
  .on "error", (error) ->
    deferred.reject(new Error(error))
  deferred.promise

promises = Q.all [readCsvPromise(argv.types), readCsvPromise(argv.attributes)]

Q.spread promises, (types, attributes) ->
  generator = new ProductTypeGenerator
  generator.run types, attributes, (success) ->
    process.exit 1 unless success

CSV = require('csv')
Q = require('q')

argv = require('optimist')
  .usage('Usage: $0 --types product-types.csv --attributes product-types-attributes.csv')
  .demand(['types', 'attributes'])
  .argv

ProductTypeGenerator = require('../main').ProductTypeGenerator

###
Reads a CSV file by given path and returns a promise for the result.
@param {string} path The path of the CSV file.
@return Promise of csv read result.
###
readCsvPromise = (path) ->
  deferred = Q.defer()
  CSV().from.path(path)
  .to (data) ->
    deferred.resolve(data)
  .on "error", (error) ->
    deferred.reject(new Error(error))
  deferred.promise

promises = Q.all [readCsvPromise(argv.types), readCsvPromise(argv.attributes)]

promises.spread (types, attributes) ->
  generator = new ProductTypeGenerator
  generator.run types, attributes, (success) ->
    process.exit 1 unless success

Use instance method instead static method.


import fetch from 'isomorphic-fetch';

port = (process.env.OPENSHIFT_NODEJS_PORT || process.env.PORT || '3000')
ip = (process.env.OPENSHIFT_NODEJS_IP || '127.0.0.1')
export API_URL = (if (typeof window == 'undefined') then ('http://' + ip + ':' + port) else '') + '/api/'

export callApiWithBody = (endpoint, method, headers, body) ->
    response = await fetch(API_URL + endpoint, {
        credentials: 'same-origin',
        method: method,
        headers,
        body
    })
    try
        return await response.json()
    catch
        return {}

export default callApi = (endpoint, data) ->
    method = if data then 'POST' else 'GET'
    headers = {
        'Content-Type': 'application/json'
    }
    body = JSON.stringify(data)
    return callApiWithBody(endpoint, method, headers, body)

import fetch from 'isomorphic-fetch';

port = (process.env.OPENSHIFT_NODEJS_PORT || process.env.PORT || '3000')
ip = (process.env.OPENSHIFT_NODEJS_IP || '127.0.0.1')
protocol = (if process.env.FORCE_HTTPS then 'https' else 'http')
export API_URL = (if (typeof window == 'undefined') then (protocol + '://' + ip + ':' + port) else '') + '/api/'

export callApiWithBody = (endpoint, method, headers, body) ->
    response = await fetch(API_URL + endpoint, {
        credentials: 'same-origin',
        method: method,
        headers,
        body
    })
    try
        return await response.json()
    catch
        return {}

export default callApi = (endpoint, data) ->
    method = if data then 'POST' else 'GET'
    headers = {
        'Content-Type': 'application/json'
    }
    body = JSON.stringify(data)
    return callApiWithBody(endpoint, method, headers, body)

Call https api if we are on https

Call https api if we are on https


# Export Google WebFont Config
window.WebFontConfig =
    # Load some fonts from google
    google:
        families: []

    # ... you can do something here if you'd like
    active: () ->

# Create script tag matching protocol
s = document.createElement 'script'
s.src = "#{if document.location.protocol is 'https:' then 'https' else 'http'}://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js"
s.type = 'text/javascript'
s.async = 'true'

# Insert it before the first script tag
s0 = (document.getElementsByTagName 'script')[0]
s0.parentNode.insertBefore s, s0

$ ->
    console.log "Document ready."
    startRenderer()
    startNetworking()
    startInput()

Bring in code to load google fonts

Bring in code to load google fonts