@AppRouter = Backbone.Router.extend
  routes:
    "reload": "reload"
    "": "categories"
    "about": "about"
    "contribute": "contribute"
    "pods/:filter": "pods"
    "pods/:filter/:sort_by": "pods"
    "pods/:filter/:sort_by/:idx": "pods"
  contribute: () ->
    @pageview '/contribute'
    @appController.displayContribute()
  about: () ->
    @pageview '/about'
    @appController.displayAbout()
  categories: () ->
    @pageview '/categories'
    @appController.displayCategories()
  pods: (filter, sort_by, idx) ->
    if !filter
      filter = 'all'
    if !sort_by
      sort_by = 'stars'
    if !idx
      idx = 0
    @pageview '/pods/'+filter+'/'+sort_by+'/'+idx
    @appController.displayPodsAndUpdateScope(parseInt(idx), filter, sort_by)
  reload: ->
    @appController.loadPods()
  pageview: (page) ->
    if ga
      ga 'send', 'pageview', page

@AppRouter = Backbone.Router.extend
  routes:
    "reload": "reload"
    "": "categories"
    "about": "about"
    "contribute": "contribute"
    "pods/:filter": "pods"
    "pods/:filter/:sort_by": "pods"
    "pods/:filter/:sort_by/:idx": "pods"
  contribute: () ->
    @pageview '/contribute'
    @appController.displayContribute()
  about: () ->
    @pageview '/about'
    @appController.displayAbout()
  categories: () ->
    @pageview '/categories'
    @appController.displayCategories()
  pods: (filter, sort_by, idx) ->
    if !filter
      filter = 'all'
    if !sort_by
      sort_by = 'stars'
    if !idx
      idx = 0
    @pageview '/pods/'+filter+'/'+sort_by+'/'+idx
    @appController.displayPodsAndUpdateScope(parseInt(idx), filter, sort_by)
  reload: ->
    @appController.loadPods()
  pageview: (page) ->
    if window.ga
      window.ga 'send', 'pageview', page

Fix app router when there are no analytics.


angular.module('doubtfire.projects.states.tutorials', [])

#
# Tasks state for projects
#
.config(($stateProvider) ->
  $stateProvider.state 'projects/tutorials', {
    parent: 'projects/index'
    url: '/tutorials'
    controller: 'ProjectsTutorialsStateCtrl'
    templateUrl: 'projects/states/tutorials/tutorials.tpl.html'
    data:
      task: "Tutorial List"
      pageTitle: "_Home_"
      roleWhitelist: ['Tutor', 'Convenor', 'Admin', 'Student']
   }
)

.controller("ProjectsTutorialsStateCtrl", ($scope, $modal, User, Project, alertService, projectService, analyticsService) ->
  $scope.sortOrder = 'abbreviation'
  $scope.setTutorial = (id) ->
    Project.update(
      { id: $scope.project.project_id, tutorial_id: id }
      (project) ->
        oldTutorialAbbr = $scope.unit.tutorialFromId($scope.project.tutorial_id)?.abbreviation
        $scope.project.tutorial_id = project.tutorial_id
        $scope.project.tutorial = $scope.unit.tutorialFromId( $scope.project.tutorial_id )
        if id == -1
          eventName = "Withdrew from all tutorials"
          successMsg = "Withdrew from #{oldTutorialAbbr}"
        else
          eventName = "Changed tutorial"
          successMsg = "Enrolled in #{$scope.project.tutorial.abbreviation}"
        analyticsService.event("Student Project View - Tutorials Tab", eventName)
        alertService.add("success", successMsg, 3000)
        projectService.updateGroups($scope.project) #can be removed from groups by changing labs
      (response) -> alertService.add("danger", response.data.error, 6000)
    )
)

angular.module('doubtfire.projects.states.tutorials', [])

#
# Tasks state for projects
#
.config(($stateProvider) ->
  $stateProvider.state 'projects/tutorials', {
    parent: 'projects/index'
    url: '/tutorials'
    controller: 'ProjectsTutorialsStateCtrl'
    templateUrl: 'projects/states/tutorials/tutorials.tpl.html'
    data:
      task: "Tutorial List"
      pageTitle: "_Home_"
      roleWhitelist: ['Tutor', 'Convenor', 'Admin', 'Student']
   }
)

.controller("ProjectsTutorialsStateCtrl", ($scope, $modal, User, Project, alertService, projectService, analyticsService) ->
  $scope.sortOrder = 'abbreviation'
)

QUALITY: Remove switch tutorial from student tutorial list


if $mate.environmentType == "browser"
    global.$mate = $mate
else if $mate.environmentType == "node"
    module.exports = $mate
else
    throw new Error()

if $mate.environmentType == "browser"
    window.$mate = $mate
else if $mate.environmentType == "node"
    module.exports = $mate
else
    throw new Error()

Fix a browser global bug.

Fix a browser global bug.


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

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

Remove console log from o change method

Remove console log from o change method


class ForgotPasswordController
  constructor: (AuthenticatorService, $routeParams) ->
    @AuthenticatorService = AuthenticatorService
    @callbackUrl = $routeParams.callback ? 'https://app.octoblu.com/api/session'
    @loginPath = "/?" + $.param(callback: @callbackUrl)

  forgotPassword: (email) =>
    @AuthenticatorService.forgotPassword(email)
      .then =>
        @message = 'An email has been sent.'
      .catch =>
        @errorMessage = 'Error resetting your password'

angular.module('email-password').controller 'ForgotPasswordController', ForgotPasswordController

class ForgotPasswordController
  constructor: (AuthenticatorService, $routeParams) ->
    @AuthenticatorService = AuthenticatorService
    @callbackUrl = $routeParams.callback ? 'https://app.octoblu.com/api/session'
    @loginPath = "/?" + $.param(callback: @callbackUrl)

  forgotPassword: (email) =>
    delete @message
    delete @errorMessage
    @AuthenticatorService.forgotPassword(email)
      .then =>
        @message = 'An email has been sent.'
      .catch =>
        @errorMessage = 'Error resetting your password'

angular.module('email-password').controller 'ForgotPasswordController', ForgotPasswordController

Hide forgot failure messages on submit

Hide forgot failure messages on submit


helpers = require '../spec-helpers'
LatexmkBuilder = require '../../lib/builders/latexmk'

describe "LatexmkBuilder", ->
  [builder] = []

  beforeEach ->
    builder = new LatexmkBuilder()

  describe "constructArgs", ->
    beforeEach ->
      @filePath = 'foo.tex'

    it "produces default arguments when package has default config values", ->
      expectedArgs = [
        '-interaction=nonstopmode'
        '-f'
        '-cd'
        '-pdf'
        '-synctex=1'
        '-file-line-error'
        "\"#{@filePath}\""
      ]
      args = builder.constructArgs(@filePath)
      expect(args).toEqual(expectedArgs)

    it "adds -shell-escape flag when package config value is set", ->
      helpers.spyOnConfig('latex.enableShellEscape', true)
      expect(builder.constructArgs(@filePath)).toContain "-shell-escape"

    it "adds -outdir=<path> argument according to package config", ->
      outdir = 'bar'
      expectedArg = "-outdir=\"#{outdir}\""
      helpers.spyOnConfig('latex.outputDirectory', outdir)
      expect(builder.constructArgs(@filePath)).toContain expectedArg

    it "adds engine argument according to package config", ->
      helpers.spyOnConfig('latex.engine', 'lualatex')
      expect(builder.constructArgs(@filePath)).toContain "-lualatex"

    it "adds a custom engine string according to package config", ->
      helpers.spyOnConfig('latex.customEngine', 'pdflatex %O %S')
      expect(builder.constructArgs(@filePath)).toContain '-pdflatex="pdflatex %O %S"'

helpers = require '../spec-helpers'
LatexmkBuilder = require '../../lib/builders/latexmk'

describe "LatexmkBuilder", ->
  [builder] = []

  beforeEach ->
    builder = new LatexmkBuilder()

  describe "constructArgs", ->
    [filePath] = []

    beforeEach ->
      filePath = 'foo.tex'

    it "produces default arguments when package has default config values", ->
      expectedArgs = [
        '-interaction=nonstopmode'
        '-f'
        '-cd'
        '-pdf'
        '-synctex=1'
        '-file-line-error'
        "\"#{filePath}\""
      ]
      args = builder.constructArgs(filePath)
      expect(args).toEqual(expectedArgs)

    it "adds -shell-escape flag when package config value is set", ->
      helpers.spyOnConfig('latex.enableShellEscape', true)
      expect(builder.constructArgs(filePath)).toContain "-shell-escape"

    it "adds -outdir=<path> argument according to package config", ->
      outdir = 'bar'
      expectedArg = "-outdir=\"#{outdir}\""
      helpers.spyOnConfig('latex.outputDirectory', outdir)
      expect(builder.constructArgs(filePath)).toContain expectedArg

    it "adds engine argument according to package config", ->
      helpers.spyOnConfig('latex.engine', 'lualatex')
      expect(builder.constructArgs(filePath)).toContain "-lualatex"

    it "adds a custom engine string according to package config", ->
      helpers.spyOnConfig('latex.customEngine', 'pdflatex %O %S')
      expect(builder.constructArgs(filePath)).toContain '-pdflatex="pdflatex %O %S"'

:art: Convert instance variable to scoped variable


# Takes two parameters: container and app
`import YoutubeAdapter from '../adapters/youtube'`
`import YoutubeSerializer from '../serializers/youtube'`
`import DS from 'ember-data'`

initialize = (ctn, app) ->
  app.register('adapter:-youtube', YoutubeAdapter)
  app.register('serializer:-youtube', YoutubeSerializer)
  DS.YoutubeAdapter = YoutubeAdapter
  DS.YoutubeSerializer = YoutubeSerializer

YoutubeInitializer =
  name: 'youtube'
  before: 'store'
  initialize: initialize

`export {initialize}`
`export default YoutubeInitializer`

# Takes two parameters: container and app
`import YoutubeAdapter from '../adapters/youtube'`
`import YoutubeSerializer from '../serializers/youtube'`
`import DS from 'ember-data'`

initialize = (ctn, app) ->
  app.register('adapter:-youtube', YoutubeAdapter)
  app.register('serializer:-youtube', YoutubeSerializer)
  DS.YoutubeAdapter = YoutubeAdapter
  DS.YoutubeSerializer = YoutubeSerializer

YoutubeInitializer =
  name: 'youtube'
  before: 'ember-data'
  initialize: initialize

`export {initialize}`
`export default YoutubeInitializer`

Use the `ember-data` initializer as a target instead of the soon to be deprecated `store` initializer


class window.SubCommentsListView extends Backbone.Marionette.CompositeView
  className: 'evidence-sub-comments-list'

  itemView: SubCommentView
  itemViewContainer: '.js-region-sub-comments-collection'

  template: 'sub_comments/sub_comments_list'

  addView: SubCommentsAddView

  initialize: ->
    @collection.fetch update: true # only fires 'add' and 'remove' events

  onShow: ->
    if Factlink.Global.signed_in
      @_subCommentsAddView ?= new @addView(addToCollection: @collection)
      @$('.js-region-sub-comments-form').html @_subCommentsAddView.render().el

  onClose: ->
    @_subCommentsAddView?.close()

class window.NDPSubCommentsListView extends SubCommentsListView
  itemView: NDPSubCommentView
  addView: NDPSubCommentsAddView

class window.SubCommentsListView extends Backbone.Marionette.CompositeView
  className: 'evidence-sub-comments-list'

  itemView: SubCommentView
  itemViewContainer: '.js-region-sub-comments-collection'

  template: 'sub_comments/sub_comments_list'

  initialize: ->
    @collection.fetch update: true # only fires 'add' and 'remove' events

  onShow: ->
    if Factlink.Global.signed_in
      @$('.js-region-sub-comments-form').html @subCommentsAddView().render().el

  onClose: ->
    @subCommentsAddView().close()

  subCommentsAddView: ->
    @_subCommentsAddView ?= new SubCommentsAddView(addToCollection: @collection)

class window.NDPSubCommentsListView extends SubCommentsListView
  itemView: NDPSubCommentView

  subCommentsAddView: ->
    @_subCommentsAddView ?= new NDPSubCommentsAddView(addToCollection: @collection)

Use method instead of instance var per @markijbema's comment


class AgentSpawner
  potential_agents: [] # Holds all potential customers from customers.json

constructor: ->
  $.ajax("/assets/data/agents.json").done($.proxy((data_agents) ->
      for data_agent in data_agents
        agent = new Agent
        customer.fromAgentData(data_agent)
        @potential_agents.push(data_agent)
    , this)
  )
  hireAgent: ()->
    agent = potential_agents[Math.floor(Math.random() * potential_agents.length())]
    potential_agents.pop(agent)
    return agent

class AgentSpawner
  potential_agents: [] # Holds all potential customers from customers.json

constructor: ->
  $.ajax("/assets/data/agents.json").done($.proxy((data_agents) ->
      for data_agent in data_agents
        agent = new Agent
        agent.fromAgentData(data_agent)
        @potential_agents.push(agent)
    , this)
  )
  hireAgent: ()->
    agent = potential_agents[Math.floor(Math.random() * potential_agents.length())]
    potential_agents.pop(agent)
    return agent

Fix bug in Agent Spawner

Fix bug in Agent Spawner


request = require 'request'

module.exports =
  class Reporter
    constructor: ->
      @request = request

    send: (eventType, data) ->
      params = timestamp: ((new Date().getTime()) / 1000)
      params.dimensions = data

      @request
        method: 'POST'
        url: "https://collector.githubapp.com/atom/#{eventType}"
        headers:
          'Content-Type' : 'application/vnd.github-octolytics+json'
        body: JSON.stringify(params)

request = require 'request'

module.exports =
  class Reporter
    constructor: ->
      @request = request

    send: (eventType, data) ->
      params =
        timestamp: new Date().getTime() / 1000
        dimensions: data

      requestOptions =
        method: 'POST'
        url: "https://collector.githubapp.com/atom/#{eventType}"
        headers:
          'Content-Type' : 'application/vnd.github-octolytics+json'
        body: JSON.stringify(params)

      @request requestOptions, -> # Callback prevents errors from going to the console

Add callback to request invocation

Add callback to request invocation

This prevents request errors such as "Uncaught Error: getaddrinfo ENOTFOUND"
from going to the console when errors are reported when you aren't online.


###
Functions to build the benchmark table
###

benchmark_id = (data, type, row) ->
  "#{row.num}#{row.variations}.#{row.revisions.version}"

get_columns = ->
  ### Get the column data for the table

  Returns:
    list of columns
  ###
  [
    {
      title:'ID'
      render:benchmark_id
    }
    {
      data:'num'
      title:'Num'
    }
    {
      data:'revisions'
      title:'Revision'
      render:((x, ...) -> x.version)
    }
    {
      data:'title'
      title:'Title'
    }
  ]

transform_data = sequence(
  flat_key_from_list('variations')
  flat_key_from_list('revisions')
)

get_benchmark_data = (data) ->
  ### the final data for the benchmark table

  Args:
    data: the raw benchmark data

  Returns:
    data formatted for Datatable
  ###
  {
    lengthMenu:[10]
    lengthChange:false
    data:transform_data(data)
    columns:get_columns()
  }

###
Functions to build the benchmark table
###

benchmark_id = (data, type, row) ->
  "#{row.num}#{row.variations}.#{row.revisions.version}"

get_columns = ->
  ### Get the column data for the table

  Returns:
    list of columns
  ###
  [
    {
      title:'ID'
      render:benchmark_id
    }
    {
      data:'num'
      title:'Num'
    }
    {
      data:'variations'
      title:'Variation'
    }
    {
      data:'revisions'
      title:'Revision'
      render:((x, ...) -> x.version)
    }
    {
      data:'title'
      title:'Title'
    }
  ]

transform_data = sequence(
  flat_key_from_list('variations')
  flat_key_from_list('revisions')
)

get_benchmark_data = (data) ->
  ### the final data for the benchmark table

  Args:
    data: the raw benchmark data

  Returns:
    data formatted for Datatable
  ###
  {
    lengthMenu:[20]
    lengthChange:false
    data:transform_data(data)
    columns:get_columns()
  }

Add variation column to benchmark table

Add variation column to benchmark table


Q = require 'q'
request = require 'superagent'
Heroku = require 'heroku-client'

heroku = new Heroku token: process.env.HEROKU_API_KEY

Q.ninvoke(heroku.apps(), 'list')
  .then (apps) ->
    urls = (app.web_url for app in apps)
    promises = urls.map (url) ->
      deferred = Q.defer()
      console.log "pinging #{url}"
      request.get(url).end (res) ->
        console.log "pingu has pinged #{url}"
        deferred.resolve()
      deferred.promise
    console.log "------------------"
    Q.all promises

  .then ->
    console.log "------------------"
    console.log "pinged all URLs"

  .fail (err) ->
    console.error err

  .done()

Q = require 'q'
request = require 'superagent'
Heroku = require 'heroku-client'

heroku = new Heroku token: process.env.HEROKU_API_KEY

ping = ->
  Q.ninvoke(heroku.apps(), 'list')
    .then (apps) ->
      urls = (app.web_url for app in apps)
      promises = urls.map (url) ->
        deferred = Q.defer()
        console.log "pinging #{url}"
        request.get(url).end (res) ->
          console.log "pingu has pinged #{url}"
          deferred.resolve()
        deferred.promise
      console.log "------------------"
      Q.all promises

    .then ->
      console.log "------------------"
      console.log "pinged all URLs"

    .fail (err) ->
      console.error err

    .done()

LOOP_INTERVAL = process.env.LOOP_INTERVAL or (1000 * 60 * 30)

if process.env.KEEP_RUNNING
  looper = ->
    ping()
    setTimeout ->
      looper()
    , LOOP_INTERVAL
  looper()
else
  ping()

Support for running on heroku.

Support for running on heroku.


#= require ./abstract_attribute_binding

class Batman.DOM.EventBinding extends Batman.DOM.AbstractAttributeBinding
  onlyObserve: Batman.BindingDefinitionOnlyObserve.Data

  constructor: ->
    super

    callback = =>
      target = @view.targetForKeypathBase(@key)
      @get('filteredValue')?.apply(target, arguments)

    if attacher = Batman.DOM.events[@attributeName]
      attacher(@node, callback, @view)
    else
      Batman.DOM.events.other(@node, @attributeName, callback, @view)

  _unfilteredValue: (key) ->
    if not @functionName and (index = key.lastIndexOf('.')) != -1
      @functionPath = key.substr(0, index)
      @functionName = key.substr(index + 1)

    value = super(@functionPath || key)
    if @functionName
      value?[@functionName]
    else
      value

#= require ./abstract_attribute_binding

class Batman.DOM.EventBinding extends Batman.DOM.AbstractAttributeBinding
  onlyObserve: Batman.BindingDefinitionOnlyObserve.Data
  bindImmediately: false

  constructor: ->
    super

    callback = =>
      func = @get('filteredValue')
      target = @view.targetForKeypathBase(@functionPath)
      return func?.apply(target, arguments)

    if attacher = Batman.DOM.events[@attributeName]
      attacher(@node, callback, @view)
    else
      Batman.DOM.events.other(@node, @attributeName, callback, @view)

  _unfilteredValue: (key) ->
    if not @functionName and (index = key.lastIndexOf('.')) != -1
      @functionPath = key.substr(0, index)
      @functionName = key.substr(index + 1)
    else
      @functionPath = key

    value = super(@functionPath)
    if @functionName
      value?[@functionName]
    else
      value

Fix event bindings for variable-length keypaths.


express = require 'express'
router = express.Router()

router.get '/admin', (req, res) ->
  if req.user
    res.redirect '/admin/cc'
  else
    res.render 'login', error: req.flash 'error'

router.get '/admin/:page?', (req, res) ->
  res.render 'index', error: req.flash 'error'

router.get "/partials/cc", (req, res) ->
  res.render 'partials/contentcontrol', error: req.flash 'error'

router.get "/partials/admin", (req, res) ->
  res.render 'partials/admincontrol', error: req.flash 'error'

module.exports = router

express = require 'express'
router = express.Router()

router.get '/resetPassword', (req, res) ->
  if !req.user or !req.user.data.needsReset
    return res.redirect "/"
  res.render 'resetpassword',
    error: req.flash 'error'
    username: req.user.data.username

router.use (req, res, next) ->
  if req.user and req.user.data.needsReset
    res.redirect '/resetPassword'
  else
    next()

router.get '/admin', (req, res) ->
  if req.user
    res.redirect '/admin/cc'
  else
    res.render 'login', error: req.flash 'error'

router.get '/admin/:page?', (req, res) ->
  res.render 'index', error: req.flash 'error'

router.get "/partials/cc", (req, res) ->
  res.render 'partials/contentcontrol', error: req.flash 'error'

router.get "/partials/admin", (req, res) ->
  res.render 'partials/admincontrol', error: req.flash 'error'

module.exports = router

Add resetpassword route, fix alert box always being shown on reset password page


loadPpt = ->
  pptData = StrutBuilder.build(JSON.parse(localStorage.regions))
    #[
      #{ #slide 1
        #start: 0,
        #end: 2.5,
        #texts: [
                 #{text: 'Hum', position: 1.2},
                 #{text: 'bewafaa', position: 1.7}
               #]
      #},
      #{ #slide 2
        #start: 2.5,
        #end: 4.3,
        #texts: [
                 #{text: 'Hargiz', position: 3.3},
                 #{text: 'na they', position: 3.8}
               #]
      #}
    #]
  localStorage['Strut_sessionMeta'] = '{"generator_index":0,"lastPresentation":"presentation-unnamed.strut"}'
  localStorage['strut-presentation-unnamed.strut'] = JSON.stringify(pptData)
  $('#editor').attr('src', '/editor/')

$ ->
  $('#ppt-loader').on 'click', loadPpt

loadPpt = ->
  pptData = StrutBuilder.build(JSON.parse(localStorage.regions))
    #[
      #{ #slide 1
        #start: 0,
        #end: 2.5,
        #texts: [
                 #{text: 'Hum', position: 1.2},
                 #{text: 'bewafaa', position: 1.7}
               #]
      #},
      #{ #slide 2
        #start: 2.5,
        #end: 4.3,
        #texts: [
                 #{text: 'Hargiz', position: 3.3},
                 #{text: 'na they', position: 3.8}
               #]
      #}
    #]
  $('#editor').removeAttr('src').one 'load', ->
    localStorage['Strut_sessionMeta'] = '{"generator_index":0,"lastPresentation":"presentation-unnamed.strut"}'
    localStorage['strut-presentation-unnamed.strut'] = JSON.stringify(pptData)
    $('#editor').attr('src', '/editor/')

$ ->
  $('#ppt-loader').on 'click', loadPpt

Make multiple loads of strut pick up latest ppt data properly.


class AppRouter extends Backbone.Router

  routes:
    '': 'homePage'
    'panel/:id': 'goToPanel'

  homePage: ->
    @view = new app.Views.Home
    @view.render()

  goToPanel: (id) ->
    @view = new app.Views["Panel_" + id]
    @view.render(id)

@app = window.app ? {}
@app.Routers.AppRouter = AppRouter

class AppRouter extends Backbone.Router

  routes:
    '': 'homePage'
    'panel/:id': 'goToPanel'

  initialize: ->
    flight.launch("#panel-1")

  homePage: ->
    @view = new app.Views.Home
    @view.render()

  goToPanel: (id) ->
    @view = new app.Views["Panel_" + id]
    @view.render(id)

@app = window.app ? {}
@app.Routers.AppRouter = AppRouter

Set start panel with flight.launch()

Set start panel with flight.launch()


import * as _ from "underscore"

import * as p from "../../core/properties"

import {InputWidget, InputWidgetView} from "./input_widget"

import multiselecttemplate from "./multiselecttemplate"

export class MultiSelectView extends InputWidgetView
  tagName: "div"
  template: multiselecttemplate
  events:
    "change select": "change_input"

  initialize: (options) ->
    super(options)
    @render()
    @listenTo(@model, 'change:value', @render_selection)
    @listenTo(@model, 'change:options', @render)
    @listenTo(@model, 'change:name', @render)
    @listenTo(@model, 'change:title', @render)

  render: () ->
    super()
    @$el.empty()
    html = @template(@model.attributes)
    @$el.html(html)
    @render_selection()
    return @

  render_selection: () =>
    values = {}
    _.map(@model.value, (x) -> values[x] = true)
    @$('option').each((el) =>
      el = @$(el)
      if values[el.attr('value')]
        el.attr('selected', 'selected')
    )

  change_input: () ->
    value = @$el.find('select').val()
    if value
      @model.value = value
    else
      @model.value = []
    super()

export class MultiSelect extends InputWidget
  type: "MultiSelect"
  default_view: MultiSelectView

  @define {
      value:   [ p.Array, [] ]
      options: [ p.Array, [] ]
    }

import * as _ from "underscore"

import * as p from "../../core/properties"

import {InputWidget, InputWidgetView} from "./input_widget"

import multiselecttemplate from "./multiselecttemplate"

export class MultiSelectView extends InputWidgetView
  tagName: "div"
  template: multiselecttemplate
  events:
    "change select": "change_input"

  initialize: (options) ->
    super(options)
    @render()
    @listenTo(@model, 'change:value', @render_selection)
    @listenTo(@model, 'change:options', @render)
    @listenTo(@model, 'change:name', @render)
    @listenTo(@model, 'change:title', @render)

  render: () ->
    super()
    @$el.empty()
    html = @template(@model.attributes)
    @$el.html(html)
    @render_selection()
    return @

  render_selection: () =>
    values = {}
    for x in @model.value
      values[x] = true
    @$('option').each((el) =>
      el = @$(el)
      if values[el.attr('value')]
        el.attr('selected', 'selected')
    )

  change_input: () ->
    value = @$el.find('select').val()
    if value
      @model.value = value
    else
      @model.value = []
    super()

export class MultiSelect extends InputWidget
  type: "MultiSelect"
  default_view: MultiSelectView

  @define {
      value:   [ p.Array, [] ]
      options: [ p.Array, [] ]
    }

Replace invalid use of _.map() with a for-loop


'use strict'

stripEof = require 'strip-eof'
exec = require('child_process').exec

keywords =
  '$newVersion':
    regex: /\$newVersion/g
    replace: '_version'

  '$oldVersion':
    regex: /\$oldVersion/g
    replace: '_oldVersion'

createLogger = (logger) ->
  logState = (state, messages) ->
    logger[state] message for message in messages when message isnt ''
  return logState

replaceAll = (str, bumped, key) ->
  str.replace keywords[key].regex, bumped[keywords[key].replace]

module.exports = (bumped, plugin, cb) ->
  logState = createLogger plugin.logger
  cmd = replaceAll plugin.command, bumped, key for key of keywords

  exec cmd, (err, stdout, stderr) ->
    if err
      code = err.code
      err = true
      buffer = stderr
      type = 'error'
    else
      buffer = stdout
      type = 'success'

    logState(type, stripEof(buffer).split('\n'))
    plugin.logger.error "Process exited with code #{code}" if code
    cb err

'use strict'

stripEof = require 'strip-eof'
exec = require('child_process').exec

keywords =
  '$newVersion':
    regex: /\$newVersion/g
    replace: '_version'

  '$oldVersion':
    regex: /\$oldVersion/g
    replace: '_oldVersion'

createLogger = (logger) ->
  logState = (state, messages) ->
    logger[state] message for message in messages when message isnt ''
  return logState

replaceAll = (str, bumped, key) ->
  str.replace keywords[key].regex, bumped[keywords[key].replace]

module.exports = (bumped, plugin, cb) ->
  logState = createLogger plugin.logger
  plugin.command = replaceAll plugin.command, bumped, key for key of keywords

  exec plugin.command, (err, stdout, stderr) ->
    if err
      code = err.code
      err = true
      buffer = stderr
      type = 'error'
    else
      buffer = stdout
      type = 'success'

    logState(type, stripEof(buffer).split('\n'))
    plugin.logger.error "Process exited with code #{code}" if code
    cb err

Fix replace all under plugin command

Fix replace all under plugin command


Browser = require 'zombie'
fs = require 'fs'
path = require 'path'
URL = require 'url'

createBrowser = (options = {}) ->
  browser = new Browser
    headers:
      "X-Otter-No-Render": "true"
  browser.resources.addHandler (request, next) ->
    if not options.allowedHosts
      options.allowedHosts = []
    # Always allow local requests
    options.allowedHosts.push(URL.parse(options.baseUrl).host)

    parsedUrl = URL.parse(request.url)
    if parsedUrl.host not in options.allowedHosts
      next(new Error("Not loading #{parsedUrl.href}: #{parsedUrl.host} not in allowedHosts"))
    else
      next()

  return browser

exports.controller = (options) ->
  (req, res, next) ->
    browser = createBrowser(options)
    browser.visit options.baseUrl + req.url, (err, browser) ->
      if err
        console.log err
      if browser.error
        console.log browser.errors
      res.send browser.document.outerHTML

Browser = require 'zombie'
fs = require 'fs'
path = require 'path'
URL = require 'url'

createBrowser = (options = {}) ->
  browser = new Browser
    headers:
      "X-Otter-No-Render": "true"
  browser.resources.addHandler (request, next) ->
    allowedHosts = []
    if options.allowedHosts
      allowedHosts = allowedHosts.concat(options.allowedHosts)
    # Always allow local requests
    allowedHosts.push(URL.parse(options.baseUrl).host)

    parsedUrl = URL.parse(request.url)
    if parsedUrl.host not in allowedHosts
      err = new Error("Not loading #{parsedUrl.href}: #{parsedUrl.host} not in allowedHosts")
      console.error(err)
      next(err)
    else
      next()

  return browser

exports.controller = (options) ->
  (req, res, next) ->
    browser = createBrowser(options)
    browser.visit options.baseUrl + req.url, (err, browser) ->
      if err
        console.log err
      if browser.error
        console.log browser.errors
      res.send browser.document.outerHTML
      browser.destroy()

Copy allowedHosts and destroy browser on every render.


module.exports =
  configDefaults:
    enabled: false

  activate: (state) ->
    @migrateOldAutosaveConfig()

    rootView.on 'focusout', ".editor:not(.mini)", (event) =>
      editSession = event.targetView()?.getModel()
      @autosave(editSession)

    rootView.on 'pane:before-item-destroyed', (event, paneItem) =>
      @autosave(paneItem)

  autosave: (paneItem) ->
    paneItem?.save?() if config.get('autosave.enabled')

  migrateOldAutosaveConfig: ->
    enabled = config.get('core.autosave')
    return unless enabled?

    config.set('autosave.enabled', enabled)
    config.set('core.autosave', null)

{$} = require 'atom'

module.exports =
  configDefaults:
    enabled: false

  activate: (state) ->
    @migrateOldAutosaveConfig()

    rootView.on 'focusout', ".editor:not(.mini)", (event) =>
      editSession = event.targetView()?.getModel()
      @autosave(editSession)

    rootView.on 'pane:before-item-destroyed', (event, paneItem) =>
      @autosave(paneItem)

    $(window).preempt 'beforeunload', =>
      for pane in rootView.getPanes()
        @autosave(paneItem) for paneItem in pane.getItems()

  autosave: (paneItem) ->
    paneItem?.save?() if config.get('autosave.enabled')

  migrateOldAutosaveConfig: ->
    enabled = config.get('core.autosave')
    return unless enabled?

    config.set('autosave.enabled', enabled)
    config.set('core.autosave', null)

Save all pane items before window is closed


#    galegis-api -- Structured Importing and RESTful providing of GA General Assembly Activity.
#    Copyright (C) 2013 Matthew Farmer
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
module.exports = (jobs, db) ->
  require('./import-sessions')(jobs, db)
  require('./import-members')(jobs, db)
  require("./import-committees")(jobs, db)
  require("./import-legislation")(jobs, db)
  require("./import-votes")(jobs, db)

  jobs.process 'poll', (job, done) ->
    # Queue up jobs that should run on each poll.
    jobs.create('import sessions').save()
    jobs.create('import members').save()
    jobs.create('import committees').save()
    jobs.create('import legislation').save()
    jobs.create('import votes').save()

    # Schedule the next poll.
    # todo

    done()

  # Create initial poll
  jobs.create('poll').save()

#    galegis-api -- Structured Importing and RESTful providing of GA General Assembly Activity.
#    Copyright (C) 2013 Matthew Farmer
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
module.exports = (jobs, db) ->
  require('./import-sessions')(jobs, db)
  require('./import-members')(jobs, db)
  require("./import-committees")(jobs, db)
  require("./import-legislation")(jobs, db)
  require("./import-votes")(jobs, db)

  jobs.process 'poll', (job, done) ->
    # Queue up jobs that should run on each poll.
    jobs.create('import sessions').save()
    jobs.create('import members').save()
    jobs.create('import committees').save()
    jobs.create('import legislation').save()
    jobs.create('import votes').save()

    # Schedule the next poll.
    # todo

    done()

  # Create initial poll
  #jobs.create('poll').save()

Disable the autopoll for now.

Disable the autopoll for now.


_ = require 'underscore'
React = require 'react'
{OutlineView, ScrollRegion} = require 'nylas-component-kit'
AccountSwitcher = require './account-switcher'
SidebarStore = require '../sidebar-store'

class AccountSidebar extends React.Component
  @displayName: 'AccountSidebar'

  @containerRequired: false
  @containerStyles:
    minWidth: 165
    maxWidth: 210

  constructor: (@props) ->
    @state = @_getStateFromStores()

  componentDidMount: =>
    @unsubscribers = []
    @unsubscribers.push SidebarStore.listen @_onStoreChange

  componentWillUnmount: =>
    unsubscribe() for unsubscribe in @unsubscribers

  _onStoreChange: =>
    @setState @_getStateFromStores()

  _getStateFromStores: =>
    accounts: SidebarStore.accounts()
    focusedAccounts: SidebarStore.focusedAccounts()
    userSections: SidebarStore.userSections()
    standardSection: SidebarStore.standardSection()

  _renderUserSections: (sections) =>
    sections.map (section) =>
      <OutlineView key={section.title} {...section} />

  render: =>
    {accounts, focusedAccounts, userSections, standardSection} = @state

      <AccountSwitcher accounts={accounts} focusedAccounts={focusedAccounts} />
      <ScrollRegion className="account-sidebar" >

          <OutlineView {...standardSection} />
          {@_renderUserSections(userSections)}

      </ScrollRegion>

module.exports = AccountSidebar

_ = require 'underscore'
React = require 'react'
{OutlineView, ScrollRegion, Flexbox} = require 'nylas-component-kit'
AccountSwitcher = require './account-switcher'
SidebarStore = require '../sidebar-store'

class AccountSidebar extends React.Component
  @displayName: 'AccountSidebar'

  @containerRequired: false
  @containerStyles:
    minWidth: 165
    maxWidth: 210

  constructor: (@props) ->
    @state = @_getStateFromStores()

  componentDidMount: =>
    @unsubscribers = []
    @unsubscribers.push SidebarStore.listen @_onStoreChange

  componentWillUnmount: =>
    unsubscribe() for unsubscribe in @unsubscribers

  _onStoreChange: =>
    @setState @_getStateFromStores()

  _getStateFromStores: =>
    accounts: SidebarStore.accounts()
    focusedAccounts: SidebarStore.focusedAccounts()
    userSections: SidebarStore.userSections()
    standardSection: SidebarStore.standardSection()

  _renderUserSections: (sections) =>
    sections.map (section) =>
      <OutlineView key={section.title} {...section} />

  render: =>
    {accounts, focusedAccounts, userSections, standardSection} = @state

    <Flexbox direction="column" style={order: 0, flexShrink: 1, flex: 1}>
      <AccountSwitcher accounts={accounts} focusedAccounts={focusedAccounts} />
      <ScrollRegion className="account-sidebar" style={order: 2}>
        <div className="account-sidebar-sections">
          <OutlineView {...standardSection} />
          {@_renderUserSections(userSections)}
        </div>
      </ScrollRegion>
    </Flexbox>

module.exports = AccountSidebar

Change the sidebar to use Flexbox for container


color = require('colors')
module.exports = (failure) ->
  return format(failure)

format = (failure) ->
  message = shorten(failure, 5)
  colorFirstLine(message)

shorten = (message, numlines) ->
  message.split('\n').splice(0, numlines).join('\n')

colorFirstLine = (message) ->
  split = message.split('\n')
  split[0] = split[0].blue
  split.join('\n')

color = require('colors')
module.exports = (failure) ->
  return format(failure)

format = (failure) ->
  message = shorten(failure, 5)
  colorFirstLine(message)

shorten = (message, numlines) ->
  message.split('\n').splice(0, numlines).join('\n')

colorFirstLine = (message) ->
  split = message.split('\n')
  split[0] = split[0].red.inverse
  split.join('\n')

Change error formatter to red

Change error formatter to red


_ = require 'underscore'

module.exports = App =
  windows: []
  root: OSX.NSBundle.mainBundle.resourcePath

  activeWindow: null

  setActiveWindow: (window) ->
    @activeWindow = window
    @windows.push window if window not in @windows

  # path - Optional. The String path to the file to base it on.
  newWindow: (path) ->
    c = OSX.AtomWindowController.alloc.initWithWindowNibName "AtomWindow"
    c.window
    c.window.makeKeyAndOrderFront null

  # Returns null or a file path.
  openPanel: ->
    panel = OSX.NSOpenPanel.openPanel
    panel.setCanChooseDirectories true
    if panel.runModal isnt OSX.NSFileHandlingPanelOKButton
      return null
    panel.filenames.lastObject

  openURL: (url) ->
    window.location = url
    @activeWindow.setTitle _.last url.replace(/\/$/,'').split '/'

  # Returns null or a file path.
  savePanel: ->
    panel = OSX.NSSavePanel.savePanel
    if panel.runModal isnt OSX.NSFileHandlingPanelOKButton
      return null
    panel.filenames.lastObject

  writeToPasteboard: (text) ->
    pb = OSX.NSPasteboard.generalPasteboard
    pb.declareTypes_owner [OSX.NSStringPboardType], null
    pb.setString_forType text, OSX.NSStringPboardType

_ = require 'underscore'

module.exports = App =
  windows: []
  root: OSX.NSBundle.mainBundle.resourcePath

  activeWindow: null

  setActiveWindow: (window) ->
    @activeWindow = window
    @windows.push window if window not in @windows

  # path - Optional. The String path to the file to base it on.
  newWindow: (path) ->
    c = OSX.AtomWindowController.alloc.initWithWindowNibName "AtomWindow"
    c.window
    c.window.makeKeyAndOrderFront null

  # Returns null or a file path.
  openPanel: ->
    panel = OSX.NSOpenPanel.openPanel
    panel.setCanChooseDirectories true
    if panel.runModal isnt OSX.NSFileHandlingPanelOKButton
      return null
    filename = panel.filenames.lastObject
    localStorage.lastOpenedFilename = filename
    filename

  openURL: (url) ->
    window.location = url
    @activeWindow.setTitle _.last url.replace(/\/$/,'').split '/'

  # Returns null or a file path.
  savePanel: ->
    panel = OSX.NSSavePanel.savePanel
    if panel.runModal isnt OSX.NSFileHandlingPanelOKButton
      return null
    panel.filenames.lastObject

  writeToPasteboard: (text) ->
    pb = OSX.NSPasteboard.generalPasteboard
    pb.declareTypes_owner [OSX.NSStringPboardType], null
    pb.setString_forType text, OSX.NSStringPboardType

Store the last opened path.

Store the last opened path.

Just throwing stuff into localStorage seems
sloppy. Maybe we just need some guidelines to
follow.


Point = require 'point'
$ = require 'jquery'
BufferedProcess = require 'buffered-process'

module.exports =
class TagGenerator
  constructor: (@path) ->

  parseTagLine: (line) ->
    sections = line.split('\t')
    if sections.length > 3
      position: new Point(parseInt(sections[2]) - 1)
      name: sections[0]
    else
      null

  generate: ->
    deferred = $.Deferred()
    tags = []
    command = require.resolve('ctags')
    args = ['--fields=+KS', '-nf', '-', @path]
    stdout = (lines) =>
      for line in lines.split('\n')
        tag = @parseTagLine(line)
        tags.push(tag) if tag
    exit = ->
      deferred.resolve(tags)
    new BufferedProcess({command, args, stdout, exit})
    deferred

Point = require 'point'
$ = require 'jquery'
BufferedProcess = require 'buffered-process'
fs = require 'fs-utils'

module.exports =
class TagGenerator
  constructor: (@path) ->

  parseTagLine: (line) ->
    sections = line.split('\t')
    if sections.length > 3
      position: new Point(parseInt(sections[2]) - 1)
      name: sections[0]
    else
      null

  generate: ->
    deferred = $.Deferred()
    tags = []
    command = fs.resolveOnLoadPath('ctags')
    args = ['--fields=+KS', '-nf', '-', @path]
    stdout = (lines) =>
      for line in lines.split('\n')
        tag = @parseTagLine(line)
        tags.push(tag) if tag
    exit = ->
      deferred.resolve(tags)
    new BufferedProcess({command, args, stdout, exit})
    deferred

Use fs.resolveOnLoadPath() to find ctags executable


'use strict'

### @ngInject ###
module.exports = ($scope) ->
  $scope.star = {
    corners: 5,
    spokeRatio: 0.5,
    fill: '#f0c039',
    stroke: '#e4a91a',
    skew: 0,
    randomness: 0,
    size: 100
  }

  $scope.updateBoxStyle = ->
    $scope.boxStyle = {
      display: 'inline-block',
      width:   $scope.star.size + 'px',
      height:  $scope.star.size + 'px'
    }
  $scope.updateBoxStyle()

  return

'use strict'

### @ngInject ###
module.exports = ($scope) ->
  $scope.star = {
    corners: 5,
    spokeRatio: 0.5,
    fill: '#f0c039',
    stroke: '#e4a91a',
    skew: 0,
    randomness: 0,
    size: 250
  }

  $scope.updateBoxStyle = ->
    $scope.boxStyle = {
      display: 'inline-block',
      width:   $scope.star.size + 'px',
      height:  $scope.star.size + 'px'
    }
  $scope.updateBoxStyle()

  return

Change default star size to 250px

Change default star size to 250px


Logger = require '../logger'

module.exports =
class ConsoleLogger extends Logger
  error: (statusCode, result, builder) ->
    console.group('LaTeX errors')
    switch statusCode
      when 127
        executable = 'latexmk' # TODO: Read from Builder::executable in the future.
        console.log(
          """
          %cTeXification failed! Builder executable '#{executable}' not found.

            latex.texPath
              as configured: #{atom.config.get('latex.texPath')}
              when resolved: #{builder.constructPath()}

          Make sure latex.texPath is configured correctly; either adjust it \
          via the settings view, or directly in your config.cson file.
          """, 'color: red')
      else
        console.group("TeXification failed with status code #{statusCode}")
        for error in result.errors
          console.log("%c#{error.filePath}:#{error.lineNumber}: #{error.message}", 'color: red')
        console.groupEnd()
    console.groupEnd()

  warning: (message) ->
    console.group('LaTeX warnings')
    console.log(message)
    console.groupEnd()

Logger = require '../logger'

module.exports =
class ConsoleLogger extends Logger
  error: (statusCode, result, builder) ->
    console.group('LaTeX errors')
    switch statusCode
      when 127
        executable = 'latexmk' # TODO: Read from Builder::executable in the future.
        console.log(
          """
          %cTeXification failed! Builder executable '#{executable}' not found.

            latex.texPath
              as configured: #{atom.config.get('latex.texPath')}
              when resolved: #{builder.constructPath()}

          Make sure latex.texPath is configured correctly; either adjust it \
          via the settings view, or directly in your config.cson file.
          """, 'color: red')
      else
        if result?.errors?
          console.group("TeXification failed with status code #{statusCode}")
          for error in result.errors
            console.log("%c#{error.filePath}:#{error.lineNumber}: #{error.message}", 'color: red')
          console.groupEnd()
        else
          console.log("%cTeXification failed with status code #{statusCode}", 'color: red')
    console.groupEnd()

  warning: (message) ->
    console.group('LaTeX warnings')
    console.log(message)
    console.groupEnd()

Handle undefined result from parser

:bug: Handle undefined result from parser


module.exports = (account)->

  {firstName} = account

  """

        <button class="kdbutton activity-status-context with-icon with-menu" id="kd-320">Status Update</button>

          <form class="kdformview status-widget">

<input name="dummy" type="text" class="kdinput text status-update-input warn-on-unsaved-data" placeholder="What's new #{firstName}?">

          </form>

  """

module.exports = (account)->

  {firstName} = account.profile

  """

        <button class="kdbutton activity-status-context with-icon with-menu" id="kd-320">Status Update</button>

          <form class="kdformview status-widget">

<input name="dummy" type="text" class="kdinput text status-update-input warn-on-unsaved-data" placeholder="What's new #{firstName}?">

          </form>

  """

Set first name in profile instance.

Set first name in profile instance.


'context-menu':
  'atom-text-editor': [
    {label: 'Correct Spelling', command: 'spell-check:correct-misspelling'}
  ]

'context-menu':
  'atom-text-editor:not([mini])': [
    {label: 'Correct Spelling', command: 'spell-check:correct-misspelling'}
  ]

Remove Correct Spelling from mini editor context menu


define ['jquery', 'underscore', 'backbone', 'bootstrap', 'plugins/select_range'], ($, _, Backbone) ->
  class SearchInputView extends Backbone.View

    initialize: () ->
      @$el.typeahead
        source: @getTypeaheadAddresses
        updater: (item) =>
          _.defer @afterTypeahead
          item
        minLength: 3

    getTypeaheadAddresses: (query, callback) =>
      params = $.param { query: query }
      $.getJSON "/autocomplete?#{params}", (addresses) ->
        callback(addresses)

    afterTypeahead: () =>
      idx = @$el.val().lastIndexOf(',')
      @$el.selectRange(idx) if idx? and idx > 0

    focus: () => @$el.focus()
    val: (v) => @$el.val.apply(@$el, arguments)

define ['jquery', 'underscore', 'backbone', 'bootstrap', 'plugins/select_range'], ($, _, Backbone) ->
  class SearchInputView extends Backbone.View

    initialize: () ->
      @$el.typeahead
        source: @getTypeaheadAddresses
        updater: (item) =>
          _.defer @afterTypeahead
          item
        minLength: 3
      @$el.on 'focus', => @$el.select()

    getTypeaheadAddresses: (query, callback) =>
      params = $.param { query: query }
      $.getJSON "/autocomplete?#{params}", (addresses) ->
        callback(addresses)

    afterTypeahead: () =>
      idx = @$el.val().lastIndexOf(',')
      @$el.selectRange(idx) if idx? and idx > 0

    focus: () => @$el.focus()
    val: (v) => @$el.val.apply(@$el, arguments)

Select input field's content on select event.


Sprangular.controller "HeaderCtrl", (
  $scope,
  $location,
  Cart,
  Account,
  Catalog,
  Env,
  Flash,
  Status,
  Angularytics,
  $translate
) ->

  $scope.cart = Cart
  Catalog.taxonomies().then (taxonomies) ->
    $scope.taxonomies = taxonomies
  $scope.account = Account
  $scope.env = Env
  $scope.search = {text: $location.search()['search']}

  $scope.goToMyAccount = ->
    $location.path '/account'

  $scope.logout = ->
    Account.logout()
      .then (content) ->
        Angularytics.trackEvent("Account", "Logout")
        $scope.$emit('account.logout')
        Flash.success 'app.logout_success'
        $location.path '/'

  $scope.login = ->
    $location.path '/sign-in'

  $scope.doSearch = ->
    Angularytics.trackEvent("Product", "Search", $scope.search.text)

    product = _.find $scope.lastSearch, (product) ->
                product.name == $scope.search.text

    if product
      $location.path "/products/#{product.slug}"
    else
      $location.search('search', $scope.search.text)
      $location.path "/products"

  $scope.getProducts = (search) ->
    return [] unless search
    Catalog.products(search, 1, pageSize: 3, ignoreLoadingIndicator: true)
      .then (products) ->
        $scope.lastSearch = products

Sprangular.controller "HeaderCtrl", (
  $scope,
  $location,
  Cart,
  Account,
  Catalog,
  Env,
  Flash,
  Status,
  Angularytics,
  $translate
) ->

  $scope.cart = Cart
  Catalog.taxonomies().then (taxonomies) ->
    $scope.taxonomies = taxonomies
  $scope.account = Account
  $scope.env = Env
  $scope.search = {text: $location.search()['keywords']}

  $scope.goToMyAccount = ->
    $location.path '/account'

  $scope.logout = ->
    Account.logout()
      .then (content) ->
        Angularytics.trackEvent("Account", "Logout")
        $scope.$emit('account.logout')
        Flash.success 'app.logout_success'
        $location.path '/'

  $scope.login = ->
    $location.path '/sign-in'

  $scope.doSearch = ->
    Angularytics.trackEvent("Product", "Search", $scope.search.text)

    product = _.find $scope.lastSearch, (product) ->
                product.name == $scope.search.text

    if product
      $location.path "/products/#{product.slug}"
    else
      $location.search('keywords', $scope.search.text)
      $location.path "/products"

  $scope.getProducts = (search) ->
    return [] unless search
    Catalog.products(search, 1, pageSize: 3, ignoreLoadingIndicator: true)
      .then (products) ->
        $scope.lastSearch = products

Update HeaderCtrl to use `keywords` param instead of `search`


# Description:
#   Listens for words and sometimes replies with an Arnie quote
#
# Dependencies:
#   None
#
# Commands:
#   None
#
# Author:
#   Casey Lawrence <cjlaw@users.noreply.github.com>
#

odds  = [1...100]

arnie_quotes = [
    'GET TO THE CHOPPA!',
    'Your clothes, give them to me, now!',
    'Hasta La Vista, Baby!',
    'DDDAAANNNAAAA!',
    'You are one ugly mother******.',
    'It`s not a tumor!',
    'When I said you should screw yourself. I didn`t mean it literally.',
    'Can you hurry up. My horse is getting tired.',
    'Are these all your lunches? You mean you eat other peoples` lunches? STOP IT!!',
    'I`m the party pooper.',
    'Who is your daddy and what does he do?'
]

module.exports = (robot) ->
    robot.hear /(^|\s)arnie(\s|$|[\W])/ig, (msg) ->
        val = msg.random odds
        if val > 50
            msg.send msg.random arnie_quotes

    robot.hear /(^|\s)arnold(\s|$|[\W])/ig, (msg) ->
        val = msg.random odds
        if val > 50
            msg.send msg.random arnie_quotes

# Description:
#   Listens for words and sometimes replies with an Arnie quote
#
# Dependencies:
#   None
#
# Commands:
#   None
#
# Author:
#   Casey Lawrence <casey.j.lawrence@gmail.com>
#

odds  = [1...100]

arnie_quotes = [
    'GET TO THE CHOPPA!',
    'Your clothes, give them to me, NOW!',
    'Hasta La Vista, Baby!',
    'DDDAAANNNAAAA!',
    'You are one ugly mothersucker.',
    'It`s not a tumor!',
    'When I said you should screw yourself I didn`t mean it literally.',
    'Can you hurry up. My horse is getting tired.',
    'Are these all your lunches? You mean you eat other peoples` lunches? STOP IT!!',
    'I`m the party pooper.',
    'Who is your daddy and what does he do?'
]

module.exports = (robot) ->
    robot.hear /(^|\s)arnie(\s|$|[\W])/ig, (msg) ->
        val = msg.random odds
        if val > 0 # Set Arnie to reply 100% for now
            msg.send msg.random arnie_quotes

    robot.hear /(^|\s)arnold(\s|$|[\W])/ig, (msg) ->
        val = msg.random odds
        if val > 0 # Set Arnie to reply 100% for now
            msg.send msg.random arnie_quotes

Set Arnie to reply 100% of the time (for now). Update a few Arnie quotes.


packages: [
  "advanced-open-file"
  "atom-alignment"
  "atom-beautify"
  "atom-transpose"
  "change-case"
  "color-picker"
  "docblockr"
  "editorconfig"
  "emmet"
  "expand-region"
  "git-blame"
  "language-apache"
  "language-applescript"
  "language-awk"
  "language-babel"
  "language-diff"
  "language-env"
  "language-gitattributes"
  "language-gitignore"
  "language-har"
  "language-hosts"
  "language-ini"
  "language-latex"
  "language-liquid"
  "language-lisp"
  "language-pegjs"
  "language-pip"
  "language-prolog"
  "language-sca"
  "language-svg"
  "language-tcl"
  "language-viml"
  "language-x86"
  "linter"
  "linter-coffeescript"
  "linter-eslint"
  "linter-flake8"
  "linter-jsonlint"
  "linter-php"
  "linter-shellcheck"
  "linter-ui-default"
  "monokai"
  "package-sync"
  "plist-converter"
  "resize-indent"
  "sort-lines"
  "ssh-config"
  "svg-preview"
  "tabs-to-spaces"
  "teletype"
]

packages: [
  "advanced-open-file"
  "atom-alignment"
  "atom-beautify"
  "atom-transpose"
  "change-case"
  "color-picker"
  "docblockr"
  "editorconfig"
  "emmet"
  "expand-region"
  "git-blame"
  "language-apache"
  "language-applescript"
  "language-awk"
  "language-babel"
  "language-diff"
  "language-env"
  "language-gitattributes"
  "language-gitignore"
  "language-har"
  "language-hosts"
  "language-ini"
  "language-javascript-jsx"
  "language-latex"
  "language-liquid"
  "language-lisp"
  "language-pegjs"
  "language-pip"
  "language-prolog"
  "language-sca"
  "language-svg"
  "language-tcl"
  "language-viml"
  "language-x86"
  "linter"
  "linter-coffeescript"
  "linter-eslint"
  "linter-flake8"
  "linter-jsonlint"
  "linter-php"
  "linter-shellcheck"
  "linter-ui-default"
  "monokai"
  "package-sync"
  "plist-converter"
  "resize-indent"
  "sort-lines"
  "ssh-config"
  "svg-preview"
  "tabs-to-spaces"
  "teletype"
]

Add JSX grammar to Atom

Add JSX grammar to Atom


w = require('when')
express = require('express')

Config = require('./config')
Project = require('./project')
TestCase = require('./test_case')

module.exports = () ->
  app = express()

  modules = []
  servers = []

  start: ->
    app.use express.static(Project.publicPath)

    w.all Config.ports.map (port) ->
      w.promise (resolve, reject) ->
        servers.push app.listen(port, resolve)

  use: (module) ->
    modules.push(module)

  stop: ->
    w.all servers.map (server) ->
      w.promise (resolve, reject) ->
        server.close(resolve)

  load: (name) ->
    testCase = TestCase(name)
    testCase.mount(app)

    modules.forEach (module) ->
      testCase.use(module)

    testCase

w = require('when')
express = require('express')

Config = require('./config')
Project = require('./project')
TestCase = require('./test_case')

module.exports = () ->
  app = express()

  modules = []
  servers = []
  testCases = []

  stop = ->
    promises = []

    servers.forEach (server) ->
      promises.push w.promise (resolve, reject) ->
        server.close(resolve)

    testCases.forEach (testCase) ->
      promises.push w.promise (resolve, reject) ->
        testCase.stop().then(resolve)

    w.all(promises)

  start: ->
    app.use express.static(Project.publicPath)

    process.on 'SIGINT', ->
      stop().then(process.exit)

    w.all Config.ports.map (port) ->
      w.promise (resolve, reject) ->
        servers.push app.listen(port, resolve)

  use: (module) ->
    modules.push(module)

  stop: stop

  load: (name) ->
    testCase = TestCase(name)
    testCase.mount(app)
    testCases.push(testCase)

    modules.forEach (module) ->
      testCase.use(module)

    testCase

Stop server and test cases on SIGINT

Stop server and test cases on SIGINT


@CodequestManager.module "Entities", (Entities, App, Backbone, Marionette, $, _) ->
  Entities.Order = Backbone.Model.extend

    urlRoot: ->
      "/orders"

    parse: (data) ->
      data.dishes = new Entities.Dishes data.dishes
      data.dishes.order = this
      data

    currentUserOrdered: ->
      @get('dishes').where(user_id: App.currentUser.id).length isnt 0

    changeStatus: ->
      $.ajax
        type: 'PUT'
        url: "#{@url()}/change_status"
        success: (data) =>
          @set({status: data.status})
          App.vent.trigger 'reload:current:user' if data.status is 'delivered'
          @get('dishes').reset(data.dishes, parse: true)

    total: ->
      (@get('dishes').total()+parseFloat(@get('shipping'))).toFixed(2)

    successPath: ->
      if @get('from_today')
        "/orders/today/#{@id}"
      else
        "/orders/#{@id}"

  Entities.Orders = Backbone.Collection.extend
    model: Entities.Order
    url: '/orders'

    page: 1

    more: ->
      @page += 1
      @fetch
        data:
          page: @page
        remove: false
        success: (collection, data) =>
          @trigger 'all:fetched' if data.length < App.pageSize

@CodequestManager.module "Entities", (Entities, App, Backbone, Marionette, $, _) ->
  Entities.Order = Backbone.Model.extend

    urlRoot: ->
      "/orders"

    parse: (data) ->
      data.dishes = new Entities.Dishes data.dishes
      data.dishes.order = this
      data

    currentUserOrdered: ->
      @get('dishes').where(user_id: App.currentUser.id).length isnt 0

    changeStatus: ->
      $.ajax
        type: 'PUT'
        url: "#{@url()}/change_status"
        success: (data) =>
          @set(@parse(data))
          App.vent.trigger 'reload:current:user' if data.status is 'delivered'

    total: ->
      (@get('dishes').total()+parseFloat(@get('shipping'))).toFixed(2)

    successPath: ->
      if @get('from_today')
        "/orders/today/#{@id}"
      else
        "/orders/#{@id}"

  Entities.Orders = Backbone.Collection.extend
    model: Entities.Order
    url: '/orders'

    page: 1

    more: ->
      @page += 1
      @fetch
        data:
          page: @page
        remove: false
        success: (collection, data) =>
          @trigger 'all:fetched' if data.length < App.pageSize

Reset the whole model when the status is changed


# Global helpers should be used in comments as well
window.setErrors = (model, errors) ->
  for attribute, error of errors
    $label = $("label[for=#{model}_#{attribute}]")
    $field = $("##{model}_#{attribute}")
    unless $label.size() is 0
      $label.addClass('error')
      $(errorTemplate(error[0])).insertAfter($label)
    else
      $field.addClass('error')
      $(errorTemplate(error[0])).insertAfter($field)

window.resetErrors = ->
  $('.error').removeClass('error')
  $('small.error_description').remove()

window.errorTemplate = (error) -> "<small class='error_description'>#{error}</small>"

if $("meta[content='kublog_path']").length > 0
  window.kublogPath = $("meta[content='kublog_path']").attr("name")
else
  window.kublogPath = "/blog"

# Global helpers should be used in comments as well
window.setErrors = (model, errors) ->
  for attribute, error of errors
    $label = $("label[for=#{model}_#{attribute}]")
    $field = $("##{model}_#{attribute}")
    unless $label.size() is 0
      $label.addClass('error')
      $(errorTemplate(error[0])).insertAfter($label)
    else
      $field.addClass('error')
      $(errorTemplate(error[0])).insertAfter($field)

window.resetErrors = ->
  $('.error').removeClass('error')
  $('small.error_description').remove()

window.errorTemplate = (error) -> "<small class='error_description'>#{error}</small>"

if $("meta[content='kublog_path']").length > 0
  window.kublogPath = String($("meta[content='kublog_path']").attr("name"))
else
  window.kublogPath = "/blog/"

# Bad Things(tm) could happen if we don't have a path separator
unless window.kublogPath.charAt(window.kublogPath.length-1) == '/'
  window.kublogPath = window.kublogPath.concat('/')

Fix for kublogPath, it must have a path separator.

Issue on Aventones' PivotalTrack:
https://www.pivotaltracker.com/story/show/21200167


SelectList = require 'select-list'
{$$} = require 'space-pen'

module.exports =
class GrammarView extends SelectList

  @viewClass: -> "#{super} grammar-view from-top overlay mini"

  filterKey: 'name'

  initialize: (@editor) ->
    @currentGrammar = @editor.getGrammar()
    @path = @editor.getPath()
    @autoDetect = name: 'Auto Detect'
    @command 'editor:select-grammar', =>
      @cancel()
      false
    super

    @populate()
    @attach()

  itemForElement: (grammar) ->
    if grammar is @currentGrammar
      grammarClass = 'current-grammar'
    else
      grammarClass = 'grammar'

    $$ ->
      @li grammar.name, class: grammarClass

  populate: ->
    grammars = new Array(syntax.grammars...)
    grammars.unshift(@autoDetect)
    @setArray(grammars)

  confirmed: (grammar) ->
    @cancel()
    if grammar is @autoDetect
      project.removeGrammarOverrideForPath(@path)
    else
      project.addGrammarOverrideForPath(@path, grammar)
    @editor.reloadGrammar()

  attach: ->
    super

    rootView.append(this)
    @miniEditor.focus()

SelectList = require 'select-list'
{$$} = require 'space-pen'

module.exports =
class GrammarView extends SelectList

  @viewClass: -> "#{super} grammar-view from-top overlay mini"

  filterKey: 'name'

  initialize: (@editor) ->
    @currentGrammar = @editor.getGrammar()
    @path = @editor.getPath()
    @autoDetect = name: 'Auto Detect'
    @command 'editor:select-grammar', =>
      @cancel()
      false
    super

    @populate()
    @attach()

  itemForElement: (grammar) ->
    if grammar is @currentGrammar
      grammarClass = 'current-grammar'
    else
      grammarClass = 'grammar'

    $$ ->
      @li grammar.name, class: grammarClass

  populate: ->
    grammars = new Array(syntax.grammars...)
    grammars.sort (grammarA, grammarB) ->
      if grammarA.scopeName is 'text.plain'
        -1
      else if grammarB.scopeName is 'text.plain'
        1
      else if grammarA.name < grammarB.name
        -1
      else if grammarA.name > grammarB.name
        1
      else
        0
    grammars.unshift(@autoDetect)
    @setArray(grammars)

  confirmed: (grammar) ->
    @cancel()
    if grammar is @autoDetect
      project.removeGrammarOverrideForPath(@path)
    else
      project.addGrammarOverrideForPath(@path, grammar)
    @editor.reloadGrammar()

  attach: ->
    super

    rootView.append(this)
    @miniEditor.focus()

Sort grammars by name in select list

Sort grammars by name in select list


window.Tahi ||= {}

class Tahi.RichEditableElement
  constructor: (@element) ->
    @instance = CKEDITOR.inline @element,
      extraPlugins: 'sharedspace'
      removePlugins: 'floatingspace,resize'
      sharedSpaces:
        top: 'toolbar'
      toolbar: [
        [ 'Format' ]
        [ 'Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat' ]
        [ 'NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', 'Table' ]
        [ 'PasteFromWord' ],
        [ 'Link', 'Unlink' ]
        [ 'Replace', '-', 'Scayt' ]
      ]
      format_tags: 'h2;h3;h4;h5;h6;p;div;pre;address'

    @placeholderText = @element.attributes['placeholder'].value
    @setPlaceholder()
    @instance.on 'focus', => @clearPlaceholder()
    @instance.on 'blur', => @setPlaceholder()

  setPlaceholder: ->
    text = $($.parseHTML(@instance.getData())).text().trim()
    if text == '' || text == @placeholderText
      @instance.element.addClass 'placeholder'
      @instance.setData @placeholderText

  clearPlaceholder: ->
    text = $($.parseHTML(@instance.getData())).text().trim()
    if text == @placeholderText
      @instance.element.removeClass 'placeholder'
      @instance.setData ''

window.Tahi ||= {}

class Tahi.RichEditableElement
  constructor: (@element) ->
    @instance = CKEDITOR.inline @element,
      extraPlugins: 'sharedspace'
      removePlugins: 'floatingspace,resize'
      sharedSpaces:
        top: 'toolbar'
      scayt_autoStartup: true
      toolbar: [
        [ 'Format' ]
        [ 'Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat' ]
        [ 'NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', 'Table' ]
        [ 'PasteFromWord' ],
        [ 'Link', 'Unlink' ]
        [ 'Replace' ]
      ]
      format_tags: 'h2;h3;h4;h5;h6;p;div;pre;address'

    @placeholderText = @element.attributes['placeholder'].value
    @setPlaceholder()
    @instance.on 'focus', => @clearPlaceholder()
    @instance.on 'blur', => @setPlaceholder()

  setPlaceholder: ->
    text = $($.parseHTML(@instance.getData())).text().trim()
    if text == '' || text == @placeholderText
      @instance.element.addClass 'placeholder'
      @instance.setData @placeholderText

  clearPlaceholder: ->
    text = $($.parseHTML(@instance.getData())).text().trim()
    if text == @placeholderText
      @instance.element.removeClass 'placeholder'
      @instance.setData ''

Remove Scayt and enable auto spelling from CKEditor

[Finishes #61853878]


#= require ../../set/set_sort

class Batman.AssociationSet extends Batman.SetSort
  constructor: (@foreignKeyValue, @association) ->
    base = new Batman.Set
    super(base, 'hashKey')
  loaded: false
  load: (callback) ->
    return callback(undefined, @) unless @foreignKeyValue?
    @association.getRelatedModel().load @_getLoadOptions(), (err, records) =>
      @loaded = true unless err
      @fire 'loaded'
      callback(err, @)
  _getLoadOptions: ->
    loadOptions = {}
    loadOptions[@association.foreignKey] = @foreignKeyValue
    loadOptions

#= require ../../set/set_sort

class Batman.AssociationSet extends Batman.SetSort
  constructor: (@foreignKeyValue, @association) ->
    base = new Batman.Set
    super(base, 'hashKey')
  loaded: false
  load: (callback) ->
    return callback(undefined, @) unless @foreignKeyValue?
    @association.getRelatedModel().load @_getLoadOptions(), (err, records) =>
      unless err
        @set 'loaded', true
        @loaded = true
      @fire 'loaded'
      callback(err, @)
  _getLoadOptions: ->
    loadOptions = {}
    loadOptions[@association.foreignKey] = @foreignKeyValue
    loadOptions

  @accessor 'loaded', Batman.Property.defaultAccessor

Set an eccessor on AssociationSets so we can do data-hideif: asssociation.loaded


angular.module 'qbn.edsl', ['qbn.quality', 'qbn.storylet', 'qbn.choice']
  .factory 'qbnEdsl', (qualities, storylets, frontalChoices, choiceFactory) ->
    api =
      quality: (id, name, description, args = {}) ->
        {defaultValue, defaultProgress, maxProgress, hasProgress, progressEscalation,
         visible} = args
        defaultValue ?= 0
        defaultProgress ?= 0
        maxProgress ?= if hasProgress then 100 else 0
        progressEscalation ?= 0.10
        visible ?= true
        qualities.register id, name, description, defaultValue,
                                defaultProgress, maxProgress, progressEscalation,
                                visible
        return
      storylet: (id, title, text, choices...) ->
        storylets.register id, title, text, choices
        return
      choice: (id, title, text, next, args = {}) ->
        {visibleReqs, activeReqs} = args
        visibleReqs ?= {}
        activeReqs ?= {}
        choiceFactory id, title, text, visibleReqs, activeReqs, next
      front: (choice) ->
        frontalChoices.register choice
        return
    return Object.freeze api

angular.module 'qbn.edsl', ['qbn.quality', 'qbn.storylet', 'qbn.choice']
  .factory 'qbnEdsl', (qualities, storylets, frontalChoices, choiceFactory) ->
    api =
      quality: (id, name, description, args = {}) ->
        {value, progress, maxProgress, hasProgress, progressEscalation,
         visible} = args
        value ?= 0
        progress ?= 0
        maxProgress ?= if hasProgress then 100 else 0
        progressEscalation ?= 0.10
        visible ?= true
        qualities.register id, name, description, value,
                           progress, maxProgress, progressEscalation,
                           visible
        return
      storylet: (id, title, text, choices...) ->
        storylets.register id, title, text, choices
        return
      choice: (id, title, text, next, args = {}) ->
        {visibleReqs, activeReqs} = args
        visibleReqs ?= {}
        activeReqs ?= {}
        choiceFactory id, title, text, visibleReqs, activeReqs, next
      front: (choice) ->
        frontalChoices.register choice
        return
    return Object.freeze api

Improve Names of Quality EDSL Parameters


# variant autocompletion

variantTemplate = HandlebarsTemplates["variants/autocomplete"]

formatVariantResult = (variant) ->
  variantTemplate(
    variant: variant
  )

$.fn.variantAutocomplete = (searchOptions = {}) ->
  @select2
    placeholder: Spree.translations.variant_placeholder
    minimumInputLength: 3
    initSelection: (element, callback) ->
      Spree.ajax
        url: Spree.routes.variants_api + "/" + element.val()
        success: callback
    ajax:
      url: Spree.routes.variants_api
      datatype: "json"
      quietMillis: 500
      params: { "headers": { "X-Spree-Token": Spree.api_key } }
      data: (term, page) =>
        searchData =
          q:
            product_name_or_sku_cont: term
          token: Spree.api_key
        _.extend(searchData, searchOptions)

      results: (data, page) ->
        window.variants = data["variants"]
        results: data["variants"]

    formatResult: formatVariantResult
    formatSelection: (variant, container, escapeMarkup) ->
      if !!variant.options_text
        Select2.util.escapeMarkup("#{variant.name} (#{variant.options_text}")
      else
        Select2.util.escapeMarkup(variant.name)

# variant autocompletion

variantTemplate = HandlebarsTemplates["variants/autocomplete"]

formatVariantResult = (variant) ->
  variantTemplate(
    variant: variant
  )

$.fn.variantAutocomplete = (searchOptions = {}) ->
  @select2
    placeholder: Spree.translations.variant_placeholder
    minimumInputLength: 3
    initSelection: (element, callback) ->
      Spree.ajax
        url: Spree.routes.variants_api + "/" + element.val()
        success: callback
    ajax:
      url: Spree.routes.variants_api
      datatype: "json"
      quietMillis: 500
      params: { "headers": { "X-Spree-Token": Spree.api_key } }
      data: (term, page) =>
        searchData =
          q:
            product_name_or_sku_cont: term
          token: Spree.api_key
        _.extend(searchData, searchOptions)

      results: (data, page) ->
        window.variants = data["variants"]
        results: data["variants"]

    formatResult: formatVariantResult
    formatSelection: (variant, container, escapeMarkup) ->
      if variant.options_text
        Select2.util.escapeMarkup("#{variant.name} (#{variant.options_text})")
      else
        Select2.util.escapeMarkup(variant.name)

Fix missing close paren in variantAutocomplete


#
# 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'
if my.online
  _.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'
else
  rx = require './test/rx_mock'
sys = require 'sys'

# Dependencies

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

game_dict = game({name: 'example', level: 1})
config = layout(game_dict)
world = god(rx, config)
#console.log "root world", my.inspect(world)

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'
if my.online
  _.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'
else
  rx = require './render/rx_mock'
sys = require 'sys'

# Dependencies

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

game_dict = game({name: 'example', level: 1})
config = layout(game_dict)
world = god(rx, config)
#console.log "root world", my.inspect(world)

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

Move tests next to their modules

Move tests next to their modules


do ($ = jQuery, config = @edsc.config) ->

  $(document).on 'click', 'a[data-pulse]', ->
    $dest = $($(this).attr('data-pulse'))
    $dest.animate(color: '#00ffff').animate(color: 'inherit')

  # Remove buttons in tables remove their rows
  $(document).on 'click', 'tr a[title="remove"]', ->
    $(this).closest('tr').remove()

  $(document).on 'click', 'tr a[title="Remove Project"]', ->
    $(this).closest('tr').remove()
    if $('tbody tr').length == 0
      $('.data-access-content').html('
No saved projects
')

  $(document).on 'click', 'a[href="#"]', (e) ->
    e.preventDefault()

  # flash the green save icon
  $(document).on 'edsc.saved', ->
    check = $('.save-success')
    check.show()
    setTimeout((-> check.fadeOut()), config.defaultAnimationDurationMs)

  $(document).ready ->
    $(document.body).tooltip({ selector: '[data-tooltip="true"]', placement: 'auto left' });

do (document, window, $ = jQuery, config = @edsc.config) ->

  $(document).on 'click', 'a[data-pulse]', ->
    $dest = $($(this).attr('data-pulse'))
    $dest.animate(color: '#00ffff').animate(color: 'inherit')

  # Remove buttons in tables remove their rows
  $(document).on 'click', 'tr a[title="remove"]', ->
    $(this).closest('tr').remove()

  $(document).on 'click', 'tr a[title="Remove Project"]', ->
    $(this).closest('tr').remove()
    if $('tbody tr').length == 0
      $('.data-access-content').html('
No saved projects
')

  $(document).on 'click', 'a[href="#"]', (e) ->
    e.preventDefault()

  # flash the green save icon
  $(document).on 'edsc.saved', ->
    check = $('.save-success')
    check.show()
    setTimeout((-> check.fadeOut()), config.defaultAnimationDurationMs)

  $(document).ready ->
    $(document.body).tooltip({ selector: '[data-tooltip="true"]', placement: 'auto left' });

  $(document).on 'click', 'a.sign-in', ->
    this.setAttribute('href',  "/login?next_point=#{encodeURIComponent(window.location.href)}")

Fix URS redirect location in IE9

EDSC-492: Fix URS redirect location in IE9


Steam.Xhr = (_) ->
  createResponse = (status, data, xhr) ->
    status: status, data: data, xhr: xhr

  link$ _.invokeH2O, (method, path, go) ->
    $.getJSON path
      .done (data, status, xhr) ->
        go null, createResponse status, data, xhr
      .fail (xhr, status, error) ->
        go createResponse status, xhr.responseJSON, xhr

Steam.Xhr = (_) ->
  createResponse = (status, data, xhr) ->
    status: status, data: data, xhr: xhr

  handleResponse = (go, jqxhr) ->
    jqxhr
      .done (data, status, xhr) ->
        go null, createResponse status, data, xhr
      .fail (xhr, status, error) ->
        go createResponse status, xhr.responseJSON, xhr

  link$ _.h2oGet, (path, go) ->
    handleResponse go, $.getJSON path

  link$ _.h2oPost, (path, opts, go) ->
    handleResponse go, $.post path, opts

Add POST request support to client proxy


a = DS.attr
ETahi.Author = DS.Model.extend
  authorGroup: DS.belongsTo('authorGroup')

  firstName: a('string')
  middleInitial: a('string')
  lastName: a('string')
  fullName: (->
     "#{@get('firstName')} #{@get('middleInitial') || ''} #{@get('lastName')}"
  ).property('firstName', 'middleInitial', 'lastName')

  email: a('string')

  title: a('string')
  department: a('string')
  affiliation: a('string')
  secondaryAffiliation: a('string')

  corresponding: a('boolean')
  deceased: a('boolean')
  position: a('number')

a = DS.attr
ETahi.Author = DS.Model.extend
  authorGroup: DS.belongsTo('authorGroup')

  firstName: a('string')
  middleInitial: a('string')
  lastName: a('string')
  fullName: (->
    [@get('firstName'), @get('middleInitial'), @get('lastName')].compact().join(' ')
  ).property('firstName', 'middleInitial', 'lastName')

  email: a('string')

  title: a('string')
  department: a('string')
  affiliation: a('string')
  secondaryAffiliation: a('string')

  corresponding: a('boolean')
  deceased: a('boolean')
  position: a('number')

Fix full name computed property * There was a redundant space getting added when the middle initial is absent


class @ItemCheckInMode extends ItemCheckoutMode
  ModeSwitcher.registerEntryPoint("vendor_check_in", @)

  glyph: -> "import"
  title: -> "Vendor Check-In"

  constructor: (args..., query) ->
    super
    @currentVendor = null
    @itemIndex = 1

  actions: -> [
    ['', (code) =>
      code = fixToUppercase(code)
      Api.item_checkin(
        code: code
      ).then(@onResultSuccess, @onResultError)
    ]
    [@commands.logout, @onLogout]
  ]

  onResultSuccess: (data) =>
    if data.vendor != @currentVendor
      @currentVendor = data.vendor
      Api.vendor_get(id: @currentVendor).done((vendor) =>
        vendorInfoRow = $('
')
        $('td', vendorInfoRow).append(new VendorInfo(vendor).render())
        @receipt.body.prepend(vendorInfoRow)

        row = @createRow(@itemIndex++, data.code, data.name, data.price)
        @receipt.body.prepend(row)
      )
    else
      row = @createRow(@itemIndex++, data.code, data.name, data.price)
      @receipt.body.prepend(row)
    @notifySuccess()

  onResultError: (jqXHR) =>
    if jqXHR.status == 404
      safeAlert("No such item")
      return
    safeAlert("Error:" + jqXHR.responseText)
    return true

class @ItemCheckInMode extends ItemCheckoutMode
  ModeSwitcher.registerEntryPoint("vendor_check_in", @)

  glyph: -> "import"
  title: -> "Vendor Check-In"

  constructor: (args..., query) ->
    super
    @currentVendor = null
    @itemIndex = 1

  actions: -> [
    ['', (code) =>
      code = fixToUppercase(code)
      Api.item_checkin(
        code: code
      ).then(@onResultSuccess, @onResultError)
    ]
    [@commands.logout, @onLogout]
  ]

  onResultSuccess: (data) =>
    if data.vendor != @currentVendor
      @currentVendor = data.vendor
      Api.vendor_get(id: @currentVendor).done((vendor) =>
        vendorInfoRow = $('
')
        $('td', vendorInfoRow).append(new VendorInfo(vendor).render())
        @receipt.body.prepend(vendorInfoRow)

        row = @createRow(@itemIndex++, data.code, data.name, data.price)
        @receipt.body.prepend(row)
      ).fail(@onResultError)
    else
      row = @createRow(@itemIndex++, data.code, data.name, data.price)
      @receipt.body.prepend(row)
    @notifySuccess()

  onResultError: (jqXHR) =>
    if jqXHR.status == 404
      safeAlert("No such item")
      return
    safeAlert("Error:" + jqXHR.responseText)
    return true

Add one extra failure handling for item checkin mode.

A successfull request has just been made before this call, but added
just to be safe.


module.exports = App.Bookmark = DS.Model.extend
  name: DS.attr()
  url: DS.attr()

module.exports = App.Bookmark = DS.Model.extend
  url: DS.attr()

Remove name attr from bookmakrk

Remove name attr from bookmakrk


# Description:
#   Allows Hubot to pull down images from calmingmanatee.com
#
# Dependencies:
#   "htmlparser": "1.7.6"
#   "soupselect": "0.2.0"
#
# Configuration:
#   None
#
# Commands:
#   hubot manatee - outputs a random manatee
#
# Author:
#   Danny Lockard

Select = require( "soupselect" ).select
HTMLParser = require "htmlparser"

module.exports = (robot) ->
        robot.respond /manatee/i, (msg) ->
                options = {
                        "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6"
                }
                msg
                        .http( 'http://calmingmanatee.com' )
                        .header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6')
                        .get(options) (err, res, body) ->
                                if err
                                        msg.send "Something went wrong #{err}"
                                        return
                                msg.send "http://calmingmanatee.com/" + get_manatee(body, "body div#holder img")

get_manatee = (body, selector)->
        html_handler = new HTMLParser.DefaultHandler((()->), ignoreWhitespace: true)
        html_parser = new HTMLParser.Parser html_handler

        html_parser.parseComplete body
        Select(html_handler.dom, selector)[0].attribs.src

# Description:
#   Allows Hubot to pull down images from calmingmanatee.com
#
# Dependencies:
#   None
#
# Configuration:
#   None
#
# Commands:
#   hubot manatee - outputs a random manatee
#
# Author:
#   Danny Lockard

module.exports = (robot) ->
        robot.respond /manatee/i, (msg) ->
                msg
                        .http( 'http://calmingmanatee.com' )
                        .headers('User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6')
                        .get() (err, res, body) ->
                                if err
                                        msg.send "Something went wrong #{err}"
                                        return

                                url = res.headers.location
                                manatee_no = url.substring(url.lastIndexOf("/") + 1)

                                msg.send "http://calmingmanatee.com/img/manatee#{manatee_no}.jpg"

Fix Manatee script: Heed location in redirect


{expect} = require "chai"
utils = require "../utils"

{Collections} = utils.require "common/base"

describe "categorical mapper", ->
  factors = ["foo", "bar", "baz"]
  start = 20
  end = 80

  testMapping = (key, expected) ->
    mapper = Collections("CategoricalMapper").create
      source_range: Collections("FactorRange").create factors: factors
      target_range: Collections("Range1d").create start: start, end: end
    expect(mapper.map_to_target key).to.equal expected

  it "should map first category to bottom third", ->
    testMapping "foo", 30

  it "should map second category to middle", ->
    testMapping "bar", 50

  it "should map third category to upper third", ->
    testMapping "baz", 70

{expect} = require "chai"
utils = require "../utils"

{Collections} = utils.require "common/base"

describe "categorical mapper", ->
  # FIXME Would be nice to randomize the numbers
  factors = ["foo", "bar", "baz"]
  start = 20
  end = 80

  testMapping = (key, expected) ->
    mapper = Collections("CategoricalMapper").create
      source_range: Collections("FactorRange").create factors: factors
      target_range: Collections("Range1d").create start: start, end: end
    expect(mapper.map_to_target key).to.equal expected

  it "should map first category to bottom third", ->
    testMapping "foo", 30

  it "should map second category to middle", ->
    testMapping "bar", 50

  it "should map third category to upper third", ->
    testMapping "baz", 70

Add a FIXME for someone who wants a low hanging fruit


angular.module('doubtfire.common.grade-icon', [])

.directive 'gradeIcon', ->
  restrict: 'E'
  replace: true
  templateUrl: 'common/partials/templates/grade-icon.tpl.html'
  scope:
    inputGrade: '=?grade'
  controller: ($scope, gradeService) ->
    $scope.grade = if _.isString($scope.inputGrade) then gradeService.grades.indexOf($scope.inputGrade) else $scope.inputGrade
    $scope.gradeText = (grade) ->
      if $scope.grade? then gradeService.grades[$scope.grade] or "Grade"
    $scope.gradeLetter = (grade) ->
      gradeService.gradeAcronyms[$scope.gradeText(grade)] or 'G'

angular.module('doubtfire.common.grade-icon', [])

.directive 'gradeIcon', ->
  restrict: 'E'
  replace: true
  templateUrl: 'common/partials/templates/grade-icon.tpl.html'
  scope:
    inputGrade: '=?grade'
  controller: ($scope, gradeService) ->
    $scope.$watch 'inputGrade', (newGrade) ->
      return unless newGrade?
      $scope.grade = if _.isString($scope.inputGrade) then gradeService.grades.indexOf($scope.inputGrade) else $scope.inputGrade
      $scope.gradeText = (grade) ->
        if $scope.grade? then gradeService.grades[$scope.grade] or "Grade"
      $scope.gradeLetter = (grade) ->
        gradeService.gradeAcronyms[$scope.gradeText(grade)] or 'G'

FIX: Make grade icon responsive to new input grades


Settings = require '../lib/settings.coffee'

describe "Settings", ->

  describe ".load(settings)", ->
    it "Loads the settings provided", ->
      settings = new Settings()
      settings.load({"foo.bar.baz": 42})

      expect(atom.config.get("foo.bar.baz")).toBe 42

  describe ".load(settings) with a 'scope' option", ->
    it "Loads the settings for the scope", ->
      settings = new Settings()
      scopedSettings =
        "*":
          "foo.bar.baz": 42
        ".source.coffee":
          "foo.bar.baz": 84
      settings.load(scopedSettings)

      expect(atom.config.get("foo.bar.baz")).toBe 42
      expect(atom.config.get("foo.bar.baz", {scope:[".source.coffee"]})).toBe 84
      expect(atom.config.get("foo.bar.baz", {scope:[".text"]})).toBe 42

Settings = require '../lib/settings'

describe "Settings", ->

  describe ".load(settings)", ->
    it "Loads the settings provided if they are flat", ->
      settings = new Settings()
      settings.load({"foo.bar.baz": 42})

      expect(atom.config.get("foo.bar.baz")).toBe 42

    it "Loads the settings provided if they are an object", ->
      settings = new Settings()
      expect(atom.config.get('foo.bar.baz')).toBe undefined
      settings.load({
        foo:
          bar:
            baz: 42
      })
      expect(atom.config.get('foo.bar.baz')).toBe 42

  describe ".load(settings) with a 'scope' option", ->
    it "Loads the settings for the scope", ->
      settings = new Settings()
      scopedSettings =
        "*":
          "foo.bar.baz": 42
        ".source.coffee":
          "foo.bar.baz": 84
      settings.load(scopedSettings)

      expect(atom.config.get("foo.bar.baz")).toBe 42
      expect(atom.config.get("foo.bar.baz", {scope:[".source.coffee"]})).toBe 84
      expect(atom.config.get("foo.bar.baz", {scope:[".text"]})).toBe 42

Add test for nested settings

Add test for nested settings


React = require 'react-atom-fork'
{div} = require 'reactionary-atom-fork'

module.exports = React.createClass
  getInitialState: ->
    columnsWidths: []
    columnsAligns: []

  render: ->
    {table, parentView} = @props
    {columnsWidths, columnsAligns} = @state

    cells = []
    for column,index in table.getColumns()
      classes = ['table-edit-header-cell']
      classes.push 'active' if parentView.isActiveColumn(index)

      cells.push div {
        className: classes.join(' ')
        style:
          width: columnsWidths[index]
          'text-align': columnsAligns[index] ? 'left'
      }, column.name

    div className: 'table-edit-header-row', cells

React = require 'react-atom-fork'
{div} = require 'reactionary-atom-fork'

module.exports = React.createClass
  getInitialState: ->
    columnsWidths: []
    columnsAligns: []

  render: ->
    {table, parentView} = @props
    {columnsWidths, columnsAligns} = @state

    cells = []
    for column,index in table.getColumns()
      classes = ['table-edit-header-cell']
      classes.push 'active' if parentView.isActiveColumn(index)

      cells.push div {
        key: "header-cell-#{index}"
        className: classes.join(' ')
        style:
          width: columnsWidths[index]
          'text-align': columnsAligns[index] ? 'left'
      }, column.name

    div className: 'table-edit-header-row', cells

:bug: Fix missing key attribute for column header cell


jQuery = require 'jquery'
_ = require 'underscore'

exports.monthAbbr = (monthInt) ->
    switch monthInt
        when 0 then 'Jan'
        when 1 then 'Feb'
        when 2 then 'Mar'
        when 3 then 'Apr'
        when 4 then 'May'
        when 5 then 'Jun'
        when 6 then 'Jul'
        when 7 then 'Aug'
        when 8 then 'Sep'
        when 9 then 'Oct'
        when 10 then 'Nov'
        when 11 then 'Dec'

exports.statusColor = (status) ->
    switch status
        when 'evaluating' then 'warning'
        when 'approved' then 'info'
        when 'paid' then 'success'
        when 'incomplete', 'rejected' then 'danger'
        else ''

exports.pageNumbers = (numPages, currentPage, options) ->
    # Set default options
    options = options ? {}
    leftEdge = options.leftEdge ? 2
    leftCurrent = options.leftCurrent ? 2
    rightCurrent = options.rightCurrent ? 5
    rightEdge = options.rightEdge ? 2

    pages = []
    for page in [1..numPages]
        if page <= leftEdge
            pages.push page
        else if (currentPage - leftCurrent) <= page < (currentPage + rightCurrent)
            pages.push page
        else if numPages - rightEdge < page
            pages.push page
        else if pages[pages.length - 1] != null
            pages.push null
    return pages

jQuery = require 'jquery'
_ = require 'underscore'

exports.statusColor = (status) ->
    switch status
        when 'evaluating' then 'warning'
        when 'approved' then 'info'
        when 'paid' then 'success'
        when 'incomplete', 'rejected' then 'danger'
        else ''

exports.pageNumbers = (numPages, currentPage, options) ->
    # Set default options
    options = options ? {}
    leftEdge = options.leftEdge ? 2
    leftCurrent = options.leftCurrent ? 2
    rightCurrent = options.rightCurrent ? 5
    rightEdge = options.rightEdge ? 2

    pages = []
    for page in [1..numPages]
        if page <= leftEdge
            pages.push page
        else if (currentPage - leftCurrent) <= page < (currentPage + rightCurrent)
            pages.push page
        else if numPages - rightEdge < page
            pages.push page
        else if pages[pages.length - 1] != null
            pages.push null
    return pages

Remove obsolete month shortening function


VoluntaryOnEmberjs.ProfileRankingsRoute = Ember.Route.extend
  model: (params) ->
    @controllerFor('profile.rankings').set('adjective', params.adjective)
    @controllerFor('profile.rankings').set('negativeAdjective', params.negative_adjective)
    @controllerFor('profile.rankings').set('topic', params.topic)
    @controllerFor('profile.rankings').set('scope', params.scope)

    VoluntaryOnEmberjs.UserRankingItem.find
      user_id: VoluntaryOnEmberjs.currentUser['id']
      thingType: attributes['thingType'], adjective: attributes['adjective'],
      negativeAdjective: attributes['negativeAdjective'], topic: attributes['topic'],
      scope: attributes['scope']

  renderTemplate: ->
    @render 'voluntary_ranking/templates/user/rankings/show'

VoluntaryOnEmberjs.ProfileRankingsRoute = Ember.Route.extend
  model: (params) ->
    @controllerFor('profile.rankings').set('yourRanking', true); @controllerFor('profile.rankings').set('yourRankingClass', 'btn active');
    @controllerFor('profile.rankings').set('globalRankingClass', 'btn')
    @controllerFor('profile.rankings').set('adjective', params.adjective)
    @controllerFor('profile.rankings').set('negativeAdjective', params.negative_adjective)
    @controllerFor('profile.rankings').set('topic', params.topic)
    @controllerFor('profile.rankings').set('scope', params.scope)
    VoluntaryOnEmberjs.UserRankingItem.find
      user_id: VoluntaryOnEmberjs.User.current().id, adjective: params.adjective,
      negative_adjective: params.negative_adjective, topic: params.topic,
      scope: params.scope

  renderTemplate: ->
    @render 'voluntary_ranking/templates/user/rankings/show'

Set yourRanking to false. Use params to request model. Use new current user API.


"*":
  core:
    themes: [
      "one-light-ui"
      "solarized-dark-syntax"
    ]
  editor:
    fontSize: 16
    invisibles: {}
    showIndentGuide: true
    showInvisibles: true
  "exception-reporting":
    userId: "76d6bd0a-16fd-42b8-0163-bce5c8c7e379"
  welcome:
    showOnStartup: false
  whitespace:
    ensureSingleTrailingNewline: false

"*":
  core:
    themes: [
      "one-light-ui"
      "solarized-dark-syntax"
    ]
  editor:
    fontFamily: "mononoki"
    fontSize: 18
    invisibles: {}
    showIndentGuide: true
    showInvisibles: true
  "exception-reporting":
    userId: "76d6bd0a-16fd-42b8-0163-bce5c8c7e379"
  welcome:
    showOnStartup: false
  whitespace:
    ensureSingleTrailingNewline: false

Switch to mononoki font in Atom editor

Switch to mononoki font in Atom editor


class CommitRequest extends Backbone.Model
  initialize: () ->
    # do stuff

  send: () =>
    $.ajax gon.commit_request_path,
      data: @request
      success: (data) => @success(data)

class Water.CommitRequest extends Backbone.Model
  initialize: () ->
    # do stuff

  send: () =>
    $.ajax gon.commit_request_path,
      data: @request
      success: (data) => @success(data)

Correct namespace for commit request

Correct namespace for commit request


SpellChecker = require 'spellchecker'

module.exports =
  findMisspellings: (text) ->
    wordRegex = /(?:^|[\s\[\]])([a-zA-Z']+)(?=[\s\.\[\]]|$)/g
    row = 0
    misspellings = []
    for line in text.split('\n')
      while matches = wordRegex.exec(line)
        word = matches[1]
        continue unless SpellChecker.isMisspelled(word)
        startColumn = matches.index + matches[0].length - word.length
        endColumn = startColumn + word.length
        misspellings.push([[row, startColumn], [row, endColumn]])
      row++
    callTaskMethod('misspellingsFound', misspellings)

SpellChecker = require 'spellchecker'

module.exports =
  findMisspellings: (text) ->
    wordRegex = /(?:^|[\s\[\]])([a-zA-Z']+)(?=[\s\.\[\]:]|$)/g
    row = 0
    misspellings = []
    for line in text.split('\n')
      while matches = wordRegex.exec(line)
        word = matches[1]
        continue unless SpellChecker.isMisspelled(word)
        startColumn = matches.index + matches[0].length - word.length
        endColumn = startColumn + word.length
        misspellings.push([[row, startColumn], [row, endColumn]])
      row++
    callTaskMethod('misspellingsFound', misspellings)

Include colon as a word boundary

Include colon as a word boundary


# USE
# If the element is not a component, add full-height-header attribute to the tag.
# With a component, add 'full_height_header: true' to the persisted options
class @Components.Utils.FullHeightHeader
  @autoInit: ->
    $('[full-height-header]').each (i, el) => new @($(el))

  constructor: (@el) ->
    @component = @el.data('component')

    if @component
      @inner = @component.inner
    else
      @inner = @el

    @lastWidth = null
    @offset = @inner.offset().top

    @compute()
    $(window).on 'resize', @compute

  compute: =>
    return false if @lastWidth == window.innerWidth
    @inner.css('height', window.innerHeight - @offset)
    @lastWidth = window.innerWidth

# USE
# If the element is not a component, add full-height-header attribute to the tag.
# With a component, add 'full_height_header: true' to the persisted options
class @Components.Utils.FullHeightHeader
  @autoInit: ->
    $('[full-height-header]').each (i, el) => new @($(el))

  constructor: (@el) ->
    @component = @el.data('component')

    if @component
      @inner = @component.inner
    else
      @inner = @el

    @lastWidth = null
    @offset = @inner.offset().top

    @compute()
    $(window).on 'resize', @compute

  compute: =>
    return false if @lastWidth == $(window).width()
    @inner.css('height', $(window).height() - @offset)
    @lastWidth = $(window).width()

Replace window.innerHeight by $(window).height to improve compatibility


'.workspace':
  'ctrl-M': 'markdown-preview:toggle'

'.markdown-preview':
  'cmd-+': 'markdown-preview:zoom-in'
  'cmd-=': 'markdown-preview:zoom-in'
  'cmd--': 'markdown-preview:zoom-out'
  'cmd-_': 'markdown-preview:zoom-out'
  'cmd-0': 'markdown-preview:reset-zoom'

'.workspace':
  'ctrl-M': 'markdown-preview:toggle'

'.platform-darwin .markdown-preview':
  'cmd-+': 'markdown-preview:zoom-in'
  'cmd-=': 'markdown-preview:zoom-in'
  'cmd--': 'markdown-preview:zoom-out'
  'cmd-_': 'markdown-preview:zoom-out'
  'cmd-0': 'markdown-preview:reset-zoom'

'.platform-win32 .markdown-preview, .platform-linux .markdown-preview':
  'ctrl-+': 'markdown-preview:zoom-in'
  'ctrl-=': 'markdown-preview:zoom-in'
  'ctrl--': 'markdown-preview:zoom-out'
  'ctrl-_': 'markdown-preview:zoom-out'
  'ctrl-0': 'markdown-preview:reset-zoom'

Add keybindings for all platforms

Add keybindings for all platforms


# Your init script
#
# Atom will evaluate this file each time a new window is opened. It is run
# after packages are loaded/activated and after the previous editor state
# has been restored.
#

fileTypes = {
  "source.gfm": (editor) ->
    editor.setSoftWrap(true)
    editor.setTabLength(4)

  "source.java": (editor) ->
    editor.setTabLength(4)

  "source.python": (editor) ->
    editor.setTabLength(4)
}

# Apply grammar-specific settings.
#
# editor - Editor to which to apply the grammar-specific settings.
applySyntaxSettings = (editor) ->
  func(editor) for scopeRegex, func of fileTypes when scopeRegex.test(editor.getGrammar().scopeName)

# Executes for each and every Editor, past and future.
atom.workspace.eachEditor (editor) ->
  applySyntaxSettings(editor)

  editor.on 'grammar-changed', ->
    applySyntaxSettings(editor)

# Your init script
#
# Atom will evaluate this file each time a new window is opened. It is run
# after packages are loaded/activated and after the previous editor state
# has been restored.
#

fileTypes = {
  "GitHub Markdown": (editor) ->
    editor.setSoftWrap(true)
    editor.setTabLength(4)

  "Java": (editor) ->
    editor.setTabLength(4)

  "Python": (editor) ->
    editor.setTabLength(4)
}

# Apply grammar-specific settings.
#
# editor - Editor to which to apply the grammar-specific settings.
applySyntaxSettings = (editor) ->
  func(editor) for name, func of fileTypes when name is editor.getGrammar().name

# Executes for each and every Editor, past and future.
atom.workspace.eachEditor (editor) ->
  applySyntaxSettings(editor)

  editor.on 'grammar-changed', ->
    applySyntaxSettings(editor)

Change back to using grammar name

Change back to using grammar name

Matching against the scope name of the grammar didn't seem to work in
all cases.