Full Code of byhestia/springseed for AI

2.x 371c73550888 cached
47 files
204.7 KB
59.0k tokens
8 symbols
1 requests
Download .txt
Showing preview only (217K chars total). Download the full file or copy to clipboard to get everything.
Repository: byhestia/springseed
Branch: 2.x
Commit: 371c73550888
Files: 47
Total size: 204.7 KB

Directory structure:
gitextract_ku31l5mv/

├── .gitattributes
├── .gitignore
├── .gitmodules
├── Cakefile
├── Gemfile
├── Guardfile
├── LICENSE
├── Makefile
├── Procfile
├── README.md
├── app/
│   ├── controllers/
│   │   ├── account.coffee
│   │   ├── browser.coffee
│   │   ├── editor.coffee
│   │   ├── modal.coffee
│   │   ├── note.item.coffee
│   │   ├── notebook.item.coffee
│   │   ├── panel.coffee
│   │   ├── popover.coffee
│   │   ├── settings.coffee
│   │   ├── sidebar.coffee
│   │   ├── sync.coffee
│   │   └── upgrader.coffee
│   ├── index.coffee
│   ├── init.coffee
│   ├── lib/
│   │   ├── setup.coffee
│   │   └── splitter.js
│   ├── models/
│   │   ├── .gitkeep
│   │   ├── note.coffee
│   │   └── notebook.coffee
│   └── views/
│       ├── .gitkeep
│       ├── note.handlebars
│       └── notebook.handlebars
├── css/
│   ├── font.scss
│   ├── keyframes.scss
│   ├── new.scss
│   └── normalize.scss
├── package.json
├── public/
│   ├── about.html
│   ├── default.json
│   ├── emojify.js
│   ├── handlebars.runtime.js
│   ├── images/
│   │   └── emoji/
│   │       └── emojify.css
│   ├── index.html
│   └── sublime.css
└── src/
    ├── AboutWindow.coffee
    ├── Springseed.coffee
    └── main.coffee

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
* text

# Binary Files.
*.png binary
*.jpg binary
*.gif binary
*.svg binary
*.ttf binary


================================================
FILE: .gitignore
================================================
*~
javascript/*.js
.sass-cache
node_modules
*.sublime-project
*.sublime-workspace

codekit-config.json
libpeerconnection.log

# Becuase mh0 needs to compress for the debian packaging
*.nw
public/application.css
public/application.js

src/*.js
app/views/*.js

.srclib-cache


================================================
FILE: .gitmodules
================================================
[submodule "app/lib/socket.io-client"]
	path = app/lib/socket.io-client
	url = https://github.com/LearnBoost/socket.io-client.git


================================================
FILE: Cakefile
================================================

Scrunch = require 'coffee-scrunch'
uglify  = require 'uglify-js'
server  = require 'node-static'
http    = require 'http'
fs      = require 'fs'
sass    = require 'node-sass'
watch   = require 'node-watch'

# Configuration
config =
  port: 9294
  public: 'public'
  js:
    folder: 'app/'
    input:  'app/init.coffee'
    output: 'public/application.js'
    min:    'public/application.js'
  sass:
    input:  'css/new.scss'
    output: 'public/application.css'

# Options
option '-p', '--port [port]', 'Set port for cake server'
option '-w', '--watch', 'Watch the folder for changes'

compile =

  sass: (options) ->
    sasscompile = ->
      console.log 'Compiling SASS'
      sass.render {
          file: config.sass.input
          success: (css) ->
            fs.writeFile config.sass.output, css, (err) ->
              console.warn err if err
          error: (err) ->
            console.warn err if err
          outputStyle: 'compressed'
        }

    if options.watch
      watch config.sass.input, sasscompile

    sasscompile()

  coffee: (options) ->

    if options.watch
      watch config.js.folder, ->
        process.stdout.write 'Compiling CoffeeScript: '
        Scrunch(config.js).then ->
          process.stdout.write 'Done!\n'

    process.stdout.write 'Compiling CoffeeScript: '
    Scrunch(config.js).then ->
      process.stdout.write 'Done!\n'

  minify: ->
    js = uglify.minify(config.js.output).code
    fs.writeFile config.js.min, js


# ===============================================================
# Tasks
# ===============================================================

task 'server', 'Start server', (options) ->

  # Start Server
  port = options.port or config.port
  file= new(server.Server)(config.public)
  server = http.createServer (req, res) ->
    req.addListener( 'end', ->
      file.serve(req, res)
    ).resume()
  server.listen(port)

  console.log "Server started on :#{port}"

  # Compile files
  compile.sass(options)
  compile.coffee(options)

task 'build',  'Compile CoffeeScript', compile.coffee
task 'minify', 'Minify application.js', compile.minify
task 'style',  'Compile Stylesheets', compile.sass



================================================
FILE: Gemfile
================================================
source 'https://rubygems.org'

# Automatically run `make` everytime a file is changed, see Guardfile for internals.
gem 'guard'
gem 'guard-shell'
gem 'sass'


================================================
FILE: Guardfile
================================================
# Only used for development!
# Always run using bundle! (`bundle exec guard`)


guard :shell do
  watch(/.*\.coffee$/) do
    p `make clean` # clean everything.
    p `make` # recompile everything.
    `pkill -f ~/atom-shell/atom` # Kill all Springseed processes automatically, quite crude, just matches all processes using a `~/atom-shell` ¯\_(ツ)_/¯
    p `~/atom-shell/atom ~/springseed` # restart springseed, again, crude, but does the job.
  end
end


================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2013-2014 Jono Cooper
Copyright (c) 2013-2014 Micheal Harker
Copyright (c) 2013-2014 Caffeinated Code <http://caffeinatedco.de>

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: Makefile
================================================
node_bin = ./node_modules/.bin

spsd = app/init.coffee
atom = $(wildcard src/*.coffee)
css = css/new.scss

spsd_out = public/application.js
atom_out = $(atom:%.coffee=%.js)
css_out = public/application.css

all: npm build-atom handlebars style build-app

build-atom: $(atom_out)

src/%.js: src/%.coffee
	@$(node_bin)/coffee -bc $<

build-app: $(spsd_out)

$(spsd_out): $(spsd)
	@$(node_bin)/browserify -t coffeeify $< > $@

handlebars:
	@$(node_bin)/handlebars app/views/note.handlebars -f app/views/note.js
	@$(node_bin)/handlebars app/views/notebook.handlebars -f app/views/notebook.js

style:
	@sass $(css) $(css_out)

npm:
	@npm install .

clean:
	@rm -f $(spsd_out) $(atom_out) $(css_out)


================================================
FILE: Procfile
================================================
web: serveup ./public

================================================
FILE: README.md
================================================
# Springseed
[![Stories in Ready](https://badge.waffle.io/byhestia/springseed.svg?label=ready&title=Ready)](http://waffle.io/byhestia/springseed) 

**Current version: 2.0**

Springseed is the simple and easy way to take your notes.

# Binaries

A fairly up-to-date build is available [here](https://xack.xyz/misc/springseed.zip).

1. Extract `springseed.zip` into its own directory.
2. `./run.sh` **should** download atom-shell, extract it, then run the app.

If there are any issues, please don't hesitate to submit a bug report.

## Preparing Springseed

Springseed is now based on the awesome work of the people at GitHub and as
such we use the fantastic `electron` framework to get stuff done. 

### Installing `electron`
(If you already have `electron` jump to the next section)

Latest builds of `electron` are available [here](https://github.com/atom/electron/releases).
* Download the appropriate file based on your operating system and the system architecture.
* Unzip the downloaded file. This must create an executable file named `electron`.

### Building this code
We have introduced a new build system based on the GNU Makefile build system. Should the
build below fail, you should run `make clean` before trying again because some
make operations won't complete if they've errored. Nothing we can do to fix
this. :smile:

    sudo gem install sass
    git submodule update --init
    make

## Running Springseed
To start Springseed, run the command `<path-to-electron-executable>/electron <springseed-build-directory>` where `<springseed-build-directory>` is the directory where you executed the three commands in **Building this code** section


If you're feeling awesome, you should contribute either with code or a
[donation][1]. Check out the [issue tracker][2] and tackle an issue.

Springseed is written in CoffeeScript and uses Spine.JS for MVC.

## Official website

<http://getspringseed.com>

Copyright &copy; 2013-2014 [Caffeinated Code][3]<br>
Copyright &copy; 2014 [Hestia][4]

Open source under the [MIT license][5].

[1]: http://getspringseed.com/donate
[2]: https://github.com/byhestia/springseed
[3]: http://www.caffeinatedco.de/
[4]: http://byhestia.com/
[5]: http://opensource.org/licenses/MIT


================================================
FILE: app/controllers/account.coffee
================================================
Spine = require 'spine'

class Account
  constructor: ->

  @signin: (username, password) ->
    # Sign in to the Springseed API. It should return a token. Save it.
    localStorage.login = JSON.stringify {'username': username, 'password': password}
    if not username and not password
      # Try signing in with stored credidentials.
      $.get 'http://api.getspringseed.com/login', JSON.parse(localStorage.login), (data) =>
        if data['status'] is 200
          localStorage.token = data['token']
          return true # Logged in
        else if data['status'] > 400
          return false
    else
      # Try signing in with the credidentials we were given.
      $.get 'http://api.getspringseed.com/login', {'username': username, 'password', password}, (data) =>
        if data['status'] is 200
          localStorage.token = data['token']
          return true # Logged in
        else if data['status'] > 400
          return false

  @isSignedIn: () ->
    return true if localStorage.token
    return false if not localStorage.token

  @enableChecks: () ->
    $.get 'http://api.getspringseed.com/me', {token: localStorage.token}, (data) =>
      if data['status'] is 403
        # Get a new valid token - for the old one has expired.
        localStorage.removeItem 'token'
        @signin()
      else
        console.log data
        localStorage.data = JSON.stringify({'username': data.username, 'first_name': data.first_name, 'last_name': data.last_name, 'pro': data.pro})
    setTimeout(@enableChecks, 300000);

  @get: () ->
    return JSON.parse(localStorage.data)

  @signout: () ->
    localStorage.removeItem 'token'
    localStorage.removeItem 'login'

module.exports = Account


================================================
FILE: app/controllers/browser.coffee
================================================
Spine = require 'spine'

# Models
Note = require '../models/note.coffee'
Notebook = require '../models/notebook.coffee'

# Controllers
NoteItem = require '../controllers/note.item.coffee'

class Browser extends Spine.Controller

  template: (->
    require '../views/note.js'
    Handlebars.templates['note']
  )()

  elements:
    'ul': 'noteBrowser'
    'span': 'title'

  events:
    'click #new': 'newNote'

  constructor: ->
    super
    Note.bind "create", @addOne
    Notebook.bind "changeNotebook", @changeNotebook

  addOne: (note) =>
    # We should always be in the right list, but doesn't hurt to check
    if typeof(Notebook.current) isnt "undefined"
      if note.notebook is Notebook.current.id and (Notebook.current.category is "all" or note.category is Notebook.find(Notebook.current.id).categories[Notebook.current.category])
        note.date = note.prettyDate()
        @noteBrowser.prepend @template note

        view = new NoteItem
          el: @noteBrowser.find("#note-#{ note.id }")
          note: note

  newNote: (e) =>
    if Notebook.current.id isnt "all"

          # Create the note meta
          note = Note.create
            name: "Untitled Note"
            starred: false
            excerpt: "This is your new blank note - add some content!"
            notebook: Notebook.current.id
            category: if Notebook.current.category is "all" then Notebook.find(Notebook.current.id).categories[0] else Notebook.find(Notebook.current.id).categories[Notebook.current.category]
            date: Math.round(new Date().getTime()/1000)

          # Set the content with the special function
          note.saveNote "# This is your new blank note\nAdd some content!", ->

            # Select it and throw it into editable mode
            note.trigger("changeNote")
            note.trigger("openNote")
    else
      Modal.get('newNote').run()

  changeNotebook: (notebook) =>
    dateSort = (a, b) ->
      return b.date - a.date

    if notebook.search is true or notebook.search is not undefined
      noteList = ""
      for note in notebook.result
        note.date = note.prettyDate
        noteList += @template note

      @noteBrowser.html noteList

    else
      noteList = ""
      for note in Note.filter(Notebook.current.id, Notebook.current.category).sort(dateSort)
        note.date = note.prettyDate()
        noteList += @template note

      @noteBrowser.html(noteList)

      # Defers for speed
      window.requestAnimationFrame( =>
        for note in Note.filter(Notebook.current.id, Notebook.current.category)
          view = new NoteItem
            el: @noteBrowser.find("#note-#{ note.id }")
            note: note
      )

module.exports = Browser


================================================
FILE: app/controllers/editor.coffee
================================================
Spine = require 'spine'
marked = require 'marked'
hljs = require 'highlight.js'

# Models
Note = require '../models/note.coffee'

# Controllers
window.Modal = require '../controllers/modal.coffee'

class Editor extends Spine.Controller

  elements:
    ".headerwrap .left input": "title"
    ".headerwrap .left time": "time"
    "#contentread": "contentread"
    "#contentwrite > .inner": "contentwrite"
    ".headerwrap .edit": "toggle"
    "#psuedoinput": "psuedoinput"
    ".headerwrap i.star": "star"

  events:
    "click .headerwrap .edit": "toggleMode"
    "click .headerwrap .revert": "revert"
    "keydown #contentwrite > .inner": "keydown"
    #"paste #contentwrite > .inner": "paste"
    "dblclick #contentread": "toggleMode"
    "click header .right .delete": "deleteNote"
    "click header .star": "starNote"
    "textInput section.inner": "inputHandler" # used for emojis
    "blur section.inner": "blurHandler" # again, used for emojis


  starNote: ->
    note = Note.find(Note.current.id)
    if note.starred is "true"
      note.updateAttribute("starred", "false")
      @star.addClass("fa-star-o")
      @star.removeClass("fa-star")
      @star.removeClass("starred")
    else
      note.updateAttribute("starred", "true")
      @star.removeClass("fa-star-o")
      @star.addClass("fa-star")
      @star.addClass("starred")

  deleteNote: (e) ->
    note = Note.find(Note.current.id)
    $(".delete-container span.name").text(note.name)
    Modal.get("delete").run()

  constructor: ->
    super
    Note.bind("changeNote", @enable)
    Note.bind "openNote", =>
      @toggleMode()
    Note.bind("revert", @revertNote)
    @.bind("checkSel", @checkSelWrap)

    emojify.setConfig {
      ignored_tags: {
        'CODE': 1
      }
    }
    marked.setOptions {
      highlight: (code, lang) ->
        try
          if lang
            return hljs.highlight(lang.toLowerCase(), code).value
          else
            return hljs.highlightAuto(code).value
        catch error
          code
      tables: true
      sanitize: true
      smartLists: true
      smartypants: true
    }
    @controls = $("#editorcontrols")
    @controls.find('#bold').click @formatBold
    @controls.find('#italics').click @formatItalics
    @controls.find('#heading').click @formatHead

  enable: (note) =>
    # Put back into the right mode
    @toggleMode() if @mode is "edit"

    # Loads note
    Note.current = note
    if note isnt undefined
      currentNote = Note.find(note.id)

      @el.removeClass("deselected")
      @title.val currentNote.name
      @time.text currentNote.prettyDate(true)

      if currentNote.starred is "true"
        @star.attr('class', 'star fa fa-star starred')
      else
        @star.attr('class', 'star fa fa-star-o')

      # Content
      currentNote.loadNote (content) =>
        @contentread.html marked(content)
        @contentwrite.text content

        # this needs to be bound
        $('#contentread a').attr('target', '_blank').click ->
          return false
    else
      @el.addClass("deselected")


    setInterval(@wc, 1000)

    @mode = "preview"

  wc: ->
    text = $('#contentwrite section').text()
    wc = $(marked(text)).text().split(' ').length
    $('.wc').text(wc)


  toggleMode: (save) ->
    if @mode is "preview" # enable the editor
      # UI bits and bobs
      @el.addClass("edit")
      @toggle.find("i").addClass("fa-lock")
      @toggle.find("i").removeClass("fa-pencil")
      @toggle.find("i")[0].parentNode.title = "Preview Note"
      @title.prop "disabled", false
      @mode = "edit"

      # Focus the text area
      @contentwrite.focus()

    else # disable the editor
      if save is false and Note.current isnt undefined # We're not saving the content (revert button)
        currentNote = Note.find(Note.current.id)
        currentNote.loadNote (content) =>
          @contentwrite.text content
      else
        @controls.hide()
        # Copy the text in
        noteText = @contentwrite.text()
        @contentread.html marked(noteText)
        $('#contentread a').attr('target', '_blank').click ->
          return false

        # Save it
        if Note.current isnt undefined
          currentNote = Note.find(Note.current.id)

          # Excerpts nicely
          info = noteText
          if info.length > 90
            info = info.substring(0, 100)
            lastIndex = info.lastIndexOf(" ")
            info = info.substring(0, lastIndex) + "&hellip;"
          info = $(marked(info)).text()
          info = info.split("\n").join(" ")

          # Update Spine
          currentNote.updateAttributes {
            "name": @title.val()
            "excerpt": info
            "date": Math.round(new Date()/1000)
          }

          # Update IndexedDB
          currentNote.saveNote(noteText)


      # The opposite
      @el.removeClass("edit")
      @toggle.find("i").removeClass("fa-lock")
      @toggle.find("i").addClass("fa-pencil")
      @toggle.find("i")[0].parentNode.title = "Edit Note"
      @title.prop "disabled", true
      @mode = "preview"
      @time.text currentNote.prettyDate(true)

  revert: ->
    if @mode isnt "preview"
      Modal.get('revert').run()

  revertNote: =>
    @toggleMode(false)

  # Pops the text into the contenteditable
  insertText: (text) ->
    sel = window.getSelection()
    range = sel.getRangeAt(0)
    range.deleteContents()
    textNode = document.createTextNode(text)
    range.insertNode(textNode)
    range.setStartAfter(textNode)
    sel.removeAllRanges()
    sel.addRange(range)


  keydown: (e) ->
    # Some keys are special
    if e.keyCode is 13 #return
      #e.preventDefault()
      @insertText "\n"
    else if e.keyCode is 9 #tab
      e.preventDefault()
      @insertText "    "
    else if e.keyCode is 27 #escape key
      e.preventDefault()
      @toggleMode()

  #paste: (e) ->
  #  # Keeps the range for later
  #  @range = window.getSelection().getRangeAt(0)

  #  # Paste it into a textarea (removes formatting)
  #  #@psuedoinput.val("").focus()

  #  # As the paste event isn't instant, put it back in a few secs.
  #  setTimeout( =>
  #    s = window.getSelection()
  #    s.removeAllRanges()
  #    s.addRange(@range)

  #    @insertText @psuedoinput.val()
  #  , 10)

  checkSelWrap: ->
    setTimeout =>
      @checkSel()
    , 50

  checkSel: ->
    if @mode is "preview"
      @controls.hide()
    else
      sel = window.getSelection()
      if sel.toString().trim() is ''
        @controls.hide()
      else
        @sel = sel
        @selrange = sel.getRangeAt(0)
        @controls.show()
        toppos = @selrange.getBoundingClientRect().top - 55 - @controls.height() + 'px'
        leftpos = @selrange.getBoundingClientRect().right - (@controls.width() / 2) + 'px'
        @controls.css {top: toppos, left: leftpos}

  newString: (str) ->
    @selrange.surroundContents(document.createElement("span"))
    text = @el.find("span").text()
    @el.find("span").text(str).contents().unwrap()

  formatBold: (e) =>
    str = @selrange.toString()
    if str.substring(0,2) is "**" and str.substring(str.length-2,str.length) is "**"
      @newString(str.substring(2,str.length-2))
    else
      @sel.collapseToStart()
      @sel.modify("move", "backward", "character")
      @sel.modify("move", "backward", "character")
      @sel.modify("extend", "forward", "word")
      @sel.modify("extend", "forward", "character")
      @sel.modify("extend", "forward", "character")
      @selrange = @sel.getRangeAt(0)
      str = @selrange.toString()

      if str.substring(0,2) is "**" and str.substring(str.length-2,str.length) is "**"
        @newString(str.substring(2,str.length-2))
      else
        @sel.collapseToStart()
        @sel.modify("move", "forward", "character")
        @sel.modify("move", "forward", "character")
        @sel.modify("extend", "forward", "word")
        @selrange = @sel.getRangeAt(0)
        str = @selrange.toString()
        @newString("**" + str + "**")

  formatItalics: (e) =>

    str = @selrange.toString()
    if str.substring(0,1) is "*" and str.substring(str.length-1,str.length) is "*"
      @newString(str.substring(1,str.length-1))
    else
      @sel.collapseToStart()
      @sel.modify("move", "backward", "character")
      @sel.modify("extend", "forward", "word")
      @sel.modify("extend", "forward", "character")
      @selrange = @sel.getRangeAt(0)
      str = @selrange.toString()

      if str.substring(0,1) is "*" and str.substring(str.length-1,str.length) is "*"
        @newString(str.substring(1,str.length-1))
      else
        @sel.collapseToStart()
        @sel.modify("move", "forward", "character")
        @sel.modify("extend", "forward", "word")
        @selrange = @sel.getRangeAt(0)
        str = @selrange.toString()
        @newString("*#{str}*")

  formatHead: (e) =>
    @sel.modify("extend", "backward", "paragraphboundary")
    @sel.modify("extend", "forward", "paragraphboundary")
    @selrange = @sel.getRangeAt(0)

    if @selrange.toString().substring(0,3) isnt "###"
      @selrange.surroundContents(document.createElement("span"))
      text = @el.find("span").text()
      @el.find("span").text("#"+text+"").contents().unwrap()
    else
      @selrange.surroundContents(document.createElement("span"))
      text = @el.find("span").text()
      @el.find("span").text(text.substring(3)).contents().unwrap()

  inputHandler: (e) ->
    # Handle Emoji creation
    if e.originalEvent.data == ":" # capture colon key
      setTimeout (->
        emojify.run() # ALL the emojis!
      ), 100


  blurHandler: (e) ->
    for i in $('section.inner img.emoji')
      $(i).replaceWith(i.title)


module.exports = Editor


================================================
FILE: app/controllers/modal.coffee
================================================
Spine = require 'spine'
$ = Spine.$

# Needed.
Note = require '../models/note.coffee'
Notebook = require '../models/notebook.coffee'

# Base Modal Class.
class Modal extends Spine.Controller
  constructor: (opts) ->
    super

    # Probably shouldn't be in here, but whatever
    Spine.bind 'sync:meta', =>
      modals['syncmeta'].run()

  state: off

  show: ->
    return unless @state is off
    @state = on
    @el.show(0).addClass 'show'
    if @onShow then @onShow()
    setTimeout ( =>
      @el.on "click.modal", (event) =>
        if event.target.className.indexOf('modals') > -1
          @hide()
    ), 500


  hide: ->
    return unless @state is on
    @state = off
    @el.removeClass 'show'
    setTimeout ( =>
      @el.hide(0)
      if @onHide then @onHide()
    ), 350
    @el.off 'click.modal'

modals = []

module.exports =

  get: (name) ->
    # Return a Modal object. Like a pro.
    return modals[name]

  init: ->
    # Do init stuff here.
    # Like, uh, getting modals sorted. Yolo.
    modals['delete'] = new Modal
      el: $('.modal.delete')
      events:
        'click .true': 'delete'
        'click .false': 'hide'

      run: ->
        @show()

      delete: ->
        # Taken from controllers/panel.coffee.
        if Note.current isnt undefined
          currentNote = Note.find(Note.current.id)

          # Take it out of editmode
          Note.trigger 'changeNote'
          currentNote.destroy()

          @hide()
    
	modals['newNote'] = new Modal
	  el: $('.newNote')
	  events:
	    'click .gotit': 'hide'
	  run: ->
	    @show()

    modals['revert'] = new Modal
      el: $('.modal.revert')
      events:
        'click .true': 'revert'
        'click .false': 'hide'

      run: ->
        @show()

      revert: ->
        Note.trigger 'revert'
        @hide()

    modals['syncmeta'] = new Modal
      el: $('.modal.syncmeta')
      events:
        'click .destroyclient': 'destroyclient'
        'click .destroyserver': 'destroyserver'

      destroyclient: ->
        Sync.firstSync("destroyclient")
        @hide()

      destroyserver: ->
        Sync.firstSync("destroyserver")
        @hide()

      run: ->
        @show()

    modals['deleteNotebook'] = new Modal
      el: $('.modal.deleteNotebook')
      events:
        'click .true': 'delete'
        'click .false': 'hide'

      run: (notebookid, @category) ->
        @notebook = Notebook.find(notebookid)
        numberofNotes = Note.filter(notebookid, category).length;
        if @category is "all"
          @el.find('.type').text "Notebook"
          @el.find('i').text @notebook.name
        else
          @el.find('.type').text "Subcategory"
          @el.find('i').text @notebook.categories[@category]

        @el.find('.numberofNotes').text(numberofNotes)

        if numberofNotes > 1
          @el.find('.oneOrMore').show()  
        else
          @el.find('.oneOrMore').hide()

        if numberofNotes > 0
          @show()
        else
          @delete()

      delete: ->
        Note.trigger 'changeNote'
        if @category is "all"
          @notebook.destroy()
        else
          @notebook.subcategoryDestroy(@category)
        @hide()

    modals['renameNotebook'] = new Modal
      el: $('.modal.renameNotebook')
      events:
        'click .true': 'rename'
        'click .false': 'hide'

      run: (@notebookid, @category) ->
        # Subcategories need a proper lookup
        input = @el.find('input')
        if @category is 'all'
          input.val(Notebook.find(@notebookid).name)
        else
          input.val(Notebook.find(@notebookid).categories[@category])
        @show()

      rename: ->
        # Backslashes only seem to be an issue here
        input = @el.find('input').val()
        input = input.replace(/\\/g, '')
        notebook = Notebook.find(@notebookid)

        # Check for Empty String
        if input isnt ''
          if @category is 'all'
            notebook.updateAttribute 'name', input
          else
            # Subcategories need to be cloned then updated
            # Also, I wish there was a better way to do pointers.
            arr = notebook.categories.slice(0)
            arr[@category] = input
            notebook.updateAttribute 'categories', arr

          Notebook.trigger 'refresh'
        @hide()

    modals['pleaseLogIn'] = new Modal
      el: $('.modal.pleaseLogIn')
      events:
        'click .false': 'hide'

      hide: ->
        @hide()


================================================
FILE: app/controllers/note.item.coffee
================================================
Spine = require 'spine'

# Models
Note = require '../models/note.coffee'

class NoteItem extends Spine.Controller

  elements:
    "h2": "title"
    "time": "time"
    "span": "excerpt"

  events:
    "click": "select"
    "dragstart": "startdrag"
    "dragend": "stopdrag"

  constructor: ->
    super
    @note.bind "changeNote", @changeNote
    @note.bind "change", @updateNote
    @note.bind "destroy", @deleteNote

  select: ->

    Note.trigger "changeNote", {id: @note.id}
    # console.log 'unemojified - change'

  changeNote: =>
    @el.parent().find(".selected").removeClass("selected")
    @el.addClass("selected")
    setTimeout (->
      emojify.run() # ALL the emojis!
    ), 100


  updateNote: =>
    @title.text @note.name
    @time.text @note.prettyDate() + " -"
    @excerpt.text @note.excerpt

  deleteNote: =>
    @el.remove()

  startdrag: (e) =>
    @el.css {opacity: 0.4}

    noteid = $(e.target).attr('id').replace("note-", "")
    e.originalEvent.dataTransfer.setData('noteid', noteid)


  stopdrag: (e) =>
    @el.css {opacity: 1}


module.exports = NoteItem


================================================
FILE: app/controllers/notebook.item.coffee
================================================
Spine = require 'spine'

# Models
Notebook = require '../models/notebook.coffee'

class NotebookItem extends Spine.Controller
  elements:
    'ul': 'category'

  events:
    'click': 'expand'
    'contextmenu': 'expand'
    'contextmenu': 'toggleMore'
    'click .icon': 'newCategory'
    'dragenter': 'onDragEnter'
    'dragleave': 'onDragLeave'
    'dragover': 'onDragOver'
    'drop': 'onDrop'

  constructor: ->
    super
    if @notebook.id isnt 'all'
      @notebook.bind 'changeNotebook', @changeNotebook
      @notebook.bind 'update', @update
      @notebook.bind 'destroy', @destroy

  expand: (e) =>
    # Categories
    if $(e.target).attr('data-category')
      Notebook.trigger('changeNotebook', {id: @notebook.id, category: $(e.target).attr('data-category')})
    else
      Notebook.trigger('changeNotebook', {id: @notebook.id, category: 'all'})

    # Hacky, but whatever.
    @changeNotebook({id: 'all', category: 'all'}) if @notebook.id is 'all'

  toggleMore: (e) =>
    @expand(e)
    e.preventDefault()
    if !$(e.target).hasClass('icon') and @notebook.id isnt 'all'
      $('.popover-mask').show()
      target = $(e.target).parent()

      if $(e.target).attr('data-category') is 'all'
        return

      # Category
      else if $(e.target).attr('data-category')
        $('.delete-popover').css(
          left: target.outerWidth(),
          top: $(e.target).offset().top-($('.delete-popover').height()/3)
        ).attr('data-notebook', @notebook.id
        ).attr('data-category', $(e.target).attr('data-category')
        ).show()

      # Book
      else
        $('.delete-popover').css(
          left: target.outerWidth(),
          top: @el.offset().top
        ).attr('data-notebook', @notebook.id
        ).attr('data-category', 'all'
        ).show()

  changeNotebook: (notebook) =>
    @el.parent()
      .children()
      .removeClass('expanded selected')
    @el.addClass('selected')

    # Only show the categories if there's more than one.
    @el.addClass('expanded') if @notebook.categories.length > 1

    # Select the right one
    @category.find('li').removeClass('selected')
    @el.find("[data-category='#{notebook.category}']").addClass('selected')

  newCategory: (e) ->
    $('.popover-mask').show()
    target = $(e.target).parent()

    $('.category-popover').css({left: target.outerWidth(), top: target.offset().top}).show()
      .find('input').val('').focus()

  update: =>
    # Subcategories
    str = '<li data-category="all" class="selected">All Notes</li>'
    for category, i in @notebook.categories
      str += "<li data-category=#{i}>#{category}</li>"
    @category.html(str)

    @el.addClass('expanded') if @notebook.categories.length > 1

  destroy: =>
    @el.remove()

  onDragEnter: (e) =>
    e.preventDefault()
    if ($(e.target).attr('data-category') and $(e.target).attr('data-category') isnt 'all') or $(e.currentTarget).attr('id') isnt 'notebook-all'
      $(e.target).addClass('dragover')

  onDragLeave: (e) =>
    e.preventDefault()
    $(e.target).removeClass('dragover')

  onDragOver: (e) =>
    e.preventDefault()
    if @notebook.id is 'all' or $(e.target).attr('data-category') is 'all'
      # No.
      return false

  onDrop: (e) =>
    # Create the note in this Notebook, delete the old one.
    if @notebook.id is 'all' or $(e.target).attr('data-category') is 'all'
      return false;
    else
      noteid = e.originalEvent.dataTransfer.getData('noteid')
      note = Note.find(noteid)
      if $(e.target).attr('data-category')
        category = $(e.target).text()
        $(e.target).removeClass('dragover') # Reset CSS changes
      else
        category = @notebook.categories[0] # Default Category

      note.updateAttributes {
        'notebook': @notebook.id,
        'category': category
      }

      # Finally, refresh!
      Notebook.trigger 'changeNotebook', {id: Notebook.current.id, category: Notebook.current.category}

module.exports = NotebookItem


================================================
FILE: app/controllers/panel.coffee
================================================
Spine = require 'spine'

# Models
Note = require '../models/note.coffee'
Notebook = require '../models/notebook.coffee'
Modal = require '../controllers/modal.coffee'
Settings = require '../controllers/settings.coffee'
Account = require '../controllers/account.coffee'

class Panel extends Spine.Controller
  elements:
    "#loginbox": "login"

  events:
    "dblclick": "maximize"
    "click #decor img": "windowControl"
    "keyup #search input": "search"
    "click #loginbox .name": "userSettings"

  maximized: false

  constructor: ->
    super
    Note.bind "changeNote", @toggleNote
    Notebook.bind "changeNotebook", @toggleNotebook
    # if win
    #   win.on 'maximize', =>
    #     @maximized = true
    #   win.on 'unmaximize', =>
    #     @maximized = false

    setInterval ->
      if Account.isSignedIn()
        $('#loginbox').find('.name').text(Account.get().first_name + " " + Account.get().last_name)
        if Account.get().pro
          $('#loginbox').find('.gopro').text('you\'re pro')
      else
        $('#loginbox').find('.name').text("log in")
        $('#loginbox').find('.gopro').text('go pro')
    ,100

    # Resizes the panel seperator
    browser = $("#browser")
    $(".splitter.split-right").on "mouseup", =>
      @noteControls.width((browser.width()-4))

  userSettings: (e) ->
    Settings.get().show("account")

  windowControl: (e) ->
    # switch e.currentTarget.className
    #   when "close"
    #     win.close()
    #   when "minimize"
    #     win.minimize()
    #   when "maximize"
    #     @maximize()

  maximize: ->
    win.maximize() if @maximized is false
    win.unmaximize() if @maximized is true

  toggleNote: (note) =>
    # if note isnt undefined
    #   @noteControls.removeClass "disabled"
    # else
    #   @noteControls.addClass "disabled"

  toggleNotebook: (notebook) =>
    # if notebook.id is "all"
    #   @noteControls.addClass "all"
    # else
    #   @noteControls.removeClass "all"

  search: (e) =>
    # This feels so ugly :/
    searchstring = $(e.target).val()
    Note.search(searchstring)

module.exports = Panel


================================================
FILE: app/controllers/popover.coffee
================================================
Spine = require 'spine'

# Models
Notebook = require '../models/notebook.coffee'

Modal = require './modal.coffee'

class Popover extends Spine.Controller

  elements:
    ".delete-popover": "categoryPopover"
    ".delete-popover input": "categoryInput"
    ".delete-popover": "delpopover"

  events:
    "click": "hidePopover"
    "contextmenu": "hidePopover"
    "click .category-popover button": "addCategory"
    "keyup .category-popover input": "addCategory"
    "click .delete-popover #deleteNotebook": "deleteNotebook"
    "click .delete-popover #renameNotebook": "renameNotebook"
    "keyup .delete-popover #addCat": "addCategory"
    "focusout .delete-popover #addCat": "cleanField"

  constructor: ->
    super

  hidePopover: (e) ->
    # Not sure where to put this, but it is global
    e.preventDefault()
    @el.hide().children().hide() if $(e.target)[0].nodeName isnt "INPUT"

  cleanField: (e) ->
    $(e.target)[0].value = ""


  addCategory: (e) ->
    if e.type is "keyup" and e.which is 13
      # adds the new category on
      notebook = Notebook.find(Notebook.current.id)
      cat = notebook.categories
      name = @categoryInput.val().replace(/\\/g, '')
      if name isnt ''
        cat.push(name)
        notebook.updateAttribute("categories", cat)
        @cleanField(e)

      @el.hide()

  renameNotebook: (e) =>
    # All renaming gets implemented in modal.coffee
    notebookid = @delpopover.attr('data-notebook')
    categoryid = @delpopover.attr('data-category')
    Modal.get('renameNotebook').run(notebookid, categoryid)

  deleteNotebook: (e) =>
    # All deletion gets implemented in modal.coffee
    notebookid = @delpopover.attr('data-notebook')
    categoryid = @delpopover.attr('data-category')
    Modal.get('deleteNotebook').run(notebookid, categoryid)


module.exports = Popover


================================================
FILE: app/controllers/settings.coffee
================================================
Spine = require 'spine'
$ = Spine.$

shell = window.require('shell') if window.require

Sync = require './sync.coffee'
Account = require '../controllers/account.coffee'

class Settings extends Spine.Controller
  elements:
    '.sync #signin': 'signinbtn'
    '.sync #signout': 'signoutbtn'
    '.account #signin': 'signinacc'
    '.sync .username': 'username'
    '.account .name': 'accusername'
    '.about': 'aboutPage'
    '.general': 'generalPage'
    '.sync .signedin': 'signedin'
    '.sync .signedout': 'signedout'
    '.account .signedin': 'accsignedin'
    '.account .signedout': 'accsignedout'
    '#accusername': 'usernameinput'
    '#accpassword': 'passwordinput'
    '.account .signedin #pro': 'pro'
    '.account .signedin #alreadypro': 'alreadypro'

  events:
    'click .tabs li': 'tabs'
    'click .sync #signin': 'signin'
    'click .sync #signout': 'signout'
    'click .account #signin': 'accountSignin'
    'click .account #signout': 'accountSignout'

  state: off

  constructor: ->
    super

    # A really bad hack
    Spine.bind 'sync:authorized', =>
      @hide()
      @signedout.hide()
      @signedin.show()
      $.ajax(
        Sync.generateRequest {request: "me"}
      ).done((data) =>
        @username.text data.email
      )

    Spine.bind 'sync:unauthorized', =>
      @signedout.show()
      @signedin.hide()
      @signinbtn.text 'Sign In'

    setInterval () =>
      if Account.isSignedIn()
        @accsignedout.hide()
        @accsignedin.show()
        @accusername.text(Account.get().first_name + " " + Account.get().last_name)
        if Account.get().pro
          @pro.hide()
          @alreadypro.show()
      else
        @accsignedin.hide()
        @accsignedout.show()
        @pro.show()
        @alreadypro.hide()
    ,100

  accountSignin: ->
    if Account.signin(@usernameinput.val(), @passwordinput.val())
      if Account.isSignedIn()
        @hide()
        Account.enableChecks()
    else
      @signinacc.text "Wrong Username/Password"
      setTimeout () =>
        @signinacc.text "Sign in"
      , 5000


  accountSignout: ->
    Account.signout()

  tabs: (e) ->
    # This is ugly. Shoot me later. Could not think of a better implementation.
    @el.find('.current').removeClass 'current'
    @el.find('div.'+$(e.target).addClass('current').attr('data-id')).addClass 'current'

  show: (tab) ->
    return unless @state is off
    @state = on
    @el.show(0).addClass("show")
    setTimeout ( =>
      @el.on "click.modal", (event) =>
        if event.target.className.indexOf('modal') > -1 then @hide()
    ), 500

    if Account.isSignedIn()
      @accsignedin.show()
      @accsignedout.hide()
    else
      @accsignedout.show()
      @accsignedin.hide()

    if tab is not null
      $('.tabs ul li[data-id="'+tab+'"]').click()

  hide: ->
    return unless @state is on
    @state = off
    @el.removeClass("show")
    setTimeout ( => @el.hide(0)), 350
    @el.off("click.modal")

  signin: ->
    @signinbtn.text 'Connecting...'
    Sync.auth (data) =>
        shell.openExternal(data.url)

  signout: ->
    Sync.signOut()


settings = null # Temp

module.exports =

  get: ->
    return settings

  init: ->
    settings = new Settings
      el: $('.modal.preferences')


================================================
FILE: app/controllers/sidebar.coffee
================================================
Spine = require 'spine'

# Models
Note = require '../models/note.coffee'
Notebook = require '../models/notebook.coffee'

# Controllers
NotebookItem = require './notebook.item.coffee'
Settings = require './settings.coffee'
Sync = require './sync.coffee'

class Sidebar extends Spine.Controller

  template: (->
    require '../views/notebook.js'
    Handlebars.templates['notebook']
  )()

  events:
    "keyup input": "new"
    "click #settings": "toggleSettings"
    "click #sync": "doSync"

  elements:
    "ul": "list"
    "input": "input"
    "#settings": "settings"
    "#sync": "sync"

  constructor: ->
    super
    Notebook.bind "create", @addOne
    Notebook.bind "changeNotebook", @change
    Notebook.bind "refresh", @refresh
    Notebook.bind "destroy", @destroy

    # Starts and stops the animation
    Spine.bind 'sync:start', =>
      @sync.addClass 'spin'
    Spine.bind 'sync:stop', =>
      @sync.removeClass 'spin'

  addOne: (notebook) =>
    @list.append @template notebook
    view = new NotebookItem
      el: @list.find("#notebook-#{ notebook.id }")
      notebook: notebook

  change: (notebook) =>
    # This is defined here, or some weird shit happens

    # Annoyingly, this is a two step process
    if Note.current
      if Note.current.persist
        setTimeout( =>
          Note.trigger "changeNote", Note.current
        , 100)
      else
        Note.trigger "changeNote"
    else
      Note.trigger "changeNote"

    Notebook.current = notebook

  refresh: () =>
    # Called on load from indexeddb
    html = @template {id: "all", name: "All Notes"}
    for notebook in Notebook.all()
      html += @template notebook
    @list.html(html)

    # Defers for speed
    window.requestAnimationFrame( =>
      # All Notes
      new NotebookItem
        el: @list.find("#notebook-all")
        notebook: {id: "all", name: "All Notes", categories: []}

      # Normal Notes
      for notebook in Notebook.all()
        view = new NotebookItem
          el: @list.find("#notebook-#{ notebook.id }")
          notebook: notebook

      # This feels so bad :(
      if Notebook.current
        Note.current.persist = true if Note.current
        # Doubley bad
        if Notebook.current.id is "all"
          $("#notebook-all").trigger("click")
        else
          Notebook.trigger('changeNotebook', Notebook.current)
      else
        $("#notebook-all").trigger("click")
    )

  destroy: ->
    # This is bad practice, but I knew this would happen.
    # We'll revamp it when we get Smart Lists
    $("#notebook-all").trigger("click")

  new: (e) ->
    val = @input.val()
    if e.which is 13 and val
      # Make a new Notebook
      newNotebook = Notebook.create
        name: val
        categories: ["General"]
        date: Math.round(new Date()/1000)

      # Select that notebook for opening
      Notebook.trigger "changeNotebook", {id: newNotebook.id, category: "all"}
      @input.val ""

  toggleSettings: (e) ->
    Settings.get().show("sync")

  doSync: ->
    if localStorage.oauth
      Sync.doSync()
    else
      @toggleSettings()

module.exports = Sidebar


================================================
FILE: app/controllers/sync.coffee
================================================
Spine = @Spine or require 'spine'
io = require '../lib/socket.io-client/dist/socket.io.js'
Model = Spine.Model

# Connection states
OFFLINE = 0
IN_PROGRESS = 1
ONLINE = 2

window.Sync =

  oauth: JSON.parse localStorage.oauth or '{"service": "undefined"}'
  queue: JSON.parse localStorage.Queue or '{"Note": {}, "Notebook": {}}'
  syncMeta: {}

  # Run a Sync on a Timeout
  # Clears if another request is put through
  timeoutSync: ->
    clearTimeout Sync.timeoutId
    Sync.timeoutId = setTimeout ->
      Sync.doSync() if localStorage.oauth
    , 5000

  # Hold pending actions
  pending: []

  # Run pending actions
  _clearPending: ->
    for [fn, that, args] in @pending by - 1
      fn.apply(that, args)
      @pending.length--

  # If connection is not ready, then we will wait until it is
  defer: (self, fn, args...) ->
    if @state is ONLINE
      fn.apply(self, args)
    else
      @pending.push [fn, self,  args]

  state: OFFLINE

  signOut: ->
    # Deletes everything. Should work right?
    localStorage.removeItem 'oauth'
    Sync.oauth = JSON.parse localStorage.oauth or '{"service": "undefined"}'
    Spine.trigger 'sync:unauthorized'
    Spine.trigger 'sync:stop'

  # analytics
  anal: ->
    $.ajax(
      Sync.generateRequest({request: "me"})
    ).done (info) ->
      anal =
        name: info.display_name
        email: info.email
        countryCode: info.country
        language: navigator.language
        platform: navigator.platform
        version: localStorage.version
      # $.get("http://api.getspringseed.com/client", anal)

  auth: (callback) ->

    # Saves data after getting it from the auth server
    onData = (data) ->
      # Calc expiration date
      data.expires = new Date().getTime() + parseInt(data.expires_in)*1000 if data.hasOwnProperty("expires_in")
      Sync.oauth = data
      localStorage.oauth = JSON.stringify(data)
      Spine.trigger 'sync:authorized'

      # Weird? Do a sync on error. Nope. We're checking if a meta file exists and then asking the user if they
      # want to copy from the server, or copy to the server. I did tests and if we don't have this step, we get
      # some really weird fuckery. File systems are great, yes. But databases are sometimes better.
      $.ajax(
        Sync.generateRequest
          request: "download"
          filename: "meta"
      ).done((data) ->
         Spine.trigger 'sync:meta'
      ).error((data) ->
        Sync.doSync()
      )

    if Sync.oauth.service is "undefined"
      # There's something weird, even thought the sockets should die.
      if Sync.socket
        Sync.socket.disconnect()
        Sync.socket.socket.reconnect()
      else
        Sync.socket = io.connect("https://springseed.azurewebsites.net:443")

      Sync.socket.on "meta", (data) ->
        console.log('meta', data)
        callback(data)

      Sync.socket.on "authorized", (data) ->
        onData(data)
        Sync.socket.disconnect() # Free up server resources

    # If it expires in the next ten minutes, we'll refresh the token
    else if Sync.oauth.service is "skydrive" and new Date().getTime() > (Sync.oauth.expires - 6000000)
      $.ajax(
        Sync.generateRequest
          request: "refresh"
      ).done((data) ->
        onData(data)
        callback() if callback
      )

  # There's two options of destroying stuff.
  # Destroy the server, or destroy the client.
  firstSync: (method) ->
    deferred = new $.Deferred()
    if method is "destroyserver"
      $.ajax(
        Sync.generateRequest
          request: "destroy"
          filename: "meta"
          dataType: "text"
      ).done (data) ->
        # Do the real initial sync
        Sync.doSync()

    else if method is "destroyclient"
      # Delete all the notes in the app
      Notebook.all().forEach (notebook) ->
        notebook.destroy()

      # Then delete the queue so nothing tries to sync
      Sync.queue = {"Note": {}, "Notebook": {}}
      Sync.saveQueue()

      # Do the real initial sync
      Sync.doSync()

  preSync: ->
    deferred = new $.Deferred()

    if Sync.oauth.service is "skydrive"
      $.ajax(
        Sync.generateRequest
          request: "findappdir"
      ).done((data) ->
        for item in data.data
          # Break when we find the springseed folder
          if item.name.toLowerCase() is "springseed"
            Sync.syncMeta.folderid = item.id
            break
        $.ajax(
          Sync.generateRequest
            request: "listappdir"
        ).done((data) ->
          Sync.syncMeta.map = {}
          for item in data.data
            Sync.syncMeta.map[item.name] = item.id
          deferred.resolve()
        )
      )
    else
      deferred.resolve()

    return deferred.promise()

  # The main syncing function.
  # It downloads the meta, then updates it to latest version as well as doing various other io.
  # It's magic. Trust me.
  doSync: ->

    Spine.trigger 'sync:start'

    # Downloads a meta file.
    $.ajax(
      Sync.generateRequest
        request: "download"
        filename: "meta"
    ).done((data) ->
      # Merge all the magical data together
      result = Sync.merger(JSON.parse(Sync.exportData()), data, Sync.queue)

      # First, we rename the keys in our current DB
      promises = []
      result[1].Note.forEach (item) ->

        promises.push((->
          deferred = $.Deferred()

          Note.find(item[0]).loadNote (oldcontent) ->
            trans = Sync.db.transaction(["notes"], "readwrite")
            store = trans.objectStore "notes"
            request = store.put(oldcontent, item[1])

            request.onsuccess = (e) =>
              Note.find(item[0]).deleteNote ->
                deferred.resolve()

          return deferred.promise()
        )())

      # All files renamed, doing da internet IO.
      $.when.apply($, promises).then ->

        promises = []
        dbrequests = []
        trans = Sync.db.transaction(["notes"], "readwrite")
        store = trans.objectStore "notes"

        result[2].Note.forEach (item) ->

          promises.push((->
            deferred = $.Deferred()

            switch item[0]
              when "upload"
                itemid = item[1]
                dbrequests[itemid] = store.get(itemid)
                dbrequests[itemid].onsuccess = (e) =>
                  # Upload file to my butt.
                  $.ajax(
                    Sync.generateRequest
                      request: "upload"
                      filename: itemid
                      dataType: "text"
                      data: e.target.result
                  ).done (data) ->
                    deferred.resolve()

              when "download"
                # Download from my butt
                $.ajax(
                  Sync.generateRequest
                    request: "download"
                    filename: item[1]
                    dataType: "text"
                ).done (data) ->
                  # We now have to store the new data in the database.
                  trans = Sync.db.transaction(["notes"], "readwrite")
                  store = trans.objectStore "notes"
                  request = store.put(data, item[1])

                  request.onsuccess = (e) =>
                    deferred.resolve()

              when "destroy"
                dbrequests[item[1]] = store.delete(item[1])
                file = item[1]

                # Delete in the butt
                $.ajax(
                  Sync.generateRequest
                    request: "destroy"
                    filename: file
                    dataType: "text"
                ).done (data) ->
                  deferred.resolve()

            return deferred.promise()
          )())

        # Almost all io done, replace metas now.
        $.when.apply($, promises).then ->

          # Copy into the app
          Sync.importData JSON.stringify(result[0])

          # Send it to my butt yo
          $.ajax(
            Sync.generateRequest
              request: "upload"
              filename: "meta"
              data: JSON.stringify(result[0])
          ).done (data) ->
            console.log("all done! Delete the queue")
            Sync.queue = {"Note": {}, "Notebook": {}}
            Sync.saveQueue()
            Spine.trigger 'sync:stop'

    ).error (data) ->
      if data.status is 401
        console.log "the bearer token is wrong. deleting token & please reauth"
        Sync.signOut()

      else if data.status is 404
        console.log "meta does not exist. uploading a new meta w/ every single file"

        promises = []
        $(Note.all()).each (i, e) ->
          e.loadNote (data) ->

            # make ajax request based on inputs from current loop element
            promises.push($.ajax(
                Sync.generateRequest
                  request: "upload"
                  filename: e.id
                  dataType: "text"
                  data: data
              )
            )

        # stuff
        $.when(promises).done ->
          console.log 'All files uploaded, uploading the meta file'

          $.ajax(
            Sync.generateRequest
              request: "upload"
              filename: "meta"
              data: Sync.exportData()
          ).done (data) ->
            console.log("all done! Delete the queue")
            Sync.queue = {"Note": {}, "Notebook": {}}
            Sync.saveQueue()
            Spine.trigger 'sync:stop'
            Note.trigger 'refresh'

  # It's *slightly* nicer having a function generating requests
  generateRequest: (opts) ->
    if Sync.oauth.service is "dropbox"
      params =
        crossDomain: true
        dataType: opts.dataType || "json"
        beforeSend: (xhr) ->
          xhr.setRequestHeader "Authorization", "Bearer " + Sync.oauth.access_token

      if opts.request is "me"
        params.type = "get"
        params.url = "https://api.dropbox.com/1/account/info"

      else if opts.request is "download"
        params.type = "get"
        params.url = "https://api-content.dropbox.com/1/files/sandbox/" + opts.filename + ".seed"

      else if opts.request is "upload"
        params.type = "put"
        params.contentType = opts.contentType || "application/octet-stream"
        params.url = "https://api-content.dropbox.com/1/files_put/sandbox/" + opts.filename + ".seed"
        params.data = opts.data

      else if opts.request is "destroy"
        params.type = "post"
        params.url = "https://api.dropbox.com/1/fileops/delete"
        params.data = {
          root: "sandbox"
          path: opts.filename + ".seed"
        }

    else if Sync.oauth.service is "skydrive"
      params =
        crossDomain: true
        dataType: opts.dataType || "json"

      if opts.request is "refresh"
        params.type = "get"
        params.url = "https://springseed.azurewebsites.net:443/refresh/skydrive?code=" + Sync.oauth.refresh_token

      else if opts.request is "me"
        params.type = "get"
        params.url = "https://apis.live.net/v5.0/me?access_token=" + Sync.oauth.access_token

      else if opts.request is "root"
        params.type = "get"
        params.url = "https://apis.live.net/v5.0/me/skydrive?access_token=" + Sync.oauth.access_token

      else if opts.request is "makeappdir"
        params.type = "post"
        params.contentType = "application/json"
        params.url = "https://apis.live.net/v5.0/me/skydrive/my_documents?access_token=" + Sync.oauth.access_token
        params.data = '{"name": "Springseed", "description": "Springseed App Data"}'

      else if opts.request is "findappdir"
        params.type = "get"
        params.url = "https://apis.live.net/v5.0/me/skydrive/my_documents/files?access_token=" + Sync.oauth.access_token

      else if opts.request is "listappdir"
        params.type = "get"
        params.url = "https://apis.live.net/v5.0/" + Sync.syncMeta.folderid + "/files?access_token=" + Sync.oauth.access_token

      else if opts.request is "download"
        params.type = "get"
        params.url = "https://apis.live.net/v5.0/" + Sync.syncMeta.map[opts.filename + ".seed"] + "/content?access_token=" + Sync.oauth.access_token

    params # return

  connect: (fn) ->

    # Only run connect once
    if @state is OFFLINE
      @state = IN_PROGRESS

      request = indexedDB.open("springseed", 1)

      request.onupgradeneeded = (e) =>
        @db = e.target.result

        # We're going to just be storing all the spine stuff in one store,
        # just because I cbf seperating the Keys.
        @db.createObjectStore("meta")

        # We'll make another store to seperate the note s
        @db.createObjectStore("notes")

      request.onsuccess = (e) =>
        Sync.db = e.target.result
        @state = ONLINE
        fn() if typeof fn is 'function'
        @_clearPending()

  # Check an event, and if it is a model update add it to the queue
  addToQueue: (event, args) ->
    if @queue[args.constructor.name][args.id] and @queue[args.constructor.name][args.id][0] is "create"
      # create + destroy = nothing
      if event is "destroy"
        delete @queue[args.constructor.name][args.id]
    else
      # Otherwiswe, add it to the queue
      @queue[args.constructor.name][args.id] = [event, Math.round(new Date()/1000)]
    @saveQueue()

  saveQueue: ->
    # Save queue to localstorage
    localStorage.Queue = JSON.stringify @queue

  exportData: (keys=["Note", "Notebook"]) ->
    # Export local data to JSON
    output = {
      "Note": Note.toJSON()
      "Notebook": Notebook.toJSON()
    }
    JSON.stringify(output)

  importData: (obj) ->
    input = JSON.parse(obj)

    # We have to save it to the db, otherwise it just hangs around in memory.
    Note.refresh(input.Note, clear: true)
    Notebook.refresh(input.Notebook, clear: true)
    Note.saveLocal()
    Notebook.saveLocal()

  # Merges the client & server, using a queue
  # Spits out the result, id changes & fs changes
  merger: (client, server, queue) ->

    # Creates an array index
    indexer = (db) ->
      result = {}
      for k,v of db
        # Sets Up Index
        result[k] = {}
        result[k].max = 0

        # Indexes Items
        for key, index in db[k]
          result[k][key.id] = index

          # Checks for the highest number
          num = parseInt(key.id.substring(2, key.id.length))
          result[k].max = num if num > result[k].max

      result #return

    clientindex = indexer(client)
    resultant = JSON.parse(JSON.stringify(server))
    resultantindex = indexer(resultant)
    namechanges = {"Notebook": [], "Note": []}
    fschanges = {"Notebook": [], "Note": []}

    # Add Changes from client
    for type of queue
      for key, value of queue[type]
        # Ensures that the key exists
          switch value[0]
            when "create"
              if clientindex[type][key]
                # we copy the change into the resultant
                oldId = key
                newId = "c-" + (resultantindex[type].max += 1)
                client[type][clientindex[type][key]].id = newId
                resultant[type].push(client[type][clientindex[type][key]])

                # update the index
                resultantindex[type][newId] = resultant[type].length

                # add to fschanges
                fschanges[type].push(["upload", newId])

                # add to name changes
                namechanges[type].push([oldId, newId]) if oldId isnt newId

            when "update"
              if clientindex[type][key]
                # If the item update was before the update on the server, create a conflicted copy
                if value[1] < resultant[type][resultantindex[type][key]].date
                  # bad case of DRY here

                  # we copy the change into the resultant
                  oldId = key
                  newId = "c-" + (resultantindex[type].max += 1)
                  client[type][clientindex[type][key]].id = newId
                  client[type][clientindex[type][key]].name += " (Conflicted Copy)"
                  resultant[type].push(client[type][clientindex[type][key]])

                  # update the index
                  resultantindex[type][newId] = resultant[type].length

                  # add to fschanges
                  fschanges[type].push(["download", resultant[type][resultantindex[type][key]].id])
                  fschanges[type].push(["upload", newId])

                  # add to name changes
                  namechanges[type].push([oldId, newId]) if oldId isnt newId
                else
                  # copies the new change in
                  resultant[type][resultantindex[type][key]] = client[type][clientindex[type][key]]

                  fschanges[type].push(["upload", resultant[type][resultantindex[type][key]].id])
            when "destroy"
              # If the item was after before the delete event, don't do anything
              if value[1] > resultant[type][resultantindex[type][key]].date
                # tell the server to delete it
                fschanges[type].push(["destroy", resultant[type][resultantindex[type][key]].id])

                # destroy the change from the resultant
                resultant[type].splice(resultantindex[type][key], 1)

                # reindex
                resultantindex = indexer(resultant)

    # Er, well if notebook name id changes we have to change note ids
    # @consindo is an idiot. Please send him angry messages.
    # This code is also annoying because it's not a keyvalue pair. That's what happens if you loop try to dry.
    # So, we'll build an index
    notebooknamechangesindex = {}
    for item in namechanges.Notebook
      notebooknamechangesindex[item[0]] = item[1]

    # Simple, right? Now we loop throught the notes and change the ids
    for k, v of resultant.Note
      if notebooknamechangesindex[v.notebook] isnt undefined
        v.notebook = notebooknamechangesindex[v.notebook]
        resultant.Note[k] = v

    # All the changes from the client should be added at this point
    # Now we detect the differences between the server copy and our client.

    # Basically, find timestamps that are newer on the server and stuff
    # that exists on the server but not the client.

    # We start by cloning the resultant
    original = JSON.parse(JSON.stringify(resultant))
    originalindex = indexer(original)

    # Removing all the stuff that is changed
    for type of fschanges
      for item in fschanges[type]
        original[type].splice(originalindex[type][item[1]], 1)
        originalindex = indexer(original)

    for type of original
      for key, value of original[type]
        # We only need to do this for stuff with dates, not anything else
        if value.date
          if client[type][clientindex[type][value.id]]
            if client[type][clientindex[type][value.id]].date < value.date
              # Server is newer than client, download from server
              fschanges[type].push(["download", value.id])
          else
            # Doesn't exist on client, download from server
            fschanges[type].push(["download", value.id])

    return [resultant, namechanges, fschanges]

# Just in case you need any default values
class Base

Model.Sync =

  extended: ->

    console.log '%c> Setting up sync for %s', 'font-weight: bold', this.name

    @fetch ->
      console.log '%c> Calling fetch', 'background: #eee'
      Sync.defer(this, @loadLocal)

    @change (record, event) ->
      Sync.addToQueue(event, record)
      console.log '%c> Calling change: ' + event, 'background: #eee'
      Sync.defer(this, @saveLocal)
      Sync.timeoutSync()

    Sync.connect()

  saveLocal: ->
    result = JSON.stringify(@)

    # Save to IndexedDB
    trans = Sync.db.transaction(["meta"], "readwrite")
    store = trans.objectStore "meta"
    request = store.put(result, @className)

  loadLocal: (options = {}) ->

    console.log "%c> Fetching #{@className}s", 'color: blue'

    options.clear = true unless options.hasOwnProperty('clear')

    # Load from IndexedDB
    trans = Sync.db.transaction(["meta"], "readwrite")
    store = trans.objectStore "meta"
    request = store.get(@className)

    request.onsuccess = (e) =>
      result = e.target.result
      @refresh(result or [], options)
      Spine.trigger "#{@className}:ready"

  saveNote: (content, callback) ->
    trans = Sync.db.transaction(["notes"], "readwrite")
    store = trans.objectStore "notes"
    request = store.put(content, @id)

    request.onsuccess = (e) =>
      Sync.timeoutSync()
      callback() if callback

  loadNote: (callback) ->
    trans = Sync.db.transaction(["notes"], "readwrite")
    store = trans.objectStore "notes"
    request = store.get(@id)

    request.onsuccess = (e) =>
      result = e.target.result
      callback(result) if callback

  deleteNote: (callback) ->
    trans = Sync.db.transaction(["notes"], "readwrite")
    store = trans.objectStore "notes"
    request = store.delete(@id)

    request.onsuccess = (e) =>
      callback() if callback

Model.Sync.Methods =
  extended: ->
    @extend Extend
    @include Include

module?.exports = Sync


================================================
FILE: app/controllers/upgrader.coffee
================================================
###############
# If you're reading this code, and you're like
# ERMAGERD, WHY IS THIS IDIOT USING NODE.JS, S`NOT EVEN ASYNC!!11!!
# Well, it's because Spine doesn't work too well when it's async.
# Not sure why, it just loves to run out of memory and crash.
###############
Spine = require 'spine'
marked = require 'marked'

Note = require '../models/note.coffee'
Notebook = require '../models/notebook.coffee'

class window.upgrader extends Spine.Controller
  constructor: ->
    super

    notebookPromise = new $.Deferred()
    notePromise = new $.Deferred()

    Spine.bind "Notebook:ready", notebookPromise.resolve
    Spine.bind "Note:ready", notePromise.resolve

    $.when.apply($, [notebookPromise.promise(), notePromise.promise()]).then =>
      @upgrade(localStorage.version)
      localStorage.version = "2.0"

  upgrade: (version) ->
    # New install, add default notes
    if version is undefined
      for notebook in ['Personal', 'Scrap', 'Work']
        Notebook.create
          name: notebook
          attributes: {starred: false}
          categories: ["General"]
          date: Math.round(new Date()/1000)

      # Semi Ajaxed in, rather than hardcoded.
      $.getJSON('default.json').done (data) ->
        for defaultNote in data
          note = Note.create
            name: defaultNote.name
            excerpt: defaultNote.content.substring(0, 100)
            notebook: 'c-2'
            category: 'General'
            date: Math.round(new Date().getTime()/1000)
          note.saveNote defaultNote.content

        # For whatever reason, it doesn't reload afterwards?
        $("#notebook-all").trigger("click")

    else if version is "1.1"
      console.log "Upgrading DB"
      for note in Note.toJSON()
        note = Note.create
          name: note.name
          starred: false
          categories: note.categories
          date: note.date
        Note.find(note.id).destroy()

      $.getJSON('default.json').done (data) ->
        for defaultNote in data
          note = Note.create
            name: defaultNote.name
            excerpt: defaultNote.content.substring(0, 100)
            notebook: 'c-2'
            category: 'General'
            date: Math.round(new Date().getTime()/1000)
          note.saveNote defaultNote.content

        # For whatever reason, it doesn't reload afterwards?
        $("#notebook-all").trigger("click")

    else if version is "1.0"
      path = window.require 'path'
      fs = window.require 'fs'

      # Make variables. Do checks.
      homedir = window.process.env.HOME

      # Set up where we're going to store stuff.
      if window.process.platform is 'darwin'
        storagedir = path.join(homedir, "/Library/Application Support/Springseed/")
      else if window.process.platform is 'win32'
        storagedir = path.join(process.env.LOCALAPPDATA, "/Springseed/")
      else if window.process.platform is 'linux'
        storagedir = path.join(homedir, '/.config/Springseed/')

      notebookdir = path.join(storagedir, 'Notebooks')
      notebooks = {}

      files = fs.readdirSync notebookdir
      files.forEach (file) =>
        if file.substr(16,5) is ".list"

          # Read the file, syncronously.
          data = fs.readFileSync path.join(notebookdir, file)
          console.log data.toString()

          # Read the old notebook, create a new spine model
          try
            oldnotebook = JSON.parse(data)
            newNotebook = Notebook.create
              name: oldnotebook.name
              categories: ["General"]
              date: Math.round(new Date()/1000)
            # Our mapping array to show the new positions
            notebooks[oldnotebook.id] = newNotebook.id
          catch error
            console.log("there was an error", id)
            # Eh, what can we do?
            return

      # Load the notes from the notebook into the model
      files.forEach (file) =>
        if file.substr(33,5) is ".note"
          raw = fs.readFileSync path.join(notebookdir, file)
          try
            contents = JSON.parse(raw)
            contents.notebook = notebooks[contents.notebook]
          catch error
            contents = {
              name: "Untitled Note"
              content: raw.toString()
              date: Math.round(new Date()/1000)
              notebook: Notebook.all()[0].id
            }

          note = Note.create
            name: contents.name
            excerpt: $(marked(contents.content.substring(0,100))).text()
            notebook: contents.notebook
            category: "General"
            date: contents.date
          note.saveNote(contents.content)

module.exports = upgrader


================================================
FILE: app/index.coffee
================================================
require './lib/setup.coffee'
Spine = require 'spine'

shell = window.require('shell') if window.require
Analytics = require 'analytics-node'

# Upgrader
Upgrader = require('./controllers/upgrader.coffee')

# Splitter. Not working in setup for whatever reason.
Splitter = require('./lib/splitter.js')

# Modals
Notebook = require './models/notebook.coffee'
Note = require './models/note.coffee'

# Controllers
Panel = require './controllers/panel.coffee'
Sidebar = require './controllers/sidebar.coffee'
Browser = require './controllers/browser.coffee'
Editor = require './controllers/editor.coffee'
Popover = require './controllers/popover.coffee'
Modal = require './controllers/modal.coffee'
Account = require './controllers/account.coffee'
Settings = require './controllers/settings.coffee'

class App extends Spine.Controller
  elements:
    '#panel': 'panel'
    '#sidebar': 'sidebar'
    '#browser': 'browser'
    '#editor': 'editor'
    '.popover-mask': 'popoverMask'
    '.modal.preferences': 'settings'

  events:
    'mousedown': 'checkSel'
    'mouseup': 'checkSel'

  constructor: ->
    super

    Account.enableChecks()
    Notebook.fetch()
    Note.fetch()

    anal = new Analytics('u9g1p9otaa')

    # We're nosey.
    anal.track({
      'userId': 'anonymous_user',
      'event': 'Open App',
      'properties': {
        'os': @getOS(),
        'country': @getCountry(),
        'language': navigator.language,
        'version': localStorage.version
      }
    })

    # Init the Splitter so we can see crap.
    Splitter.init
      parent: $('#parent')[0],
      panels:
        left:
          el: $("#sidebar")[0]
          min: 150
          width: 200
          max: 450
        center:
          el: $("#browser")[0]
          min: 250
          width: 300
          max: 850
        right:
          el: $("#editor")[0]
          min: 450
          width: 550
          max: Infinity

    Modal.init()

    Settings.init()

    @settings = Settings.get()

    # Init Stuff
    new Upgrader()
    @panel = new Panel( el: @panel )
    @sidebar = new Sidebar( el: @sidebar )
    @browser = new Browser( el: @browser )
    @editor = new Editor( el: @editor )
    @popover = new Popover( el: @popoverMask )

    # We'll put the sync conenct here as well.
    Spine.trigger 'sync:authorized' if Sync.oauth.service != "undefined"
    Sync.anal()

    # Stuff for node webkit.
    $('a').on 'click', (e) ->
      e.preventDefault()
      if e.which is 1 or e.which is 2
        shell.openExternal $(@).attr("href")
      return false

    # Going to use this to enable the dev tools, because yolo
    # konami_keys = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65]
    # konami_index = 0
    # $(document).keydown (e) ->
    #   location.reload() if e.keyCode is 116
    #   if e.keyCode is konami_keys[konami_index++]
    #     if konami_index is konami_keys.length
    #       $(document).unbind "keydown", arguments.callee
    #       <nw require>.Window.get().showDevTools()
    #   else
    #     konami_index = 0

  # We're sending an event to the editor here because we need the checksel to be global
  checkSel: ->
    @editor.trigger("checkSel")

  getOS: ->
    ua = navigator.userAgent
    return "Linux" if ua.indexOf("Linux") > -1
    return "Mac OS X 10.9" if ua.indexOf("Mac OS X 10_9") > -1
    return "Mac OS X 10.8" if ua.indexOf("Mac OS X 10_8") > -1
    return "Mac OS X 10.7" if ua.indexOf("Mac OS X 10_7") > -1
    return "Mac OS X 10.6" if ua.indexOf("Mac OS X 10_6") > -1
    return "Windows XP" if ua.indexOf("Windows NT 6.2") > -1
    return "Windows Vista" if ua.indexOf("Windows NT 6") > -1
    return "Windows 7" if ua.indexOf("Windows NT 6.1") > -1
    return "Windows 8" if ua.indexOf("Windows NT 6.2") > -1
    return "Windows 8.1" if ua.indexOf("Windows NT 6.3") > -1

  getCountry: ->
    $.getJSON 'http://freegeoip.net/json/', (loc) ->
      return loc.country_name


module.exports = App


================================================
FILE: app/init.coffee
================================================
jQuery  = require 'jqueryify'
exports = this
jQuery ->
  App = require './index.coffee'
  exports.app = new App
    el: $('body')


================================================
FILE: app/lib/setup.coffee
================================================
require('jqueryify')

require('spine')
require '../controllers/sync.coffee'


================================================
FILE: app/lib/splitter.js
================================================
(function() {

  // Variables
  var parent;
  var panels = {};
  var splitters = {};
  var parentOffset = 0;
  var width = 0;
  var active = false;
  var offset = {};
  var minWidth = 0;
  var last = {
    pos: 0,
    width: 0
  };


  // Class Panel
  var Panel = function(id, options) {
    this.id = id;
    this.el = options.el;
    this.min = options.min || 0;
    this.max = options.max || Infinity;
    this.width = options.width || 0;

    switch (this.id) {
      case "left":
        this.pos = 0;
        break;
      case "center":
        this.pos = panels.left.width;
        break;
      case "right":
        this.pos = panels.left.width + panels.center.width;
        break;
    }

    if (this.id !== "right") { this.el.style.width = this.width + "px"; }
    this.el.style.left = this.pos + "px";

  };

  Panel.prototype = {
    move: function(position, relative) {
      if (relative) { this.pos += position; }
      else { this.pos = position; }
      this.el.style.left = this.pos + "px";
    },
    resize: function(width, relative) {
      if (relative) { this.width += width; }
      else { this.width = width; }
      if (this.width < this.min) { this.width = this.min; }
      else if (this.width > this.max) { this.width = this.max; }
      this.el.style.width = this.width + "px";
    }
  };


  // Class Splitter
  var Splitter = function(id) {
    this.id = id;
    this.el = doc.createElement("div")
    this.pos = 0;

    if (this.id === "left") {
      this.left = panels.left;
      this.right = panels.center;
    }
    else if (this.id === "right") {
      this.left = panels.center;
      this.right = panels.right;
    }

    this.el.className = "splitter split-" + this.id;
    this.el.style.left = this.right.pos + "px";
    this.left.el.insertAdjacentElement('afterend', this.el);
    this.pos = this.el.offsetLeft;
    this.el.obj = this;
    this.el.onmousedown = events.mousedown;

  };

  Splitter.prototype = {
    move: Panel.prototype.move,
    resize: function(pos) {
      var resizeWindow = true;

      // Left min
      if (pos < this.left.min + offset.left) {
        pos = this.left.min + offset.left;
      }

      // Left max
      else if (pos > this.left.max + offset.left) {
        pos = this.left.max + offset.left;
      }

      if (this.id === "right") {
        resizeWindow = false;

        // Right min
        if (offset.right - pos < this.right.min) {
          resizeWindow = true;
        }

        // Right max
        else if (offset.right - pos > this.right.max) {
          pos = offset.right - this.right.max;
        }
      }

      // Calculate diff
      var diff = pos - last.pos;
      if (diff === 0) {
        this.pos = pos;
        return true;
      }

      // Right Splitter
      if (this.id === "right") {
        panels.center.resize(pos - offset.left);
        panels.right.move(pos);
        splitters.right.move(pos);
      }

      // Left splitter
      else if (this.id === "left") {
        splitters.left.move(pos);
        splitters.right.move(pos + panels.center.width);
        panels.left.resize(pos - offset.left);
        panels.center.move(pos);
        panels.right.move(splitters.right.pos);
        minWidth = pos + panels.center.min + panels.right.min;
      }

      // Resize window frame
      if (mode === "node" && resizeWindow) {
        width += diff;
        offset.right = win.width = width;
      }

      // Save position
      this.pos = last.pos = pos;
    }
  };


  /*
    Node Webkit Support
    -------------------
    global.document = document
    global.window = window
  */
  var win, doc, mode;
  // Think cake is fucking this.
  // if (typeof(process) != "undefined") {
  //   mode = "node";
  //   console.log("2")
  //   win = global.gui.Window.get();
  //   doc = global.document;
  // } else {
    mode = "browser";
    win = window;
    doc = document;
  // }


  // Calculate position of cursor on parent.
  var getPos = function(clientX) {
    var pos = clientX - parentOffset;
    if (pos < 0) {
      pos = 0;
    }
    else if (pos > width) {
      pos = width;
    }
    return pos;
  };


  // Events
  var events = {

    mousedown: function(event) {
      active = this.obj;
      offset = {
        left: 0,
        right: width
      };
      if (active.id === "right") {
        offset.left = splitters.left.pos;
      }
      else if (active.id === "left") {
        offset.right = splitters.right.pos;
      }
      last.pos = getPos(event.clientX);
      doc.body.className = "resizing";
    },

    mousemove: function(event) {
      if (active) {
        var pos = getPos(event.clientX);
        active.resize(pos);
      }
    },

    mouseup: function() {

      if (mode == "node" && active.id === "left") {
        win.setMinimumSize(panels.left.max + panels.center.min + panels.right.min, 0);
      }

      doc.body.className = "";
      active = false;
    },

    resize: function() {

      // Only run if triggered by user
      if (!active) {

        // Get new width and check if it hase changed
        width = parent.offsetWidth;
        var diff = width - last.width;
        if (diff === 0 || width < minWidth) { return false; }

        // If window is shrinking
        if (diff < 0) {
          // Check right panel for min width
          if (panels.right.el.offsetWidth <= panels.right.min) {
            panels.center.resize(diff, true);
            panels.right.move(diff, true);
            splitters.right.move(diff, true);
          }
        }

        last.width = width;
      }
    }
  };

  var init = function(options) {

    // Get options
    parent = options.parent;

    // Create Panels
    panels.left = new Panel("left", options.panels.left);
    panels.center = new Panel("center", options.panels.center);
    panels.right = new Panel("right", options.panels.right);

    // Create Splitters
    splitters.left = new Splitter("left");
    splitters.right = new Splitter("right");

    // Get width of parent
    width = parent.offsetWidth;
    minWidth = panels.left.min + panels.center.min + panels.right.min;

    // Bind events
    doc.onmousemove = events.mousemove;
    doc.onmouseup = events.mouseup;
    window.onresize = events.resize;

  };

  var exports = {
    init: init,
    panels: panels,
    splitters: splitters
  };

  if (typeof(module) !== "undefined") {
    module.exports = exports;
  }
  else {
    window.Splitter = exports;
  }

}());


================================================
FILE: app/models/.gitkeep
================================================


================================================
FILE: app/models/note.coffee
================================================
Spine = require 'spine'
Notebook = require './notebook.coffee'

class window.Note extends Spine.Model
  @configure 'Note',
    'name',
    'starred',
    'excerpt',
    'notebook',
    'category',
    'date'

  @extend @Sync
  @include @Sync

  # Deletes it from IndexedDB
  @.bind "beforeDestroy", (note) ->
    note.deleteNote()

  # since we can't change .find, we can use this to the same effect
  @filter: (notebook, category) ->
    # returns all the notes if no notebook specified
    if notebook && notebook isnt "all"
      array = Note.findAllByAttribute("notebook", notebook)

      # because 0 evals to false in JS
      category = category.toString()
      # returns items in a category, unless not specfied
      if category && category isnt "all"
        # matches the id number to the realname. i wish i had made a better system.
        category = Notebook.find(notebook).categories[category]
        newArray = []
        for note in array
          newArray.push(note) if note.category is category
        array = newArray
    else
      array = Note.all()
    return array

  @search: (string) ->
    # Ported from 1.0
    results = []
    notes = Note.all()
    for note in notes
      if note.name.match(new RegExp(string, 'i'))# or content.match(new RegExp(string, 'i'))
        note.date = note.prettyDate()
        results.push(note)

    console.log(results)
    Notebook.trigger 'changeNotebook', {id: 'all', category: 'all', search: true, result: results}

  prettyDate: (time) =>
    date = new Date(@date * 1000)
    pad = (n) -> (if (n < 10) then ("0" + n) else n)

    month = [
      "Jan"
      "Feb"
      "Mar"
      "Apr"
      "May"
      "Jun"
      "Jul"
      "Aug"
      "Sep"
      "Oct"
      "Nov"
      "Dec"
    ]

    now = new Date()
    difference = 0
    oneDay = 86400000; # 1000*60*60*24 - one day in milliseconds
    words = ''

    # Find difference between days
    difference = Math.ceil((date.getTime() - now.getTime()) / oneDay)

    # Show difference nicely
    if difference is 0
      words = "Today"
      words = "Yesterday" if now.getDate() isnt date.getDate()
    else if difference is -1
      words = "Yesterday"
    else if difference > 0
      # If the user has a TARDIS
      words = "Today"
    else if difference > -15
      words = Math.abs(difference) + " days ago"
    else if difference > -365
      words = month[date.getMonth()] + " " + date.getDate()
    else
      words = pad(date.getFullYear())+"-"+(pad(date.getMonth()+1))+"-"+pad(date.getDate())

    words += " " + date.getHours() + ":" + pad(date.getMinutes()) if time

    return words


module.exports = Note


================================================
FILE: app/models/notebook.coffee
================================================
Spine = require 'spine'

class window.Notebook extends Spine.Model
  @configure 'Notebook',
    'name',
    'categories',
    'date'

  @extend @Sync

  @.bind "beforeUpdate", (notebook, context) ->
    if context isnt "date"
      notebook.updateAttributes {
        "date": Math.round(new Date()/1000)
      }, "date"

  @.bind "beforeDestroy", (notebook) ->
    for note in Note.filter(notebook.id, "all")
      note.destroy()

  subcategoryDestroy: (category) ->
    for note in Note.filter(Notebook.current.id, category)
      note.destroy()

    # this is a terrible hack. I will fix it maybe
    # in theory, they can't an empty subcategory string
    arr = @categories.slice(0)
    arr[category] = ""
    @updateAttribute 'categories', arr

module.exports = Notebook


================================================
FILE: app/views/.gitkeep
================================================


================================================
FILE: app/views/note.handlebars
================================================
<li id="note-{{id}}" draggable="true" data-notebook="{{notebook}}">
  <h2>{{name}}</h2>
  <time>{{date}}  - </time><span>{{{excerpt}}}</span>
</li>


================================================
FILE: app/views/notebook.handlebars
================================================
<li class="notebook" id="notebook-{{id}}"><span class="name">{{name}}</span><span class="icon"></span>
<ul class="category">
  <li data-category="all" class="selected">All Notes</li>
  {{#each categories}}
  <li data-category="{{@index}}">{{this}}</li>
  {{/each}}
</ul>
</li>


================================================
FILE: css/font.scss
================================================
@font-face {
  font-family: 'YK Thin';
  font-style: normal;
  font-weight: 400;
  src: url("YanoneKaffeesatz-Thin.ttf") format('ttf');
}
@font-face {
  font-family: 'YK Sans';
  font-style: normal;
  font-weight: 200;
  src: url("YanoneKaffeesatz-Thin.ttf") format('ttf');
}
@font-face {
  font-family: 'YK Sans';
  font-style: normal;
  font-weight: 300;
  src: url("YanoneKaffeesatz-Light.ttf") format('ttf');
}
@font-face {
  font-family: 'PT Sans';
  font-style: normal;
  font-weight: 400;
  src: url("YanoneKaffeesatz-Normal.ttf") format('ttf');
}
@font-face {
  font-family: 'PT Sans';
  font-style: normal;
  font-weight: 700;
  src: url("YanoneKaffeesatz-Bold.ttf") format('ttf');
}

================================================
FILE: css/keyframes.scss
================================================
@-webkit-keyframes zoom-in {
	0% {
		-webkit-transform: scale(0.1) transform3d(0,0,0);
	}

	100% {
		-webkit-transform: scale(1) transform3d(0,0,0);
	}
}

@-webkit-keyframes spin {
	0% {
		-webkit-transform: rotate(0deg) transform3d(0,0,0);
	}

	100% {
		-webkit-transform: rotate(3600deg) transform3d(0,0,0);
	}
}


================================================
FILE: css/new.scss
================================================
@import "font";
@import "normalize";
@import "keyframes";

$light-color: #ecf0f1;
$gray-color: #AAAAAA;
$dark-color: #2d3235;

$font: "YK Sans", sans-serif;
$light-font: "YK Thin", sans-serif;

.spin {
	-webkit-animation: spin 1s linear;
}

::-webkit-scrollbar {
	width: 5px;
}

::-webkit-scrollbar-thumb {
	background: rgba(0,0,0,0.25);
	border-radius: 2.5px;
}

body, input, textarea {
	font-family: $font;
	overflow: hidden;

	-webkit-font-smoothing: antialiased;
}

// Dragging stuff.
#sidebar, #panel, #browser, .drag {
	-webkit-app-region: drag;
	-webkit-user-select: none;
	cursor: default!important;
}

#sidebar, #browser, .nodrag {
	-webkit-app-region: no-drag;
}

//
//  ABOUT PAGE
//

body.about {
	text-align: center;
	font-family: $light-font;
	background: #F0F0F0;
	font-size: 16px;
	color: $dark-color;
	font-weight: 200;

	h1 {
		font-weight: 400;
	}

	p {
		font-size: 10px;
	}
}

// Panel

#panel {
	width: 100%;
	height: 15px;
	background: #FFFFFF;
	border-left: 200px solid $dark-color;
	box-shadow: 300px 0 0 0 $light-color inset;
	cursor: default;
}

#decor {
	display: inline-block;
	height: 19px;
	margin: 12px 9px;

	position: absolute;
	top:0;left:0;

	img {
		padding: 3px;

		-webkit-transition: all 0.25s ease;
	}
}

#loginbox {
	position: absolute;
	top: 0; right: 15px;
	text-align: right;
	padding: 5px;
	color: lighten($dark-color, 15%);

	.name {
		display: block;
		text-transform: uppercase;
		font-size: 10pt;
		font-weight: 600;
	}

	.gopro {
		display: block;
		text-transform: lowercase;
		font-size: 8pt;
		font-weight: 200;
	}
}

#parent {
	position: absolute;
	overflow: hidden;
	top: 15px; bottom: 0;
	left: 0; right: 0;
}

.panel {
	position: absolute;
	top: 0; bottom: 0;
	overflow: hidden;
	box-sizing: border-box;
}

#sidebar {
	position: absolute;
	left: 0;

	background: $dark-color;
	padding-bottom: 30px;

	.container {
		position: absolute;
		top: 0;
		width: 100%;
		bottom: 30px;
		overflow-x: hidden;

		& .title {
			padding: 10px 15px;
			color: $light-color;
			font-family: $light-font;
			font-size: 20pt;
			font-weight: 200;
		}
	}

	ul {
		list-style-type: none;
		padding: 0;
		margin: 0;
	}

	li.notebook {
		font-family: $light-font;
		font-size: 10pt;
		font-weight: 200;
		color: $light-color;
		padding: 10px 15px;
		margin: 5px 0;

		&.selected {
			background: darken($dark-color, 5%);
		}

		.name {
			font-size: 14pt;
		}
	}

	#settingsbar {
		position: absolute;
		bottom: 0; left: 0;
		color: $light-color;
		padding: 5px;

		& i {
			font-size: 12pt;
			cursor: pointer;
		}
	}

	input {
		background: $dark-color;
		border: none;
		font-size: 14pt;
		font-weight: 200;
		color: $light-color;
		padding: 10px 15px;
		margin: 5px 0;
	}
}

#browser {
	position: absolute;
	background: $light-color;
	overflow-x: hidden;
	overflow-y: auto;

	& .title {
		padding: 10px 15px;
		color: $dark-color;
		font-family: $light-font;
		font-size: 20pt;
		font-weight: 200;
	}

	& #new {
		font-size: 18pt;
		color: $dark-color;
		cursor: pointer;
	}

	ul {
		margin: 0;
		padding: 5px 0 0;
		list-style-type: none;
	}

	li {
		cursor: default;
		padding: 4px 15px 8px;
		color: $dark-color;
		line-height: 16px;
		font-family: $light-font;
		font-weight: 200;

		&.selected {
			background: darken($light-color, 5%);
		}
	}

	h2 {
		margin: 8px 0;
		font-size: 14pt;
		font-weight: 200;
	}

	span {
		font-size: 10pt;
		font-weight: 200;
	}

	time {
		display: none;
	}
}

#editor {
	position: absolute;
	background: #ffffff;
	right: 0;

	&.deselected {
		background: #FFFFFF url(img/page.svg) 50% 100px no-repeat;
		background-size: 140px;

		&::after {
			content: "Select a note using the sidebar.";
			position: absolute;
			top: 230px;
			font-weight: 200;
			font-size: 16pt;
			left: 0;
			right: 0;
			color: $gray-color;
			text-align: center;
		}

		header, #contentread, #contentwrite {
			display: none !important;
		}
	}

	header {
		margin: 0;
		background: #9b59b6;
		position: absolute;
		left: 15px; right: 15px;
		padding: 10px;

		.headerwrap {
			-webkit-user-select: none;

			.star {
				color: $light-color;
				font-size: 14pt;
			}

			.star.starred {
				color: #f1c40f;
			}

			input {
				font-weight: 200;
				outline: 0;
				margin: 0;
				color: white;
				padding: 5px;
				background: transparent;
				font-size: 18pt;
				border: 0;
				box-sizing: border-box;
				max-width: 400px;
			}

			.left {
				float: left;

				time {
					display: none;
				}
			}

			.right {
				float: right;

				a {
					color: $gray-color;
					font-size: 14pt;
					padding: 10px;
					cursor: pointer;
					display: inline-block;
				}

				button {
					color: white;
					border: none;
					background: transparent;
					font-size: 14pt;
					padding: 8px;
					outline: 0;
				}
			}
		}
	}

	&.edit {
		#contentread {
			display: none;
		}

		#contentwrite {
			display: block;
		}
	}
}

#contentscroller {
	position: absolute;
	top: 60px; bottom: 0;
	left: 0; right: 0;
	overflow-y: auto;
}

#contentread, #contentwrite {
	position: absolute;
	top: 0; bottom: 0;
	left: 0; right: 0;
	background: #FFFFFF;
	padding: 0 30px;
	color: $dark-color;
	font-family: $font;
}

#psuedoinput {
	position: fixed;
	top: -9999px;
}

#contentwrite {
	padding: 35px 25px;
	display: none;

	> .inner {
		width: 100%;
		margin: 0;
		font-size: 15px;
		line-height: 1.1;
		padding: 0 0 30px;
		outline: none;
		white-space: pre-wrap;
	}

	& > .wc {
		position: fixed;
		bottom: 5px;
		right: 5px;
		border-radius: 3px;
		font-size: 12px;
		padding: 5px 10px;
		background: #3f3b3a;
		color: white;
		display: block-inline;
	}
}

#contentread {
	padding: 35px 25px;
	bottom: auto;
	z-index: 4;
	line-height: 1.1;
	font-size: 15px;
	font-family: $light-font;
	font-weight: 200;

	:first-child {
		margin-top: 0;
	}

	h1, h2, h3 {
		margin-bottom: 0.2em;
		font-weight: 400;
	}

	ul {
		padding: 0 0 0 20px;
	}

	p {
		margin-top: 0.4em;
	}

	a {
		color: #2d8dd6;
		text-decoration: none;

		&:hover {
			text-decoration: underline;
		}
	}

	code, pre {
		font-size: 0.95em;
		line-height: 1.1;
		font-family: monospace;
	}

	& > .wc {
		display: none;
	}
}

.modal {
	display: none;
	font-size: 14px;
	color: hsl(0,0,30%);
	width: 100%;
	height: 100%;
	opacity: 0;
	z-index: 9999!important;
	background: rgba(0,0,0,0.7);
	position: absolute;
	top: 0; left: 0;
	bottom: 0; right: 0;
	-webkit-transition: .3s opacity ease;
	-webkit-user-select: none;
	-webkit-tap-highlight-color: rgba(0,0,0,0);

	&.show {
		opacity: 1;

		& > div {
			-webkit-transition: .3s zoom-in ease linear;
		}
	}

	& > div {
		position: absolute;
		top: 15%;
		left: 50%;
		background: white;
		font-size: 16px;
		box-shadow: 0 2px 15px rgba(0,0,0,0.2);
	}

	.delete-container, .error-container {
		width: 600px;
		margin-left: -328px;
		padding: 25px;
		text-align: center;
		font-size: 18px;
		font-weight: 200;
		color: $dark-color;
		border: 5px solid #E15556;

		h1 {
			-webkit-user-select: none;
		}

		span.name {
			font-weight: 400;
		}
	}

	.syncmeta-container {
		width: 600px;
		margin-left: -328px;
		padding: 25px;
		text-align: center;
		font-size: 16px;
		font-weight: 200;
		color: $dark-color;
		border: 5px solid #66BE7F;

		.special {
			border-color: #E15556;
		}

		.special.green {
			border-color: #66BE7F;
		}
	}

	.newNote-container {
		width: 600px;
		margin-left: -328px;
		padding: 25px;
		text-align: center;
		font-size: 16px;
		font-weight: 200;
		color: $dark-color;
		border: 5px solid #66BE7F;
	}

	.rename-container {
		width: 600px;
		margin-left: -328px;
		padding: 25px;
		text-align: center;
		font-size: 16px;
		font-weight: 200;
		color: $dark-color;
		border: 5px solid $dark-color;

		.special {
			border-color: #E15556;
		}

		.special.green {
			border-color: #66BE7F;
		}
	}

	.preferences-container {
		width: 450px;
		margin-left: -227px;
		text-align: center;
		font-size: 16px;
		color: $dark-color;
		border: 5px solid #9b59b6;
		font-weight: 200;

		.tabs {
			border-bottom: 2px solid #9b59b6;

			ul {
				list-style: none;
				margin: 0;
				padding: 0;
				font-size: 0;
			}

			li {
				display: inline-block;
				line-height: 30px;
				font-size: 15px;
				padding: 0 15px;
				font-weight: 400;
				color: $dark-color;
				cursor: default;

				&:active {
					color: darken(#9b59b6, 15%);
				}

				&.current {
					background: #9b59b6;
					color: white;
				}
			}
		}

		a {
			text-decoration: none;
		}

		.account {
			padding: 10px;

			.pro {
				background: #9b59b6;
				color: white;
				padding: 1px 35px 20px;
				margin: 10px -35px;

				p {
					font-weight: normal;
				}
			}
		}

		.container {
			padding: 10px 25px;
		}

		.signedin, .signedout {
			padding-bottom: 15px;
			p {
				margin: 0;
			}
			button {
				font-size: 13px;
			}
		}

		.signedin {
			display: none;
		}

		input {
			display: block;
			text-decoration: none;
			border-radius: 0.0001px;
			border: 1px solid $light-color;
			background: lighten($light-color, 5%);
			margin: 10px 0 0;
			padding: 10px 15px;
			font-size: 10pt;
		}

		.about, .sync, .account {
			display: none;
			text-align: left;

			h1 {
				font-weight: 400;
			}

			p {
				font-weight: 200;
				font-size: 10pt;
			}

			& img {
				float: left;
				margin-right: 10px;
			}

			&.current {
				display: block;
			}
		}
	}

	button.special, a.special {
		display: inline-block;
		text-decoration: none;
		border-radius: 0.0001px;
		border: 1px solid $light-color;
		background: lighten($light-color, 5%);
		margin: 10px 0 0;
		padding: 10px 20px;
	}
}

#editorcontrols {
	display: none;
	position: absolute;
	z-index: 1000;
	background: $dark-color;
	box-shadow: 0 2px 5px rgba(0,0,0,0.2);
}

#editorcontrols button {
	-webkit-transition: 200ms ease all;
	padding: 10px 15px;
	float: left;
	border: 0;
	background: transparent;
}

#editorcontrols button:hover {
	background: rgba(0,0,0,0.15);
}

.popover-mask {
	display: none;
	z-index: 100;
	width: 100%;
	height: 100%;
	position: absolute;
	top: 0;

	& > div {
		display: none;

		input {
			background: $light-color;
			display: block;
			font-size: 14pt;
			font-weight: 200;
			border: 0;
			width: 100%;
			box-sizing: border-box;
			padding: 5px 10px;
			outline: 0;
			color: $gray-color;
			text-align: left;

			-webkit-transition: .5s all ease;
		}

		button {
			background: $light-color;
			display: block;
			font-size: 14pt;
			font-weight: 200;
			border: 0;
			width: 100%;
			box-sizing: border-box;
			padding: 5px 10px;
			outline: 0;
			color: $gray-color;
			text-align: left;

			-webkit-transition: .5s all ease;
		}

		button:hover {
			color: $dark-color;
		}
	}
}

.delete-popover, .category-popover {
	display: inline-block;
	width: 300px;
	height: 36px;
	position: absolute;

	.arrow {
		display: none;
	}

	.container {
		display: inline-block;
		background: $light-color;
		width: 150px;
		vertical-align: top;
		padding: 5px;
		box-shadow: 0 0 5px rgba(0,0,0,0.2);
	}

	input {
		width: 100px;
	}
}

.category { display: none; }

.expanded .category { display: block; }

.category .selected { font-weight: 400; }


img.emoji {
	width: 20px;
	height: 20px;
}


================================================
FILE: css/normalize.scss
================================================
/*! normalize.css v1.0.1 | MIT License | git.io/normalize */

/* ==========================================================================
   HTML5 display definitions
   ========================================================================== */

/*
 * Corrects `block` display not defined in IE 6/7/8/9 and Firefox 3.
 */

article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
nav,
section,
summary {
    display: block;
}

/*
 * Corrects `inline-block` display not defined in IE 6/7/8/9 and Firefox 3.
 */

audio,
canvas,
video {
    display: inline-block;
    *display: inline;
    *zoom: 1;
}

/*
 * Prevents modern browsers from displaying `audio` without controls.
 * Remove excess height in iOS 5 devices.
 */

audio:not([controls]) {
    display: none;
    height: 0;
}

/*
 * Addresses styling for `hidden` attribute not present in IE 7/8/9, Firefox 3,
 * and Safari 4.
 * Known issue: no IE 6 support.
 */

[hidden] {
    display: none;
}

/* ==========================================================================
   Base
   ========================================================================== */

/*
 * 1. Corrects text resizing oddly in IE 6/7 when body `font-size` is set using
 *    `em` units.
 * 2. Prevents iOS text size adjust after orientation change, without disabling
 *    user zoom.
 */

html {
    font-size: 100%; /* 1 */
    -webkit-text-size-adjust: 100%; /* 2 */
    -ms-text-size-adjust: 100%; /* 2 */
}

/*
 * Addresses `font-family` inconsistency between `textarea` and other form
 * elements.
 */

html,
button,
input,
select,
textarea {
    font-family: sans-serif;
}

/*
 * Addresses margins handled incorrectly in IE 6/7.
 */

body {
    margin: 0;
}

/* ==========================================================================
   Links
   ========================================================================== */

/*
 * Addresses `outline` inconsistency between Chrome and other browsers.
 */

a:focus {
    outline: thin dotted;
}

/*
 * Improves readability when focused and also mouse hovered in all browsers.
 */

a:active,
a:hover {
    outline: 0;
}

/* ==========================================================================
   Typography
   ========================================================================== */

/*
 * Addresses font sizes and margins set differently in IE 6/7.
 * Addresses font sizes within `section` and `article` in Firefox 4+, Safari 5,
 * and Chrome.
 */

h1 {
    font-size: 2em;
    margin: 0.67em 0;
}

h2 {
    font-size: 1.5em;
    margin: 0.83em 0;
}

h3 {
    font-size: 1.17em;
    margin: 1em 0;
}

h4 {
    font-size: 1em;
    margin: 1.33em 0;
}

h5 {
    font-size: 0.83em;
    margin: 1.67em 0;
}

h6 {
    font-size: 0.75em;
    margin: 2.33em 0;
}

/*
 * Addresses styling not present in IE 7/8/9, Safari 5, and Chrome.
 */

abbr[title] {
    border-bottom: 1px dotted;
}

/*
 * Addresses style set to `bolder` in Firefox 3+, Safari 4/5, and Chrome.
 */

b,
strong {
    font-weight: bold;
}

blockquote {
    margin: 1em 40px;
}

/*
 * Addresses styling not present in Safari 5 and Chrome.
 */

dfn {
    font-style: italic;
}

/*
 * Addresses styling not present in IE 6/7/8/9.
 */

mark {
    background: #ff0;
    color: #000;
}

/*
 * Addresses margins set differently in IE 6/7.
 */

p,
pre {
    margin: 1em 0;
}

/*
 * Corrects font family set oddly in IE 6, Safari 4/5, and Chrome.
 */

code,
kbd,
pre,
samp {
    font-family: 'Source Code Pro', monospace;
    font-size: 1em;
}

/*
 * Improves readability of pre-formatted text in all browsers.
 */

pre {
    white-space: pre;
    white-space: pre-wrap;
    word-wrap: break-word;
}

/*
 * Addresses CSS quotes not supported in IE 6/7.
 */

q {
    quotes: none;
}

/*
 * Addresses `quotes` property not supported in Safari 4.
 */

q:before,
q:after {
    content: '';
    content: none;
}

/*
 * Addresses inconsistent and variable font size in all browsers.
 */

small {
    font-size: 80%;
}

/*
 * Prevents `sub` and `sup` affecting `line-height` in all browsers.
 */

sub,
sup {
    font-size: 75%;
    line-height: 0;
    position: relative;
    vertical-align: baseline;
}

sup {
    top: -0.5em;
}

sub {
    bottom: -0.25em;
}

/* ==========================================================================
   Lists
   ========================================================================== */

/*
 * Addresses margins set differently in IE 6/7.
 */

dl,
menu,
ol,
ul {
    margin: 1em 0;
}

dd {
    margin: 0 0 0 40px;
}

/*
 * Addresses paddings set differently in IE 6/7.
 */

menu,
ol,
ul {
    padding: 0 0 0 40px;
}

/*
 * Corrects list images handled incorrectly in IE 7.
 */

nav ul,
nav ol {
    list-style: none;
    list-style-image: none;
}

/* ==========================================================================
   Embedded content
   ========================================================================== */

/*
 * 1. Removes border when inside `a` element in IE 6/7/8/9 and Firefox 3.
 * 2. Improves image quality when scaled in IE 7.
 */

img {
    border: 0; /* 1 */
    -ms-interpolation-mode: bicubic; /* 2 */
}

/*
 * Corrects overflow displayed oddly in IE 9.
 */

svg:not(:root) {
    overflow: hidden;
}

/* ==========================================================================
   Figures
   ========================================================================== */

/*
 * Addresses margin not present in IE 6/7/8/9, Safari 5, and Opera 11.
 */

figure {
    margin: 0;
}

/* ==========================================================================
   Forms
   ========================================================================== */

/*
 * Corrects margin displayed oddly in IE 6/7.
 */

form {
    margin: 0;
}

/*
 * Define consistent border, margin, and padding.
 */

fieldset {
    border: 1px solid #c0c0c0;
    margin: 0 2px;
    padding: 0.35em 0.625em 0.75em;
}

/*
 * 1. Corrects color not being inherited in IE 6/7/8/9.
 * 2. Corrects text not wrapping in Firefox 3.
 * 3. Corrects alignment displayed oddly in IE 6/7.
 */

legend {
    border: 0; /* 1 */
    padding: 0;
    white-space: normal; /* 2 */
    *margin-left: -7px; /* 3 */
}

/*
 * 1. Corrects font size not being inherited in all browsers.
 * 2. Addresses margins set differently in IE 6/7, Firefox 3+, Safari 5,
 *    and Chrome.
 * 3. Improves appearance and consistency in all browsers.
 */

button,
input,
select,
textarea {
    font-size: 100%; /* 1 */
    margin: 0; /* 2 */
    vertical-align: baseline; /* 3 */
    *vertical-align: middle; /* 3 */
}

/*
 * Addresses Firefox 3+ setting `line-height` on `input` using `!important` in
 * the UA stylesheet.
 */

button,
input {
    line-height: normal;
}

/*
 * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
 *    and `video` controls.
 * 2. Corrects inability to style clickable `input` types in iOS.
 * 3. Improves usability and consistency of cursor style between image-type
 *    `input` and others.
 * 4. Removes inner spacing in IE 7 without affecting normal text inputs.
 *    Known issue: inner spacing remains in IE 6.
 */

button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
    -webkit-appearance: button; /* 2 */
    cursor: pointer; /* 3 */
    *overflow: visible;  /* 4 */
}

/*
 * Re-set default cursor for disabled elements.
 */

button[disabled],
input[disabled] {
    cursor: default;
}

/*
 * 1. Addresses box sizing set to content-box in IE 8/9.
 * 2. Removes excess padding in IE 8/9.
 * 3. Removes excess padding in IE 7.
 *    Known issue: excess padding remains in IE 6.
 */

input[type="checkbox"],
input[type="radio"] {
    box-sizing: border-box; /* 1 */
    padding: 0; /* 2 */
    *height: 13px; /* 3 */
    *width: 13px; /* 3 */
}

/*
 * 1. Addresses `appearance` set to `searchfield` in Safari 5 and Chrome.
 * 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome
 *    (include `-moz` to future-proof).
 */

input[type="search"] {
    -webkit-appearance: textfield; /* 1 */
    -moz-box-sizing: content-box;
    -webkit-box-sizing: content-box; /* 2 */
    box-sizing: content-box;
}

/*
 * Removes inner padding and search cancel button in Safari 5 and Chrome
 * on OS X.
 */

input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
    -webkit-appearance: none;
}

/*
 * Removes inner padding and border in Firefox 3+.
 */

button::-moz-focus-inner,
input::-moz-focus-inner {
    border: 0;
    padding: 0;
}

/*
 * 1. Removes default vertical scrollbar in IE 6/7/8/9.
 * 2. Improves readability and alignment in all browsers.
 */

textarea {
    overflow: auto; /* 1 */
    vertical-align: top; /* 2 */
}

/* ==========================================================================
   Tables
   ========================================================================== */

/*
 * Remove most spacing between table cells.
 */

table {
    border-collapse: collapse;
    border-spacing: 0;
}


================================================
FILE: package.json
================================================
{
    "main": "src/main.js",
    "name": "Springseed",
    "version": "2.0.0",
    "repository": {
        "type":"git",
        "url": "http://github.com/springseednotes/springseed.git"
    },
    "window": {
        "toolbar": true,
        "width": 1024,
        "height": 600,
        "position": "center",
        "min_width": 300,
        "min_height": 500
    },
    "dependencies": {
        "underscore": "1.4.x",
        "jqueryify": "~1.9.1",
        "spine": "~1.1.x",
        "marked": "0.2.9",
        "socket.io-client": "0.9.16",
        "highlight.js": "7.3.0",
        "open": "0.0.5",
        "analytics-node": "1.0.4"
    },
    "devDependencies": {
        "handlebars": "1.0.x",
        "coffee-script": "1.7.x",
        "browserify": "4.1.x",
        "coffeeify": "0.6.x"
    }
}


================================================
FILE: public/about.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <title>About</title>
    <link rel="stylesheet" type="text/css" href="application.css"/>
  </head>
  <body class="about">
    <img src="img/icon.svg" height="150">
    <h1>Springseed <small>2.0</small></h1>
    <p>Copyright &copy; 2012-2014 Springseed.</p>
    <p><a href="http://getspringseed.com">http://getspringseed.com/</a></p>
  </body>
</html>


================================================
FILE: public/default.json
================================================
[
	{
		"name": "Springseed!",
		"content": "Springseed 2.0 is here and there's a lot going on. We finally have a Twitter and Google+ page, which means that we're going to keep you updated with what is going on with Springseed.\n\nOur Twitter can be found at http://twitter.com/springseednotes whereas our Google+ page can be found at http://plus.google.com/+Getspringseed - we hope that you follow us on these platforms because it's great to let you know what's happening.\n\nIn other news, we're also working on other cool stuff so do try and get involved as much as you can, it means a lot to us!\n\nOh, and before we forgot, we also have IRC! We can be found at irc.freenode.net in #springseed"
	}
]


================================================
FILE: public/emojify.js
================================================
/*! emojify.js - v0.9.2 - 
 * Copyright (c) Hassan Khan 2014
 */!function(a){"use strict";var b=function(){function b(a){return" "===a||"	"===a||"\r"===a||"\n"===a||""===a}function c(a,b,c){var d=i.createElement("img");d.setAttribute("title",":"+c+":"),d.setAttribute("alt",":"+c+":"),d.setAttribute("class","emoji"),d.setAttribute("src",q.img_dir+"/"+c+".png"),d.setAttribute("align","absmiddle"),a.splitText(b.index),a.nextSibling.nodeValue=a.nextSibling.nodeValue.substr(b[0].length,a.nextSibling.nodeValue.length),d.appendChild(a.splitText(b.index)),a.parentNode.insertBefore(d,a.nextSibling)}function d(a){if(a[1]&&a[2]){var b=a[2];if(l[b])return b}else for(var c=3;c<a.length-1;c++)if(a[c])return n[c-2][1]}function e(a,b){return"<img title=':"+b+":' alt=':"+b+":' class='emoji' src='"+q.img_dir+"/"+b+".png' align='absmiddle' />"}function f(){this.lastEmojiTerminatedAt=-1}function g(a,b){if(!a)return a;b||(b=e);var c=new f;return a.replace(p,function(){var a=Array.prototype.slice.call(arguments,0,-2),d=arguments[arguments.length-2],e=arguments[arguments.length-1],f=c.validate(a,d,e);return f?b(arguments[0],f):arguments[0]})}function h(a){"undefined"==typeof a&&(a=q.only_crawl_id?i.getElementById(q.only_crawl_id):i.body);for(var b,e=q.ignored_tags,g=i.createTreeWalker(a,NodeFilter.SHOW_TEXT|NodeFilter.SHOW_ELEMENT,function(a){return 1!==a.nodeType?NodeFilter.FILTER_ACCEPT:e[a.tagName]||a.classList.contains("no-emojify")?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_SKIP},!1),h=[];null!==(b=g.nextNode());)h.push(b);h.forEach(function(a){for(var b,e=[],g=new f;null!==(b=p.exec(a.data));)g.validate(b,b.index,b.input)&&e.push(b);for(var h=e.length;h-->0;){var i=d(e[h]);c(a,e[h],i)}})}var i=a.window.document,j="100,109,1234,-1,+1,8ball,abcd,abc,ab,accept,aerial_tramway,airplane,alarm_clock,alien,ambulance,anchor,angel,anger,angry,anguished,ant,a,apple,aquarius,aries,arrow_backward,arrow_double_down,arrow_double_up,arrow_down,arrow_down_small,arrow_forward,arrow_heading_down,arrow_heading_up,arrow_left,arrow_lower_left,arrow_lower_right,arrow_right_hook,arrow_right,arrows_clockwise,arrows_counterclockwise,arrow_up_down,arrow_upper_left,arrow_upper_right,arrow_up,arrow_up_small,articulated_lorry,art,astonished,atm,baby_bottle,baby_chick,baby,baby_symbol,baggage_claim,balloon,ballot_box_with_check,bamboo,banana,bangbang,bank,barber,bar_chart,baseball,basketball,bath,bathtub,battery,bear,bee,beer,beers,beetle,beginner,bell,bento,bicyclist,bike,bikini,bird,birthday,black_circle,black_joker,black_nib,black_square_button,black_square,blossom,blowfish,blue_book,blue_car,blue_heart,blush,boar,boat,bomb,bookmark,bookmark_tabs,book,books,boom,boot,bouquet,bowling,bow,bowtie,boy,b,bread,bride_with_veil,bridge_at_night,briefcase,broken_heart,bug,bulb,bullettrain_front,bullettrain_side,bus,busstop,bust_in_silhouette,busts_in_silhouette,cactus,cake,calendar,calling,camel,camera,cancer,candy,capital_abcd,capricorn,card_index,carousel_horse,car,cat2,cat,cd,chart,chart_with_downwards_trend,chart_with_upwards_trend,checkered_flag,cherries,cherry_blossom,chestnut,chicken,children_crossing,chocolate_bar,christmas_tree,church,cinema,circus_tent,city_sunrise,city_sunset,clapper,clap,clipboard,clock1030,clock10,clock1130,clock11,clock1230,clock12,clock130,clock1,clock230,clock2,clock330,clock3,clock430,clock4,clock530,clock5,clock630,clock6,clock730,clock7,clock830,clock8,clock930,clock9,closed_book,closed_lock_with_key,closed_umbrella,cloud,cl,clubs,cn,cocktail,coffee,cold_sweat,collision,computer,confetti_ball,confounded,confused,congratulations,construction,construction_worker,convenience_store,cookie,cool,cop,copyright,corn,couplekiss,couple,couple_with_heart,cow2,cow,credit_card,crocodile,crossed_flags,crown,crying_cat_face,cry,crystal_ball,cupid,curly_loop,currency_exchange,curry,custard,customs,cyclone,dancer,dancers,dango,dart,dash,date,deciduous_tree,department_store,de,diamond_shape_with_a_dot_inside,diamonds,disappointed,disappointed_relieved,dizzy_face,dizzy,dog2,dog,dollar,dolls,dolphin,do_not_litter,donut,door,doughnut,dragon_face,dragon,dress,dromedary_camel,droplet,dvd,ear_of_rice,ear,earth_africa,earth_americas,earth_asia,eggplant,egg,eight,eight_pointed_black_star,eight_spoked_asterisk,electric_plug,elephant,e-mail,email,end,envelope,es,european_castle,european_post_office,euro,evergreen_tree,exclamation,expressionless,eyeglasses,eyes,facepunch,factory,fallen_leaf,family,fast_forward,fax,fearful,feelsgood,feet,ferris_wheel,file_folder,finnadie,fire_engine,fire,fireworks,first_quarter_moon,first_quarter_moon_with_face,fish_cake,fishing_pole_and_fish,fish,fist,five,flags,flashlight,floppy_disk,flower_playing_cards,flushed,foggy,football,fork_and_knife,fountain,four_leaf_clover,four,free,fried_shrimp,fries,frog,frowning,fr,fuelpump,full_moon,full_moon_with_face,fu,game_die,gb,gemini,gem,ghost,gift_heart,gift,girl,globe_with_meridians,goat,goberserk,godmode,golf,grapes,green_apple,green_book,green_heart,grey_exclamation,grey_question,grimacing,grinning,grin,guardsman,guitar,gun,haircut,hamburger,hammer,hamster,handbag,hand,hankey,hash,hatched_chick,hatching_chick,headphones,hear_no_evil,heartbeat,heart_decoration,heart_eyes_cat,heart_eyes,heart,heartpulse,hearts,heavy_check_mark,heavy_division_sign,heavy_dollar_sign,heavy_exclamation_mark,heavy_minus_sign,heavy_multiplication_x,heavy_plus_sign,helicopter,herb,hibiscus,high_brightness,high_heel,hocho,honeybee,honey_pot,horse,horse_racing,hospital,hotel,hotsprings,hourglass_flowing_sand,hourglass,house,house_with_garden,hurtrealbad,hushed,ice_cream,icecream,ideograph_advantage,id,imp,inbox_tray,incoming_envelope,information_desk_person,information_source,innocent,interrobang,iphone,it,izakaya_lantern,jack_o_lantern,japanese_castle,japanese_goblin,japanese_ogre,japan,jeans,joy_cat,joy,jp,keycap_ten,key,kimono,kissing_cat,kissing_closed_eyes,kissing_face,kissing_heart,kissing,kissing_smiling_eyes,kiss,koala,koko,kr,large_blue_circle,large_blue_diamond,large_orange_diamond,last_quarter_moon,last_quarter_moon_with_face,laughing,leaves,ledger,left_luggage,left_right_arrow,leftwards_arrow_with_hook,lemon,leopard,leo,libra,light_rail,link,lips,lipstick,lock,lock_with_ink_pen,lollipop,loop,loudspeaker,love_hotel,love_letter,low_brightness,mag,mag_right,mahjong,mailbox_closed,mailbox,mailbox_with_mail,mailbox_with_no_mail,man,mans_shoe,man_with_gua_pi_mao,man_with_turban,maple_leaf,mask,massage,meat_on_bone,mega,melon,memo,mens,metal,metro,microphone,microscope,milky_way,minibus,minidisc,mobile_phone_off,moneybag,money_with_wings,monkey_face,monkey,monorail,moon,mortar_board,mountain_bicyclist,mountain_cableway,mountain_railway,mount_fuji,mouse2,mouse,movie_camera,moyai,m,muscle,mushroom,musical_keyboard,musical_note,musical_score,mute,nail_care,name_badge,neckbeard,necktie,negative_squared_cross_mark,neutral_face,new_moon,new_moon_with_face,new,newspaper,ng,nine,no_bell,no_bicycles,no_entry,no_entry_sign,no_good,no_mobile_phones,no_mouth,non-potable_water,no_pedestrians,nose,no_smoking,notebook,notebook_with_decorative_cover,notes,nut_and_bolt,o2,ocean,octocat,octopus,oden,office,ok_hand,ok,ok_woman,older_man,older_woman,oncoming_automobile,oncoming_bus,oncoming_police_car,oncoming_taxi,one,on,open_file_folder,open_hands,open_mouth,ophiuchus,o,orange_book,outbox_tray,ox,page_facing_up,pager,page_with_curl,palm_tree,panda_face,paperclip,parking,part_alternation_mark,partly_sunny,passport_control,paw_prints,peach,pear,pencil2,pencil,penguin,pensive,performing_arts,persevere,person_frowning,person_with_blond_hair,person_with_pouting_face,phone,pig2,pig_nose,pig,pill,pineapple,pisces,pizza,plus1,point_down,point_left,point_right,point_up_2,point_up,police_car,poodle,poop,postal_horn,postbox,post_office,potable_water,pouch,poultry_leg,pound,pouting_cat,pray,princess,punch,purple_heart,purse,pushpin,put_litter_in_its_place,question,rabbit2,rabbit,racehorse,radio_button,radio,rage1,rage2,rage3,rage4,rage,railway_car,rainbow,raised_hand,raised_hands,raising_hand,ramen,ram,rat,recycle,red_car,red_circle,registered,relaxed,relieved,repeat_one,repeat,restroom,revolving_hearts,rewind,ribbon,rice_ball,rice_cracker,rice,rice_scene,ring,rocket,roller_coaster,rooster,rose,rotating_light,round_pushpin,rowboat,rugby_football,runner,running,running_shirt_with_sash,ru,sagittarius,sailboat,sake,sandal,santa,sa,satellite,satisfied,saxophone,school,school_satchel,scissors,scorpius,scream_cat,scream,scroll,seat,secret,seedling,see_no_evil,seven,shaved_ice,sheep,shell,shipit,ship,shirt,shit,shoe,shower,signal_strength,six,six_pointed_star,ski,skull,sleeping,sleepy,slot_machine,small_blue_diamond,small_orange_diamond,small_red_triangle_down,small_red_triangle,smile_cat,smile,smiley_cat,smiley,smiling_imp,smirk_cat,smirk,smoking,snail,snake,snowboarder,snowflake,snowman,sob,soccer,soon,sos,sound,space_invader,spades,spaghetti,sparkler,sparkles,sparkling_heart,speaker,speak_no_evil,speech_balloon,speedboat,squirrel,star2,star,stars,station,statue_of_liberty,steam_locomotive,stew,straight_ruler,strawberry,stuck_out_tongue_closed_eyes,stuck_out_tongue,stuck_out_tongue_winking_eye,sunflower,sunglasses,sunny,sunrise_over_mountains,sunrise,sun_with_face,surfer,sushi,suspect,suspension_railway,sweat_drops,sweat,sweat_smile,sweet_potato,swimmer,symbols,syringe,tada,tanabata_tree,tangerine,taurus,taxi,tea,telephone,telephone_receiver,telescope,tennis,tent,thought_balloon,three,thumbsdown,thumbsup,ticket,tiger2,tiger,tired_face,tm,toilet,tokyo_tower,tomato,tongue,tophat,top,tractor,traffic_light,train2,train,tram,triangular_flag_on_post,triangular_ruler,trident,triumph,trolleybus,trollface,trophy,tropical_drink,tropical_fish,truck,trumpet,tshirt,tulip,turtle,tv,twisted_rightwards_arrows,two_hearts,two_men_holding_hands,two,two_women_holding_hands,u5272,u5408,u55b6,u6307,u6708,u6709,u6e80,u7121,u7533,u7981,u7a7a,uk,umbrella,unamused,underage,unlock,up,us,vertical_traffic_light,vhs,vibration_mode,video_camera,video_game,violin,virgo,volcano,v,vs,walking,waning_crescent_moon,waning_gibbous_moon,warning,watch,water_buffalo,watermelon,wave,wavy_dash,waxing_crescent_moon,waxing_gibbous_moon,wc,weary,wedding,whale2,whale,wheelchair,white_check_mark,white_circle,white_flower,white_large_square,white_square_button,white_square,wind_chime,wine_glass,wink2,wink,wolf,woman,womans_clothes,womans_hat,womens,worried,wrench,x,yellow_heart,yen,yum,zap,zero,zzz",k=j.split(/,/),l=k.reduce(function(a,b){return a[b]=!0,a},{}),m={named:/:([a-z0-9A-Z_-]+):/,blush:/:-?\)/g,scream:/:-o/gi,smirk:/[:;]-?]/g,smiley:/[:;]-?d/gi,stuck_out_tongue_closed_eyes:/x-d/gi,stuck_out_tongue_winking_eye:/[:;]-?p/gi,rage:/:-?[\[@]/g,disappointed:/:-?\(/g,sob:/:['’]-?\(|:&#x27;\(/g,kissing_heart:/:-?\*/g,wink:/;-?\)/g,pensive:/:-?\//g,confounded:/:-?s/gi,flushed:/:-?\|/g,relaxed:/:-?\$/g,mask:/:-x/gi,heart:/<3|&lt;3/g,broken_heart:/<\/3|&lt;&#x2F;3/g,thumbsup:/:\+1:/g,thumbsdown:/:\-1:/g},n=Object.keys(m).map(function(a){return[m[a],a]}),o=n.map(function(a){var b=a[0],c=b.source||b;return c=c.replace(/(^|[^\[])\^/g,"$1"),"("+c+")"}).join("|"),p=new RegExp(o,"gi"),q={emojify_tag_type:"div",only_crawl_id:null,img_dir:"images/emoji",ignored_tags:{SCRIPT:1,TEXTAREA:1,A:1,PRE:1,CODE:1}};return f.prototype={validate:function(a,c,e){function f(){return g.lastEmojiTerminatedAt=j+c,h}var g=this,h=d(a);if(h){var i=a[0],j=i.length;if(0===c)return f();if(e.length===i.length+c)return f();var k=this.lastEmojiTerminatedAt===c;if(k)return f();if(b(e.charAt(c-1)))return f();var l=b(e.charAt(i.length+c));return l&&k?f():void 0}}},{defaultConfig:q,emojiNames:k,setConfig:function(a){Object.keys(q).forEach(function(b){b in a&&(q[b]=a[b])})},replace:g,run:h}}();return a.emojify=b,"function"==typeof define&&define.amd&&define([],function(){return b}),b}(this);

================================================
FILE: public/handlebars.runtime.js
================================================
/*

Copyright (C) 2011 by Yehuda Katz

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

// lib/handlebars/browser-prefix.js
var Handlebars = {};

(function(Handlebars, undefined) {
;
// lib/handlebars/base.js

Handlebars.VERSION = "1.0.0";
Handlebars.COMPILER_REVISION = 4;

Handlebars.REVISION_CHANGES = {
  1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
  2: '== 1.0.0-rc.3',
  3: '== 1.0.0-rc.4',
  4: '>= 1.0.0'
};

Handlebars.helpers  = {};
Handlebars.partials = {};

var toString = Object.prototype.toString,
    functionType = '[object Function]',
    objectType = '[object Object]';

Handlebars.registerHelper = function(name, fn, inverse) {
  if (toString.call(name) === objectType) {
    if (inverse || fn) { throw new Handlebars.Exception('Arg not supported with multiple helpers'); }
    Handlebars.Utils.extend(this.helpers, name);
  } else {
    if (inverse) { fn.not = inverse; }
    this.helpers[name] = fn;
  }
};

Handlebars.registerPartial = function(name, str) {
  if (toString.call(name) === objectType) {
    Handlebars.Utils.extend(this.partials,  name);
  } else {
    this.partials[name] = str;
  }
};

Handlebars.registerHelper('helperMissing', function(arg) {
  if(arguments.length === 2) {
    return undefined;
  } else {
    throw new Error("Missing helper: '" + arg + "'");
  }
});

Handlebars.registerHelper('blockHelperMissing', function(context, options) {
  var inverse = options.inverse || function() {}, fn = options.fn;

  var type = toString.call(context);

  if(type === functionType) { context = context.call(this); }

  if(context === true) {
    return fn(this);
  } else if(context === false || context == null) {
    return inverse(this);
  } else if(type === "[object Array]") {
    if(context.length > 0) {
      return Handlebars.helpers.each(context, options);
    } else {
      return inverse(this);
    }
  } else {
    return fn(context);
  }
});

Handlebars.K = function() {};

Handlebars.createFrame = Object.create || function(object) {
  Handlebars.K.prototype = object;
  var obj = new Handlebars.K();
  Handlebars.K.prototype = null;
  return obj;
};

Handlebars.logger = {
  DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, level: 3,

  methodMap: {0: 'debug', 1: 'info', 2: 'warn', 3: 'error'},

  // can be overridden in the host environment
  log: function(level, obj) {
    if (Handlebars.logger.level <= level) {
      var method = Handlebars.logger.methodMap[level];
      if (typeof console !== 'undefined' && console[method]) {
        console[method].call(console, obj);
      }
    }
  }
};

Handlebars.log = function(level, obj) { Handlebars.logger.log(level, obj); };

Handlebars.registerHelper('each', function(context, options) {
  var fn = options.fn, inverse = options.inverse;
  var i = 0, ret = "", data;

  var type = toString.call(context);
  if(type === functionType) { context = context.call(this); }

  if (options.data) {
    data = Handlebars.createFrame(options.data);
  }

  if(context && typeof context === 'object') {
    if(context instanceof Array){
      for(var j = context.length; i<j; i++) {
        if (data) { data.index = i; }
        ret = ret + fn(context[i], { data: data });
      }
    } else {
      for(var key in context) {
        if(context.hasOwnProperty(key)) {
          if(data) { data.key = key; }
          ret = ret + fn(context[key], {data: data});
          i++;
        }
      }
    }
  }

  if(i === 0){
    ret = inverse(this);
  }

  return ret;
});

Handlebars.registerHelper('if', function(conditional, options) {
  var type = toString.call(conditional);
  if(type === functionType) { conditional = conditional.call(this); }

  if(!conditional || Handlebars.Utils.isEmpty(conditional)) {
    return options.inverse(this);
  } else {
    return options.fn(this);
  }
});

Handlebars.registerHelper('unless', function(conditional, options) {
  return Handlebars.helpers['if'].call(this, conditional, {fn: options.inverse, inverse: options.fn});
});

Handlebars.registerHelper('with', function(context, options) {
  var type = toString.call(context);
  if(type === functionType) { context = context.call(this); }

  if (!Handlebars.Utils.isEmpty(context)) return options.fn(context);
});

Handlebars.registerHelper('log', function(context, options) {
  var level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1;
  Handlebars.log(level, context);
});
;
// lib/handlebars/utils.js

var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];

Handlebars.Exception = function(message) {
  var tmp = Error.prototype.constructor.apply(this, arguments);

  // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
  for (var idx = 0; idx < errorProps.length; idx++) {
    this[errorProps[idx]] = tmp[errorProps[idx]];
  }
};
Handlebars.Exception.prototype = new Error();

// Build out our basic SafeString type
Handlebars.SafeString = function(string) {
  this.string = string;
};
Handlebars.SafeString.prototype.toString = function() {
  return this.string.toString();
};

var escape = {
  "&": "&amp;",
  "<": "&lt;",
  ">": "&gt;",
  '"': "&quot;",
  "'": "&#x27;",
  "`": "&#x60;"
};

var badChars = /[&<>"'`]/g;
var possible = /[&<>"'`]/;

var escapeChar = function(chr) {
  return escape[chr] || "&amp;";
};

Handlebars.Utils = {
  extend: function(obj, value) {
    for(var key in value) {
      if(value.hasOwnProperty(key)) {
        obj[key] = value[key];
      }
    }
  },

  escapeExpression: function(string) {
    // don't escape SafeStrings, since they're already safe
    if (string instanceof Handlebars.SafeString) {
      return string.toString();
    } else if (string == null || string === false) {
      return "";
    }

    // Force a string conversion as this will be done by the append regardless and
    // the regex test will do this transparently behind the scenes, causing issues if
    // an object's to string has escaped characters in it.
    string = string.toString();

    if(!possible.test(string)) { return string; }
    return string.replace(badChars, escapeChar);
  },

  isEmpty: function(value) {
    if (!value && value !== 0) {
      return true;
    } else if(toString.call(value) === "[object Array]" && value.length === 0) {
      return true;
    } else {
      return false;
    }
  }
};
;
// lib/handlebars/runtime.js

Handlebars.VM = {
  template: function(templateSpec) {
    // Just add water
    var container = {
      escapeExpression: Handlebars.Utils.escapeExpression,
      invokePartial: Handlebars.VM.invokePartial,
      programs: [],
      program: function(i, fn, data) {
        var programWrapper = this.programs[i];
        if(data) {
          programWrapper = Handlebars.VM.program(i, fn, data);
        } else if (!programWrapper) {
          programWrapper = this.programs[i] = Handlebars.VM.program(i, fn);
        }
        return programWrapper;
      },
      merge: function(param, common) {
        var ret = param || common;

        if (param && common) {
          ret = {};
          Handlebars.Utils.extend(ret, common);
          Handlebars.Utils.extend(ret, param);
        }
        return ret;
      },
      programWithDepth: Handlebars.VM.programWithDepth,
      noop: Handlebars.VM.noop,
      compilerInfo: null
    };

    return function(context, options) {
      options = options || {};
      var result = templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data);

      var compilerInfo = container.compilerInfo || [],
          compilerRevision = compilerInfo[0] || 1,
          currentRevision = Handlebars.COMPILER_REVISION;

      if (compilerRevision !== currentRevision) {
        if (compilerRevision < currentRevision) {
          var runtimeVersions = Handlebars.REVISION_CHANGES[currentRevision],
              compilerVersions = Handlebars.REVISION_CHANGES[compilerRevision];
          throw "Template was precompiled with an older version of Handlebars than the current runtime. "+
                "Please update your precompiler to a newer version ("+runtimeVersions+") or downgrade your runtime to an older version ("+compilerVersions+").";
        } else {
          // Use the embedded version info since the runtime doesn't know about this revision yet
          throw "Template was precompiled with a newer version of Handlebars than the current runtime. "+
                "Please update your runtime to a newer version ("+compilerInfo[1]+").";
        }
      }

      return result;
    };
  },

  programWithDepth: function(i, fn, data /*, $depth */) {
    var args = Array.prototype.slice.call(arguments, 3);

    var program = function(context, options) {
      options = options || {};

      return fn.apply(this, [context, options.data || data].concat(args));
    };
    program.program = i;
    program.depth = args.length;
    return program;
  },
  program: function(i, fn, data) {
    var program = function(context, options) {
      options = options || {};

      return fn(context, options.data || data);
    };
    program.program = i;
    program.depth = 0;
    return program;
  },
  noop: function() { return ""; },
  invokePartial: function(partial, name, context, helpers, partials, data) {
    var options = { helpers: helpers, partials: partials, data: data };

    if(partial === undefined) {
      throw new Handlebars.Exception("The partial " + name + " could not be found");
    } else if(partial instanceof Function) {
      return partial(context, options);
    } else if (!Handlebars.compile) {
      throw new Handlebars.Exception("The partial " + name + " could not be compiled when running in runtime-only mode");
    } else {
      partials[name] = Handlebars.compile(partial, {data: data !== undefined});
      return partials[name](context, options);
    }
  }
};

Handlebars.template = Handlebars.VM.template;
;
// lib/handlebars/browser-suffix.js
})(Handlebars);
;


================================================
FILE: public/images/emoji/emojify.css
================================================
.emojify{width:1.5em;height:1.5em;display:inline-block;margin-bottom:-0.25em}.emojify.alien{background:url(alien.png) no-repeat;background-size:1.5em}.emojify.angel{background:url(angel.png) no-repeat;background-size:1.5em}.emojify.anger{background:url(anger.png) no-repeat;background-size:1.5em}.emojify.angry{background:url(angry.png) no-repeat;background-size:1.5em}.emojify.anguished{background:url(anguished.png) no-repeat;background-size:1.5em}.emojify.astonished{background:url(astonished.png) no-repeat;background-size:1.5em}.emojify.baby{background:url(baby.png) no-repeat;background-size:1.5em}.emojify.blue_heart{background:url(blue_heart.png) no-repeat;background-size:1.5em}.emojify.blush{background:url(blush.png) no-repeat;background-size:1.5em}.emojify.boom{background:url(boom.png) no-repeat;background-size:1.5em}.emojify.bow{background:url(bow.png) no-repeat;background-size:1.5em}.emojify.bowtie{background:url(bowtie.png) no-repeat;background-size:1.5em}.emojify.boy{background:url(boy.png) no-repeat;background-size:1.5em}.emojify.bride_with_veil{background:url(bride_with_veil.png) no-repeat;background-size:1.5em}.emojify.broken_heart{background:url(broken_heart.png) no-repeat;background-size:1.5em}.emojify.bust_in_silhouette{background:url(bust_in_silhouette.png) no-repeat;background-size:1.5em}.emojify.busts_in_silhouette{background:url(busts_in_silhouette.png) no-repeat;background-size:1.5em}.emojify.clap{background:url(clap.png) no-repeat;background-size:1.5em}.emojify.cold_sweat{background:url(cold_sweat.png) no-repeat;background-size:1.5em}.emojify.collision{background:url(collision.png) no-repeat;background-size:1.5em}.emojify.confounded{background:url(confounded.png) no-repeat;background-size:1.5em}.emojify.confused{background:url(confused.png) no-repeat;background-size:1.5em}.emojify.construction_worker{background:url(construction_worker.png) no-repeat;background-size:1.5em}.emojify.cop{background:url(cop.png) no-repeat;background-size:1.5em}.emojify.couple_with_heart{background:url(couple_with_heart.png) no-repeat;background-size:1.5em}.emojify.couple{background:url(couple.png) no-repeat;background-size:1.5em}.emojify.couplekiss{background:url(couplekiss.png) no-repeat;background-size:1.5em}.emojify.cry{background:url(cry.png) no-repeat;background-size:1.5em}.emojify.crying_cat_face{background:url(crying_cat_face.png) no-repeat;background-size:1.5em}.emojify.cupid{background:url(cupid.png) no-repeat;background-size:1.5em}.emojify.dancer{background:url(dancer.png) no-repeat;background-size:1.5em}.emojify.dancers{background:url(dancers.png) no-repeat;background-size:1.5em}.emojify.dash{background:url(dash.png) no-repeat;background-size:1.5em}.emojify.disappointed{background:url(disappointed.png) no-repeat;background-size:1.5em}.emojify.dizzy_face{background:url(dizzy_face.png) no-repeat;background-size:1.5em}.emojify.dizzy{background:url(dizzy.png) no-repeat;background-size:1.5em}.emojify.droplet{background:url(droplet.png) no-repeat;background-size:1.5em}.emojify.ear{background:url(ear.png) no-repeat;background-size:1.5em}.emojify.exclamation{background:url(exclamation.png) no-repeat;background-size:1.5em}.emojify.expressionless{background:url(expressionless.png) no-repeat;background-size:1.5em}.emojify.eyes{background:url(eyes.png) no-repeat;background-size:1.5em}.emojify.facepunch{background:url(facepunch.png) no-repeat;background-size:1.5em}.emojify.family{background:url(family.png) no-repeat;background-size:1.5em}.emojify.fearful{background:url(fearful.png) no-repeat;background-size:1.5em}.emojify.feelsgood{background:url(feelsgood.png) no-repeat;background-size:1.5em}.emojify.feet{background:url(feet.png) no-repeat;background-size:1.5em}.emojify.finnadie{background:url(finnadie.png) no-repeat;background-size:1.5em}.emojify.fire{background:url(fire.png) no-repeat;background-size:1.5em}.emojify.fist{background:url(fist.png) no-repeat;background-size:1.5em}.emojify.flushed{background:url(flushed.png) no-repeat;background-size:1.5em}.emojify.frowning{background:url(frowning.png) no-repeat;background-size:1.5em}.emojify.girl{background:url(girl.png) no-repeat;background-size:1.5em}.emojify.goberserk{background:url(goberserk.png) no-repeat;background-size:1.5em}.emojify.godmode{background:url(godmode.png) no-repeat;background-size:1.5em}.emojify.green_heart{background:url(green_heart.png) no-repeat;background-size:1.5em}.emojify.grey_exclamation{background:url(grey_exclamation.png) no-repeat;background-size:1.5em}.emojify.grey_question{background:url(grey_question.png) no-repeat;background-size:1.5em}.emojify.grimacing{background:url(grimacing.png) no-repeat;background-size:1.5em}.emojify.grin{background:url(grin.png) no-repeat;background-size:1.5em}.emojify.grinning{background:url(grinning.png) no-repeat;background-size:1.5em}.emojify.guardsman{background:url(guardsman.png) no-repeat;background-size:1.5em}.emojify.haircut{background:url(haircut.png) no-repeat;background-size:1.5em}.emojify.hand{background:url(hand.png) no-repeat;background-size:1.5em}.emojify.hankey{background:url(hankey.png) no-repeat;background-size:1.5em}.emojify.hear_no_evil{background:url(hear_no_evil.png) no-repeat;background-size:1.5em}.emojify.heart_eyes_cat{background:url(heart_eyes_cat.png) no-repeat;background-size:1.5em}.emojify.heart_eyes{background:url(heart_eyes.png) no-repeat;background-size:1.5em}.emojify.heart{background:url(heart.png) no-repeat;background-size:1.5em}.emojify.heartbeat{background:url(heartbeat.png) no-repeat;background-size:1.5em}.emojify.heartpulse{background:url(heartpulse.png) no-repeat;background-size:1.5em}.emojify.hurtrealbad{background:url(hurtrealbad.png) no-repeat;background-size:1.5em}.emojify.hushed{background:url(hushed.png) no-repeat;background-size:1.5em}.emojify.imp{background:url(imp.png) no-repeat;background-size:1.5em}.emojify.information_desk_person{background:url(information_desk_person.png) no-repeat;background-size:1.5em}.emojify.innocent{background:url(innocent.png) no-repeat;background-size:1.5em}.emojify.japanese_goblin{background:url(japanese_goblin.png) no-repeat;background-size:1.5em}.emojify.japanese_ogre{background:url(japanese_ogre.png) no-repeat;background-size:1.5em}.emojify.joy_cat{background:url(joy_cat.png) no-repeat;background-size:1.5em}.emojify.joy{background:url(joy.png) no-repeat;background-size:1.5em}.emojify.kiss{background:url(kiss.png) no-repeat;background-size:1.5em}.emojify.kissing_cat{background:url(kissing_cat.png) no-repeat;background-size:1.5em}.emojify.kissing_closed_eyes{background:url(kissing_closed_eyes.png) no-repeat;background-size:1.5em}.emojify.kissing_heart{background:url(kissing_heart.png) no-repeat;background-size:1.5em}.emojify.kissing_smiling_eyes{background:url(kissing_smiling_eyes.png) no-repeat;background-size:1.5em}.emojify.kissing{background:url(kissing.png) no-repeat;background-size:1.5em}.emojify.laughing{background:url(laughing.png) no-repeat;background-size:1.5em}.emojify.lips{background:url(lips.png) no-repeat;background-size:1.5em}.emojify.love_letter{background:url(love_letter.png) no-repeat;background-size:1.5em}.emojify.man_with_gua_pi_mao{background:url(man_with_gua_pi_mao.png) no-repeat;background-size:1.5em}.emojify.man_with_turban{background:url(man_with_turban.png) no-repeat;background-size:1.5em}.emojify.man{background:url(man.png) no-repeat;background-size:1.5em}.emojify.mask{background:url(mask.png) no-repeat;background-size:1.5em}.emojify.massage{background:url(massage.png) no-repeat;background-size:1.5em}.emojify.metal{background:url(metal.png) no-repeat;background-size:1.5em}.emojify.muscle{background:url(muscle.png) no-repeat;background-size:1.5em}.emojify.musical_note{background:url(musical_note.png) no-repeat;background-size:1.5em}.emojify.nail_care{background:url(nail_care.png) no-repeat;background-size:1.5em}.emojify.neckbeard{background:url(neckbeard.png) no-repeat;background-size:1.5em}.emojify.neutral_face{background:url(neutral_face.png) no-repeat;background-size:1.5em}.emojify.no_good{background:url(no_good.png) no-repeat;background-size:1.5em}.emojify.no_mouth{background:url(no_mouth.png) no-repeat;background-size:1.5em}.emojify.nose{background:url(nose.png) no-repeat;background-size:1.5em}.emojify.notes{background:url(notes.png) no-repeat;background-size:1.5em}.emojify.ok_hand{background:url(ok_hand.png) no-repeat;background-size:1.5em}.emojify.ok_woman{background:url(ok_woman.png) no-repeat;background-size:1.5em}.emojify.older_man{background:url(older_man.png) no-repeat;background-size:1.5em}.emojify.older_woman{background:url(older_woman.png) no-repeat;background-size:1.5em}.emojify.open_hands{background:url(open_hands.png) no-repeat;background-size:1.5em}.emojify.open_mouth{background:url(open_mouth.png) no-repeat;background-size:1.5em}.emojify.pensive{background:url(pensive.png) no-repeat;background-size:1.5em}.emojify.persevere{background:url(persevere.png) no-repeat;background-size:1.5em}.emojify.person_frowning{background:url(person_frowning.png) no-repeat;background-size:1.5em}.emojify.person_with_blond_hair{background:url(person_with_blond_hair.png) no-repeat;background-size:1.5em}.emojify.person_with_pouting_face{background:url(person_with_pouting_face.png) no-repeat;background-size:1.5em}.emojify.point_down{background:url(point_down.png) no-repeat;background-size:1.5em}.emojify.point_left{background:url(point_left.png) no-repeat;background-size:1.5em}.emojify.point_right{background:url(point_right.png) no-repeat;background-size:1.5em}.emojify.point_up_2{background:url(point_up_2.png) no-repeat;background-size:1.5em}.emojify.point_up{background:url(point_up.png) no-repeat;background-size:1.5em}.emojify.poop{background:url(poop.png) no-repeat;background-size:1.5em}.emojify.pouting_cat{background:url(pouting_cat.png) no-repeat;background-size:1.5em}.emojify.pray{background:url(pray.png) no-repeat;background-size:1.5em}.emojify.princess{background:url(princess.png) no-repeat;background-size:1.5em}.emojify.punch{background:url(punch.png) no-repeat;background-size:1.5em}.emojify.purple_heart{background:url(purple_heart.png) no-repeat;background-size:1.5em}.emojify.question{background:url(question.png) no-repeat;background-size:1.5em}.emojify.rage{background:url(rage.png) no-repeat;background-size:1.5em}.emojify.rage1{background:url(rage1.png) no-repeat;background-size:1.5em}.emojify.rage2{background:url(rage2.png) no-repeat;background-size:1.5em}.emojify.rage3{background:url(rage3.png) no-repeat;background-size:1.5em}.emojify.rage4{background:url(rage4.png) no-repeat;background-size:1.5em}.emojify.raised_hand{background:url(raised_hand.png) no-repeat;background-size:1.5em}.emojify.raised_hands{background:url(raised_hands.png) no-repeat;background-size:1.5em}.emojify.relaxed{background:url(relaxed.png) no-repeat;background-size:1.5em}.emojify.relieved{background:url(relieved.png) no-repeat;background-size:1.5em}.emojify.revolving_hearts{background:url(revolving_hearts.png) no-repeat;background-size:1.5em}.emojify.runner{background:url(runner.png) no-repeat;background-size:1.5em}.emojify.running{background:url(running.png) no-repeat;background-size:1.5em}.emojify.satisfied{background:url(satisfied.png) no-repeat;background-size:1.5em}.emojify.scream_cat{background:url(scream_cat.png) no-repeat;background-size:1.5em}.emojify.scream{background:url(scream.png) no-repeat;background-size:1.5em}.emojify.see_no_evil{background:url(see_no_evil.png) no-repeat;background-size:1.5em}.emojify.shit{background:url(shit.png) no-repeat;background-size:1.5em}.emojify.skull{background:url(skull.png) no-repeat;background-size:1.5em}.emojify.sleeping{background:url(sleeping.png) no-repeat;background-size:1.5em}.emojify.sleepy{background:url(sleepy.png) no-repeat;background-size:1.5em}.emojify.smile_cat{background:url(smile_cat.png) no-repeat;background-size:1.5em}.emojify.smile{background:url(smile.png) no-repeat;background-size:1.5em}.emojify.smiley_cat{background:url(smiley_cat.png) no-repeat;background-size:1.5em}.emojify.smiley{background:url(smiley.png) no-repeat;background-size:1.5em}.emojify.smiling_imp{background:url(smiling_imp.png) no-repeat;background-size:1.5em}.emojify.smirk_cat{background:url(smirk_cat.png) no-repeat;background-size:1.5em}.emojify.smirk{background:url(smirk.png) no-repeat;background-size:1.5em}.emojify.sob{background:url(sob.png) no-repeat;background-size:1.5em}.emojify.sparkling_heart{background:url(sparkling_heart.png) no-repeat;background-size:1.5em}.emojify.sparkles{background:url(sparkles.png) no-repeat;background-size:1.5em}.emojify.speak_no_evil{background:url(speak_no_evil.png) no-repeat;background-size:1.5em}.emojify.speech_balloon{background:url(speech_balloon.png) no-repeat;background-size:1.5em}.emojify.star{background:url(star.png) no-repeat;background-size:1.5em}.emojify.star2{background:url(star2.png) no-repeat;background-size:1.5em}.emojify.stuck_out_tongue_closed_eyes{background:url(stuck_out_tongue_closed_eyes.png) no-repeat;background-size:1.5em}.emojify.stuck_out_tongue_winking_eye{background:url(stuck_out_tongue_winking_eye.png) no-repeat;background-size:1.5em}.emojify.stuck_out_tongue{background:url(stuck_out_tongue.png) no-repeat;background-size:1.5em}.emojify.sunglasses{background:url(sunglasses.png) no-repeat;background-size:1.5em}.emojify.suspect{background:url(suspect.png) no-repeat;background-size:1.5em}.emojify.sweat_drops{background:url(sweat_drops.png) no-repeat;background-size:1.5em}.emojify.sweat_smile{background:url(sweat_smile.png) no-repeat;background-size:1.5em}.emojify.sweat{background:url(sweat.png) no-repeat;background-size:1.5em}.emojify.thought_balloon{background:url(thought_balloon.png) no-repeat;background-size:1.5em}.emojify.thumbsdown{background:url(thumbsdown.png) no-repeat;background-size:1.5em}.emojify.thumbsup{background:url(thumbsup.png) no-repeat;background-size:1.5em}.emojify.tired_face{background:url(tired_face.png) no-repeat;background-size:1.5em}.emojify.tongue{background:url(tongue.png) no-repeat;background-size:1.5em}.emojify.triumph{background:url(triumph.png) no-repeat;background-size:1.5em}.emojify.trollface{background:url(trollface.png) no-repeat;background-size:1.5em}.emojify.two_hearts{background:url(two_hearts.png) no-repeat;background-size:1.5em}.emojify.two_men_holding_hands{background:url(two_men_holding_hands.png) no-repeat;background-size:1.5em}.emojify.two_women_holding_hands{background:url(two_women_holding_hands.png) no-repeat;background-size:1.5em}.emojify.unamused{background:url(unamused.png) no-repeat;background-size:1.5em}.emojify.v{background:url(v.png) no-repeat;background-size:1.5em}.emojify.walking{background:url(walking.png) no-repeat;background-size:1.5em}.emojify.wave{background:url(wave.png) no-repeat;background-size:1.5em}.emojify.weary{background:url(weary.png) no-repeat;background-size:1.5em}.emojify.wink2{background:url(wink2.png) no-repeat;background-size:1.5em}.emojify.wink{background:url(wink.png) no-repeat;background-size:1.5em}.emojify.woman{background:url(woman.png) no-repeat;background-size:1.5em}.emojify.worried{background:url(worried.png) no-repeat;background-size:1.5em}.emojify.yellow_heart{background:url(yellow_heart.png) no-repeat;background-size:1.5em}.emojify.yum{background:url(yum.png) no-repeat;background-size:1.5em}.emojify.zzz{background:url(zzz.png) no-repeat;background-size:1.5em}.emojify.sunny{background:url(sunny.png) no-repeat;background-size:1.5em}.emojify.umbrella{background:url(umbrella.png) no-repeat;background-size:1.5em}.emojify.cloud{background:url(cloud.png) no-repeat;background-size:1.5em}.emojify.snowflake{background:url(snowflake.png) no-repeat;background-size:1.5em}.emojify.snowman{background:url(snowman.png) no-repeat;background-size:1.5em}.emojify.zap{background:url(zap.png) no-repeat;background-size:1.5em}.emojify.cyclone{background:url(cyclone.png) no-repeat;background-size:1.5em}.emojify.foggy{background:url(foggy.png) no-repeat;background-size:1.5em}.emojify.ocean{background:url(ocean.png) no-repeat;background-size:1.5em}.emojify.cat{background:url(cat.png) no-repeat;background-size:1.5em}.emojify.dog{background:url(dog.png) no-repeat;background-size:1.5em}.emojify.mouse{background:url(mouse.png) no-repeat;background-size:1.5em}.emojify.hamster{background:url(hamster.png) no-repeat;background-size:1.5em}.emojify.rabbit{background:url(rabbit.png) no-repeat;background-size:1.5em}.emojify.wolf{background:url(wolf.png) no-repeat;background-size:1.5em}.emojify.frog{background:url(frog.png) no-repeat;background-size:1.5em}.emojify.tiger{background:url(tiger.png) no-repeat;background-size:1.5em}.emojify.koala{background:url(koala.png) no-repeat;background-size:1.5em}.emojify.bear{background:url(bear.png) no-repeat;background-size:1.5em}.emojify.pig{background:url(pig.png) no-repeat;background-size:1.5em}.emojify.pig_nose{background:url(pig_nose.png) no-repeat;background-size:1.5em}.emojify.cow{background:url(cow.png) no-repeat;background-size:1.5em}.emojify.boar{background:url(boar.png) no-repeat;background-size:1.5em}.emojify.monkey_face{background:url(monkey_face.png) no-repeat;background-size:1.5em}.emojify.monkey{background:url(monkey.png) no-repeat;background-size:1.5em}.emojify.horse{background:url(horse.png) no-repeat;background-size:1.5em}.emojify.racehorse{background:url(racehorse.png) no-repeat;background-size:1.5em}.emojify.camel{background:url(camel.png) no-repeat;background-size:1.5em}.emojify.sheep{background:url(sheep.png) no-repeat;background-size:1.5em}.emojify.elephant{background:url(elephant.png) no-repeat;background-size:1.5em}.emojify.panda_face{background:url(panda_face.png) no-repeat;background-size:1.5em}.emojify.snake{background:url(snake.png) no-repeat;background-size:1.5em}.emojify.bird{background:url(bird.png) no-repeat;background-size:1.5em}.emojify.baby_chick{background:url(baby_chick.png) no-repeat;background-size:1.5em}.emojify.hatched_chick{background:url(hatched_chick.png) no-repeat;background-size:1.5em}.emojify.hatching_chick{background:url(hatching_chick.png) no-repeat;background-size:1.5em}.emojify.chicken{background:url(chicken.png) no-repeat;background-size:1.5em}.emojify.penguin{background:url(penguin.png) no-repeat;background-size:1.5em}.emojify.turtle{background:url(turtle.png) no-repeat;background-size:1.5em}.emojify.bug{background:url(bug.png) no-repeat;background-size:1.5em}.emojify.honeybee{background:url(honeybee.png) no-repeat;background-size:1.5em}.emojify.ant{background:url(ant.png) no-repeat;background-size:1.5em}.emojify.beetle{background:url(beetle.png) no-repeat;background-size:1.5em}.emojify.snail{background:url(snail.png) no-repeat;background-size:1.5em}.emojify.octopus{background:url(octopus.png) no-repeat;background-size:1.5em}.emojify.tropical_fish{background:url(tropical_fish.png) no-repeat;background-size:1.5em}.emojify.fish{background:url(fish.png) no-repeat;background-size:1.5em}.emojify.whale{background:url(whale.png) no-repeat;background-size:1.5em}.emojify.whale2{background:url(whale2.png) no-repeat;background-size:1.5em}.emojify.dolphin{background:url(dolphin.png) no-repeat;background-size:1.5em}.emojify.cow2{background:url(cow2.png) no-repeat;background-size:1.5em}.emojify.ram{background:url(ram.png) no-repeat;background-size:1.5em}.emojify.rat{background:url(rat.png) no-repeat;background-size:1.5em}.emojify.water_buffalo{background:url(water_buffalo.png) no-repeat;background-size:1.5em}.emojify.tiger2{background:url(tiger2.png) no-repeat;background-size:1.5em}.emojify.rabbit2{background:url(rabbit2.png) no-repeat;background-size:1.5em}.emojify.dragon{background:url(dragon.png) no-repeat;background-size:1.5em}.emojify.goat{background:url(goat.png) no-repeat;background-size:1.5em}.emojify.rooster{background:url(rooster.png) no-repeat;background-size:1.5em}.emojify.dog2{background:url(dog2.png) no-repeat;background-size:1.5em}.emojify.pig2{background:url(pig2.png) no-repeat;background-size:1.5em}.emojify.mouse2{background:url(mouse2.png) no-repeat;background-size:1.5em}.emojify.ox{background:url(ox.png) no-repeat;background-size:1.5em}.emojify.dragon_face{background:url(dragon_face.png) no-repeat;background-size:1.5em}.emojify.blowfish{background:url(blowfish.png) no-repeat;background-size:1.5em}.emojify.crocodile{background:url(crocodile.png) no-repeat;background-size:1.5em}.emojify.dromedary_camel{background:url(dromedary_camel.png) no-repeat;background-size:1.5em}.emojify.leopard{background:url(leopard.png) no-repeat;background-size:1.5em}.emojify.cat2{background:url(cat2.png) no-repeat;background-size:1.5em}.emojify.poodle{background:url(poodle.png) no-repeat;background-size:1.5em}.emojify.paw_prints{background:url(paw_prints.png) no-repeat;background-size:1.5em}.emojify.bouquet{background:url(bouquet.png) no-repeat;background-size:1.5em}.emojify.cherry_blossom{background:url(cherry_blossom.png) no-repeat;background-size:1.5em}.emojify.tulip{background:url(tulip.png) no-repeat;background-size:1.5em}.emojify.four_leaf_clover{background:url(four_leaf_clover.png) no-repeat;background-size:1.5em}.emojify.rose{background:url(rose.png) no-repeat;background-size:1.5em}.emojify.sunflower{background:url(sunflower.png) no-repeat;background-size:1.5em}.emojify.hibiscus{background:url(hibiscus.png) no-repeat;background-size:1.5em}.emojify.maple_leaf{background:url(maple_leaf.png) no-repeat;background-size:1.5em}.emojify.leaves{background:url(leaves.png) no-repeat;background-size:1.5em}.emojify.fallen_leaf{background:url(fallen_leaf.png) no-repeat;background-size:1.5em}.emojify.herb{background:url(herb.png) no-repeat;background-size:1.5em}.emojify.mushroom{background:url(mushroom.png) no-repeat;background-size:1.5em}.emojify.cactus{background:url(cactus.png) no-repeat;background-size:1.5em}.emojify.palm_tree{background:url(palm_tree.png) no-repeat;background-size:1.5em}.emojify.evergreen_tree{background:url(evergreen_tree.png) no-repeat;background-size:1.5em}.emojify.deciduous_tree{background:url(deciduous_tree.png) no-repeat;background-size:1.5em}.emojify.chestnut{background:url(chestnut.png) no-repeat;background-size:1.5em}.emojify.seedling{background:url(seedling.png) no-repeat;background-size:1.5em}.emojify.blossom{background:url(blossom.png) no-repeat;background-size:1.5em}.emojify.ear_of_rice{background:url(ear_of_rice.png) no-repeat;background-size:1.5em}.emojify.shell{background:url(shell.png) no-repeat;background-size:1.5em}.emojify.globe_with_meridians{background:url(globe_with_meridians.png) no-repeat;background-size:1.5em}.emojify.sun_with_face{background:url(sun_with_face.png) no-repeat;background-size:1.5em}.emojify.full_moon_with_face{background:url(full_moon_with_face.png) no-repeat;background-size:1.5em}.emojify.new_moon_with_face{background:url(new_moon_with_face.png) no-repeat;background-size:1.5em}.emojify.new_moon{background:url(new_moon.png) no-repeat;background-size:1.5em}.emojify.waxing_crescent_moon{background:url(waxing_crescent_moon.png) no-repeat;background-size:1.5em}.emojify.first_quarter_moon{background:url(first_quarter_moon.png) no-repeat;background-size:1.5em}.emojify.waxing_gibbous_moon{background:url(waxing_gibbous_moon.png) no-repeat;background-size:1.5em}.emojify.full_moon{background:url(full_moon.png) no-repeat;background-size:1.5em}.emojify.waning_gibbous_moon{background:url(waning_gibbous_moon.png) no-repeat;background-size:1.5em}.emojify.last_quarter_moon{background:url(last_quarter_moon.png) no-repeat;background-size:1.5em}.emojify.waning_crescent_moon{background:url(waning_crescent_moon.png) no-repeat;background-size:1.5em}.emojify.last_quarter_moon_with_face{background:url(last_quarter_moon_with_face.png) no-repeat;background-size:1.5em}.emojify.first_quarter_moon_with_face{background:url(first_quarter_moon_with_face.png) no-repeat;background-size:1.5em}.emojify.moon{background:url(moon.png) no-repeat;background-size:1.5em}.emojify.earth_africa{background:url(earth_africa.png) no-repeat;background-size:1.5em}.emojify.earth_americas{background:url(earth_americas.png) no-repeat;background-size:1.5em}.emojify.earth_asia{background:url(earth_asia.png) no-repeat;background-size:1.5em}.emojify.volcano{background:url(volcano.png) no-repeat;background-size:1.5em}.emojify.milky_way{background:url(milky_way.png) no-repeat;background-size:1.5em}.emojify.partly_sunny{background:url(partly_sunny.png) no-repeat;background-size:1.5em}.emojify.octocat{background:url(octocat.png) no-repeat;background-size:1.5em}.emojify.squirrel{background:url(squirrel.png) no-repeat;background-size:1.5em}.emojify.bamboo{background:url(bamboo.png) no-repeat;background-size:1.5em}.emojify.gift_heart{background:url(gift_heart.png) no-repeat;background-size:1.5em}.emojify.dolls{background:url(dolls.png) no-repeat;background-size:1.5em}.emojify.school_satchel{background:url(school_satchel.png) no-repeat;background-size:1.5em}.emojify.mortar_board{background:url(mortar_board.png) no-repeat;background-size:1.5em}.emojify.flags{background:url(flags.png) no-repeat;background-size:1.5em}.emojify.fireworks{background:url(fireworks.png) no-repeat;background-size:1.5em}.emojify.sparkler{background:url(sparkler.png) no-repeat;background-size:1.5em}.emojify.wind_chime{background:url(wind_chime.png) no-repeat;background-size:1.5em}.emojify.rice_scene{background:url(rice_scene.png) no-repeat;background-size:1.5em}.emojify.jack_o_lantern{background:url(jack_o_lantern.png) no-repeat;background-size:1.5em}.emojify.ghost{background:url(ghost.png) no-repeat;background-size:1.5em}.emojify.santa{background:url(santa.png) no-repeat;background-size:1.5em}.emojify.christmas_tree{background:url(christmas_tree.png) no-repeat;background-size:1.5em}.emojify.gift{background:url(gift.png) no-repeat;background-size:1.5em}.emojify.bell{background:url(bell.png) no-repeat;background-size:1.5em}.emojify.no_bell{background:url(no_bell.png) no-repeat;background-size:1.5em}.emojify.tanabata_tree{background:url(tanabata_tree.png) no-repeat;background-size:1.5em}.emojify.tada{background:url(tada.png) no-repeat;background-size:1.5em}.emojify.confetti_ball{background:url(confetti_ball.png) no-repeat;background-size:1.5em}.emojify.balloon{background:url(balloon.png) no-repeat;background-size:1.5em}.emojify.crystal_ball{background:url(crystal_ball.png) no-repeat;background-size:1.5em}.emojify.cd{background:url(cd.png) no-repeat;background-size:1.5em}.emojify.dvd{background:url(dvd.png) no-repeat;background-size:1.5em}.emojify.floppy_disk{background:url(floppy_disk.png) no-repeat;background-size:1.5em}.emojify.camera{background:url(camera.png) no-repeat;background-size:1.5em}.emojify.video_camera{background:url(video_camera.png) no-repeat;background-size:1.5em}.emojify.movie_camera{background:url(movie_camera.png) no-repeat;background-size:1.5em}.emojify.computer{background:url(computer.png) no-repeat;background-size:1.5em}.emojify.tv{background:url(tv.png) no-repeat;background-size:1.5em}.emojify.iphone{background:url(iphone.png) no-repeat;background-size:1.5em}.emojify.phone{background:url(phone.png) no-repeat;background-size:1.5em}.emojify.telephone{background:url(telephone.png) no-repeat;background-size:1.5em}.emojify.telephone_receiver{background:url(telephone_receiver.png) no-repeat;background-size:1.5em}.emojify.pager{background:url(pager.png) no-repeat;background-size:1.5em}.emojify.fax{background:url(fax.png) no-repeat;background-size:1.5em}.emojify.minidisc{background:url(minidisc.png) no-repeat;background-size:1.5em}.emojify.vhs{background:url(vhs.png) no-repeat;background-size:1.5em}.emojify.sound{background:url(sound.png) no-repeat;background-size:1.5em}.emojify.speaker{background:url(speaker.png) no-repeat;background-size:1.5em}.emojify.mute{background:url(mute.png) no-repeat;background-size:1.5em}.emojify.loudspeaker{background:url(loudspeaker.png) no-repeat;background-size:1.5em}.emojify.mega{background:url(mega.png) no-repeat;background-size:1.5em}.emojify.hourglass{background:url(hourglass.png) no-repeat;background-size:1.5em}.emojify.hourglass_flowing_sand{background:url(hourglass_flowing_sand.png) no-repeat;background-size:1.5em}.emojify.alarm_clock{background:url(alarm_clock.png) no-repeat;background-size:1.5em}.emojify.watch{background:url(watch.png) no-repeat;background-size:1.5em}.emojify.radio{background:url(radio.png) no-repeat;background-size:1.5em}.emojify.satellite{background:url(satellite.png) no-repeat;background-size:1.5em}.emojify.loop{background:url(loop.png) no-repeat;background-size:1.5em}.emojify.mag{background:url(mag.png) no-repeat;background-size:1.5em}.emojify.mag_right{background:url(mag_right.png) no-repeat;background-size:1.5em}.emojify.unlock{background:url(unlock.png) no-repeat;background-size:1.5em}.emojify.lock{background:url(lock.png) no-repeat;background-size:1.5em}.emojify.lock_with_ink_pen{background:url(lock_with_ink_pen.png) no-repeat;background-size:1.5em}.emojify.closed_lock_with_key{background:url(closed_lock_with_key.png) no-repeat;background-size:1.5em}.emojify.key{background:url(key.png) no-repeat;background-size:1.5em}.emojify.bulb{background:url(bulb.png) no-repeat;background-size:1.5em}.emojify.flashlight{background:url(flashlight.png) no-repeat;background-size:1.5em}.emojify.high_brightness{background:url(high_brightness.png) no-repeat;background-size:1.5em}.emojify.low_brightness{background:url(low_brightness.png) no-repeat;background-size:1.5em}.emojify.electric_plug{background:url(electric_plug.png) no-repeat;background-size:1.5em}.emojify.battery{background:url(battery.png) no-repeat;background-size:1.5em}.emojify.calling{background:url(calling.png) no-repeat;background-size:1.5em}.emojify.email{background:url(email.png) no-repeat;background-size:1.5em}.emojify.mailbox{background:url(mailbox.png) no-repeat;background-size:1.5em}.emojify.postbox{background:url(postbox.png) no-repeat;background-size:1.5em}.emojify.bath{background:url(bath.png) no-repeat;background-size:1.5em}.emojify.bathtub{background:url(bathtub.png) no-repeat;background-size:1.5em}.emojify.shower{background:url(shower.png) no-repeat;background-size:1.5em}.emojify.toilet{background:url(toilet.png) no-repeat;background-size:1.5em}.emojify.wrench{background:url(wrench.png) no-repeat;background-size:1.5em}.emojify.nut_and_bolt{background:url(nut_and_bolt.png) no-repeat;background-size:1.5em}.emojify.hammer{background:url(hammer.png) no-repeat;background-size:1.5em}.emojify.seat{background:url(seat.png) no-repeat;background-size:1.5em}.emojify.moneybag{background:url(moneybag.png) no-repeat;background-size:1.5em}.emojify.yen{background:url(yen.png) no-repeat;background-size:1.5em}.emojify.dollar{background:url(dollar.png) no-repeat;background-size:1.5em}.emojify.pound{background:url(pound.png) no-repeat;background-size:1.5em}.emojify.euro{background:url(euro.png) no-repeat;background-size:1.5em}.emojify.credit_card{background:url(credit_card.png) no-repeat;background-size:1.5em}.emojify.money_with_wings{background:url(money_with_wings.png) no-repeat;background-size:1.5em}.emojify.e-mail{background:url(e-mail.png) no-repeat;background-size:1.5em}.emojify.inbox_tray{background:url(inbox_tray.png) no-repeat;background-size:1.5em}.emojify.outbox_tray{background:url(outbox_tray.png) no-repeat;background-size:1.5em}.emojify.envelope{background:url(envelope.png) no-repeat;background-size:1.5em}.emojify.incoming_envelope{background:url(incoming_envelope.png) no-repeat;background-size:1.5em}.emojify.postal_horn{background:url(postal_horn.png) no-repeat;background-size:1.5em}.emojify.mailbox_closed{background:url(mailbox_closed.png) no-repeat;background-size:1.5em}.emojify.mailbox_with_mail{background:url(mailbox_with_mail.png) no-repeat;background-size:1.5em}.emojify.mailbox_with_no_mail{background:url(mailbox_with_no_mail.png) no-repeat;background-size:1.5em}.emojify.door{background:url(door.png) no-repeat;background-size:1.5em}.emojify.smoking{background:url(smoking.png) no-repeat;background-size:1.5em}.emojify.bomb{background:url(bomb.png) no-repeat;background-size:1.5em}.emojify.gun{background:url(gun.png) no-repeat;background-size:1.5em}.emojify.hocho{background:url(hocho.png) no-repeat;background-size:1.5em}.emojify.pill{background:url(pill.png) no-repeat;background-size:1.5em}.emojify.syringe{background:url(syringe.png) no-repeat;background-size:1.5em}.emojify.page_facing_up{background:url(page_facing_up.png) no-repeat;background-size:1.5em}.emojify.page_with_curl{background:url(page_with_curl.png) no-repeat;background-size:1.5em}.emojify.bookmark_tabs{background:url(bookmark_tabs.png) no-repeat;background-size:1.5em}.emojify.bar_chart{background:url(bar_chart.png) no-repeat;background-size:1.5em}.emojify.chart_with_upwards_trend{background:url(chart_with_upwards_trend.png) no-repeat;background-size:1.5em}.emojify.chart_with_downwards_trend{background:url(chart_with_downwards_trend.png) no-repeat;background-size:1.5em}.emojify.scroll{background:url(scroll.png) no-repeat;background-size:1.5em}.emojify.clipboard{background:url(clipboard.png) no-repeat;background-size:1.5em}.emojify.calendar{background:url(calendar.png) no-repeat;background-size:1.5em}.emojify.date{background:url(date.png) no-repeat;background-size:1.5em}.emojify.card_index{background:url(card_index.png) no-repeat;background-size:1.5em}.emojify.file_folder{background:url(file_folder.png) no-repeat;background-size:1.5em}.emojify.open_file_folder{background:url(open_file_folder.png) no-repeat;background-size:1.5em}.emojify.scissors{background:url(scissors.png) no-repeat;background-size:1.5em}.emojify.pushpin{background:url(pushpin.png) no-repeat;background-size:1.5em}.emojify.paperclip{background:url(paperclip.png) no-repeat;background-size:1.5em}.emojify.black_nib{background:url(black_nib.png) no-repeat;background-size:1.5em}.emojify.pencil2{background:url(pencil2.png) no-repeat;background-size:1.5em}.emojify.straight_ruler{background:url(straight_ruler.png) no-repeat;background-size:1.5em}.emojify.triangular_ruler{background:url(triangular_ruler.png) no-repeat;background-size:1.5em}.emojify.closed_book{background:url(closed_book.png) no-repeat;background-size:1.5em}.emojify.green_book{background:url(green_book.png) no-repeat;background-size:1.5em}.emojify.blue_book{background:url(blue_book.png) no-repeat;background-size:1.5em}.emojify.orange_book{background:url(orange_book.png) no-repeat;background-size:1.5em}.emojify.notebook{background:url(notebook.png) no-repeat;background-size:1.5em}.emojify.notebook_with_decorative_cover{background:url(notebook_with_decorative_cover.png) no-repeat;background-size:1.5em}.emojify.ledger{background:url(ledger.png) no-repeat;background-size:1.5em}.emojify.books{background:url(books.png) no-repeat;background-size:1.5em}.emojify.bookmark{background:url(bookmark.png) no-repeat;background-size:1.5em}.emojify.name_badge{background:url(name_badge.png) no-repeat;background-size:1.5em}.emojify.microscope{background:url(microscope.png) no-repeat;background-size:1.5em}.emojify.telescope{background:url(telescope.png) no-repeat;background-size:1.5em}.emojify.newspaper{background:url(newspaper.png) no-repeat;background-size:1.5em}.emojify.football{background:url(football.png) no-repeat;background-size:1.5em}.emojify.basketball{background:url(basketball.png) no-repeat;background-size:1.5em}.emojify.soccer{background:url(soccer.png) no-repeat;background-size:1.5em}.emojify.baseball{background:url(baseball.png) no-repeat;background-size:1.5em}.emojify.tennis{background:url(tennis.png) no-repeat;background-size:1.5em}.emojify.eightball{background:url(eightball.png) no-repeat;background-size:1.5em}.emojify.rugby_football{background:url(rugby_football.png) no-repeat;background-size:1.5em}.emojify.bowling{background:url(bowling.png) no-repeat;background-size:1.5em}.emojify.golf{background:url(golf.png) no-repeat;background-size:1.5em}.emojify.mountain_bicyclist{background:url(mountain_bicyclist.png) no-repeat;background-size:1.5em}.emojify.bicyclist{background:url(bicyclist.png) no-repeat;background-size:1.5em}.emojify.horse_racing{background:url(horse_racing.png) no-repeat;background-size:1.5em}.emojify.snowboarder{background:url(snowboarder.png) no-repeat;background-size:1.5em}.emojify.swimmer{background:url(swimmer.png) no-repeat;background-size:1.5em}.emojify.surfer{background:url(surfer.png) no-repeat;background-size:1.5em}.emojify.ski{background:url(ski.png) no-repeat;background-size:1.5em}.emojify.spades{background:url(spades.png) no-repeat;background-size:1.5em}.emojify.hearts{background:url(hearts.png) no-repeat;background-size:1.5em}.emojify.clubs{background:url(clubs.png) no-repeat;background-size:1.5em}.emojify.diamonds{background:url(diamonds.png) no-repeat;background-size:1.5em}.emojify.gem{background:url(gem.png) no-repeat;background-size:1.5em}.emojify.ring{background:url(ring.png) no-repeat;background-size:1.5em}.emojify.trophy{background:url(trophy.png) no-repeat;background-size:1.5em}.emojify.musical_score{background:url(musical_score.png) no-repeat;background-size:1.5em}.emojify.musical_keyboard{background:url(musical_keyboard.png) no-repeat;background-size:1.5em}.emojify.violin{background:url(violin.png) no-repeat;background-size:1.5em}.emojify.space_invader{background:url(space_invader.png) no-repeat;background-size:1.5em}.emojify.video_game{background:url(video_game.png) no-repeat;background-size:1.5em}.emojify.black_joker{background:url(black_joker.png) no-repeat;background-size:1.5em}.emojify.flower_playing_cards{background:url(flower_playing_cards.png) no-repeat;background-size:1.5em}.emojify.game_die{background:url(game_die.png) no-repeat;background-size:1.5em}.emojify.dart{background:url(dart.png) no-repeat;background-size:1.5em}.emojify.mahjong{background:url(mahjong.png) no-repeat;background-size:1.5em}.emojify.clapper{background:url(clapper.png) no-repeat;background-size:1.5em}.emojify.memo{background:url(memo.png) no-repeat;background-size:1.5em}.emojify.pencil{background:url(pencil.png) no-repeat;background-size:1.5em}.emojify.book{background:url(book.png) no-repeat;background-size:1.5em}.emojify.art{background:url(art.png) no-repeat;background-size:1.5em}.emojify.microphone{background:url(microphone.png) no-repeat;background-size:1.5em}.emojify.headphones{background:url(headphones.png) no-repeat;background-size:1.5em}.emojify.trumpet{background:url(trumpet.png) no-repeat;background-size:1.5em}.emojify.saxophone{background:url(saxophone.png) no-repeat;background-size:1.5em}.emojify.guitar{background:url(guitar.png) no-repeat;background-size:1.5em}.emojify.shoe{background:url(shoe.png) no-repeat;background-size:1.5em}.emojify.sandal{background:url(sandal.png) no-repeat;background-size:1.5em}.emojify.high_heel{background:url(high_heel.png) no-repeat;background-size:1.5em}.emojify.lipstick{background:url(lipstick.png) no-repeat;background-size:1.5em}.emojify.boot{background:url(boot.png) no-repeat;background-size:1.5em}.emojify.shirt{background:url(shirt.png) no-repeat;background-size:1.5em}.emojify.tshirt{background:url(tshirt.png) no-repeat;background-size:1.5em}.emojify.necktie{background:url(necktie.png) no-repeat;background-size:1.5em}.emojify.womans_clothes{background:url(womans_clothes.png) no-repeat;background-size:1.5em}.emojify.dress{background:url(dress.png) no-repeat;background-size:1.5em}.emojify.running_shirt_with_sash{background:url(running_shirt_with_sash.png) no-repeat;background-size:1.5em}.emojify.jeans{background:url(jeans.png) no-repeat;background-size:1.5em}.emojify.kimono{background:url(kimono.png) no-repeat;background-size:1.5em}.emojify.bikini{background:url(bikini.png) no-repeat;background-size:1.5em}.emojify.ribbon{background:url(ribbon.png) no-repeat;background-size:1.5em}.emojify.tophat{background:url(tophat.png) no-repeat;background-size:1.5em}.emojify.crown{background:url(crown.png) no-repeat;background-size:1.5em}.emojify.womans_hat{background:url(womans_hat.png) no-repeat;background-size:1.5em}.emojify.mans_shoe{background:url(mans_shoe.png) no-repeat;background-size:1.5em}.emojify.closed_umbrella{background:url(closed_umbrella.png) no-repeat;background-size:1.5em}.emojify.briefcase{background:url(briefcase.png) no-repeat;background-size:1.5em}.emojify.handbag{background:url(handbag.png) no-repeat;background-size:1.5em}.emojify.pouch{background:url(pouch.png) no-repeat;background-size:1.5em}.emojify.purse{background:url(purse.png) no-repeat;background-size:1.5em}.emojify.eyeglasses{background:url(eyeglasses.png) no-repeat;background-size:1.5em}.emojify.fishing_pole_and_fish{background:url(fishing_pole_and_fish.png) no-repeat;background-size:1.5em}.emojify.coffee{background:url(coffee.png) no-repeat;background-size:1.5em}.emojify.tea{background:url(tea.png) no-repeat;background-size:1.5em}.emojify.sake{background:url(sake.png) no-repeat;background-size:1.5em}.emojify.baby_bottle{background:url(baby_bottle.png) no-repeat;background-size:1.5em}.emojify.beer{background:url(beer.png) no-repeat;background-size:1.5em}.emojify.beers{background:url(beers.png) no-repeat;background-size:1.5em}.emojify.cocktail{background:url(cocktail.png) no-repeat;background-size:1.5em}.emojify.tropical_drink{background:url(tropical_drink.png) no-repeat;background-size:1.5em}.emojify.wine_glass{background:url(wine_glass.png) no-repeat;background-size:1.5em}.emojify.fork_and_knife{background:url(fork_and_knife.png) no-repeat;background-size:1.5em}.emojify.pizza{background:url(pizza.png) no-repeat;background-size:1.5em}.emojify.hamburger{background:url(hamburger.png) no-repeat;background-size:1.5em}.emojify.fries{background:url(fries.png) no-repeat;background-size:1.5em}.emojify.poultry_leg{background:url(poultry_leg.png) no-repeat;background-size:1.5em}.emojify.meat_on_bone{background:url(meat_on_bone.png) no-repeat;background-size:1.5em}.emojify.spaghetti{background:url(spaghetti.png) no-repeat;background-size:1.5em}.emojify.curry{background:url(curry.png) no-repeat;background-size:1.5em}.emojify.fried_shrimp{background:url(fried_shrimp.png) no-repeat;background-size:1.5em}.emojify.bento{background:url(bento.png) no-repeat;background-size:1.5em}.emojify.sushi{background:url(sushi.png) no-repeat;background-size:1.5em}.emojify.fish_cake{background:url(fish_cake.png) no-repeat;background-size:1.5em}.emojify.rice_ball{background:url(rice_ball.png) no-repeat;background-size:1.5em}.emojify.rice_cracker{background:url(rice_cracker.png) no-repeat;background-size:1.5em}.emojify.rice{background:url(rice.png) no-repeat;background-size:1.5em}.emojify.ramen{background:url(ramen.png) no-repeat;background-size:1.5em}.emojify.stew{background:url(stew.png) no-repeat;background-size:1.5em}.emojify.oden{background:url(oden.png) no-repeat;background-size:1.5em}.emojify.dango{background:url(dango.png) no-repeat;background-size:1.5em}.emojify.egg{background:url(egg.png) no-repeat;background-size:1.5em}.emojify.bread{background:url(bread.png) no-repeat;background-size:1.5em}.emojify.doughnut{background:url(doughnut.png) no-repeat;background-size:1.5em}.emojify.custard{background:url(custard.png) no-repeat;background-size:1.5em}.emojify.icecream{background:url(icecream.png) no-repeat;background-size:1.5em}.emojify.ice_cream{background:url(ice_cream.png) no-repeat;background-size:1.5em}.emojify.shaved_ice{background:url(shaved_ice.png) no-repeat;background-size:1.5em}.emojify.birthday{background:url(birthday.png) no-repeat;background-size:1.5em}.emojify.cake{background:url(cake.png) no-repeat;background-size:1.5em}.emojify.cookie{background:url(cookie.png) no-repeat;background-size:1.5em}.emojify.chocolate_bar{background:url(chocolate_bar.png) no-repeat;background-size:1.5em}.emojify.candy{background:url(candy.png) no-repeat;background-size:1.5em}.emojify.lollipop{background:url(lollipop.png) no-repeat;background-size:1.5em}.emojify.honey_pot{background:url(honey_pot.png) no-repeat;background-size:1.5em}.emojify.apple{background:url(apple.png) no-repeat;background-size:1.5em}.emojify.green_apple{background:url(green_apple.png) no-repeat;background-size:1.5em}.emojify.tangerine{background:url(tangerine.png) no-repeat;background-size:1.5em}.emojify.lemon{background:url(lemon.png) no-repeat;background-size:1.5em}.emojify.cherries{background:url(cherries.png) no-repeat;background-size:1.5em}.emojify.grapes{background:url(grapes.png) no-repeat;background-size:1.5em}.emojify.watermelon{background:url(watermelon.png) no-repeat;background-size:1.5em}.emojify.strawberry{background:url(strawberry.png) no-repeat;background-size:1.5em}.emojify.peach{background:url(peach.png) no-repeat;background-size:1.5em}.emojify.melon{background:url(melon.png) no-repeat;background-size:1.5em}.emojify.banana{background:url(banana.png) no-repeat;background-size:1.5em}.emojify.pear{background:url(pear.png) no-repeat;background-size:1.5em}.emojify.pineapple{background:url(pineapple.png) no-repeat;background-size:1.5em}.emojify.sweet_potato{background:url(sweet_potato.png) no-repeat;background-size:1.5em}.emojify.eggplant{background:url(eggplant.png) no-repeat;background-size:1.5em}.emojify.tomato{background:url(tomato.png) no-repeat;background-size:1.5em}.emojify.corn{background:url(corn.png) no-repeat;background-size:1.5em}.emojify.onezeronine{background:url(onezeronine.png) no-repeat;background-size:1.5em}.emojify.house{background:url(house.png) no-repeat;background-size:1.5em}.emojify.house_with_garden{background:url(house_with_garden.png) no-repeat;background-size:1.5em}.emojify.school{background:url(school.png) no-repeat;background-size:1.5em}.emojify.office{background:url(office.png) no-repeat;background-size:1.5em}.emojify.post_office{background:url(post_office.png) no-repeat;background-size:1.5em}.emojify.hospital{background:url(hospital.png) no-repeat;background-size:1.5em}.emojify.bank{background:url(bank.png) no-repeat;background-size:1.5em}.emojify.convenience_store{background:url(convenience_store.png) no-repeat;background-size:1.5em}.emojify.love_hotel{background:url(love_hotel.png) no-repeat;background-size:1.5em}.emojify.hotel{background:url(hotel.png) no-repeat;background-size:1.5em}.emojify.wedding{background:url(wedding.png) no-repeat;background-size:1.5em}.emojify.church{background:url(church.png) no-repeat;background-size:1.5em}.emojify.department_store{background:url(department_store.png) no-repeat;background-size:1.5em}.emojify.european_post_office{background:url(european_post_office.png) no-repeat;background-size:1.5em}.emojify.city_sunrise{background:url(city_sunrise.png) no-repeat;background-size:1.5em}.emojify.city_sunset{background:url(city_sunset.png) no-repeat;background-size:1.5em}.emojify.japanese_castle{background:url(japanese_castle.png) no-repeat;background-size:1.5em}.emojify.european_castle{background:url(european_castle.png) no-repeat;background-size:1.5em}.emojify.tent{background:url(tent.png) no-repeat;background-size:1.5em}.emojify.factory{background:url(factory.png) no-repeat;background-size:1.5em}.emojify.tokyo_tower{background:url(tokyo_tower.png) no-repeat;background-size:1.5em}.emojify.japan{background:url(japan.png) no-repeat;background-size:1.5em}.emojify.mount_fuji{background:url(mount_fuji.png) no-repeat;background-size:1.5em}.emojify.sunrise_over_mountains{background:url(sunrise_over_mountains.png) no-repeat;background-size:1.5em}.emojify.sunrise{background:url(sunrise.png) no-repeat;background-size:1.5em}.emojify.stars{background:url(stars.png) no-repeat;background-size:1.5em}.emojify.statue_of_liberty{background:url(statue_of_liberty.png) no-repeat;background-size:1.5em}.emojify.bridge_at_night{background:url(bridge_at_night.png) no-repeat;background-size:1.5em}.emojify.carousel_horse{background:url(carousel_horse.png) no-repeat;background-size:1.5em}.emojify.rainbow{background:url(rainbow.png) no-repeat;background-size:1.5em}.emojify.ferris_wheel{background:url(ferris_wheel.png) no-repeat;background-size:1.5em}.emojify.fountain{background:url(fountain.png) no-repeat;background-size:1.5em}.emojify.roller_coaster{background:url(roller_coaster.png) no-repeat;background-size:1.5em}.emojify.ship{background:url(ship.png) no-repeat;background-size:1.5em}.emojify.speedboat{background:url(speedboat.png) no-repeat;background-size:1.5em}.emojify.boat{background:url(boat.png) no-repeat;background-size:1.5em}.emojify.sailboat{background:url(sailboat.png) no-repeat;background-size:1.5em}.emojify.rowboat{background:url(rowboat.png) no-repeat;background-size:1.5em}.emojify.anchor{background:url(anchor.png) no-repeat;background-size:1.5em}.emojify.rocket{background:url(rocket.png) no-repeat;background-size:1.5em}.emojify.airplane{background:url(airplane.png) no-repeat;background-size:1.5em}.emojify.helicopter{background:url(helicopter.png) no-repeat;background-size:1.5em}.emojify.steam_locomotive{background:url(steam_locomotive.png) no-repeat;background-size:1.5em}.emojify.tram{background:url(tram.png) no-repeat;background-size:1.5em}.emojify.mountain_railway{background:url(mountain_railway.png) no-repeat;background-size:1.5em}.emojify.bike{background:url(bike.png) no-repeat;background-size:1.5em}.emojify.aerial_tramway{background:url(aerial_tramway.png) no-repeat;background-size:1.5em}.emojify.suspension_railway{background:url(suspension_railway.png) no-repeat;background-size:1.5em}.emojify.mountain_cableway{background:url(mountain_cableway.png) no-repeat;background-size:1.5em}.emojify.tractor{background:url(tractor.png) no-repeat;background-size:1.5em}.emojify.blue_car{background:url(blue_car.png) no-repeat;background-size:1.5em}.emojify.oncoming_automobile{background:url(oncoming_automobile.png) no-repeat;background-size:1.5em}.emojify.car{background:url(car.png) no-repeat;background-size:1.5em}.emojify.red_car{background:url(red_car.png) no-repeat;background-size:1.5em}.emojify.taxi{background:url(taxi.png) no-repeat;background-size:1.5em}.emojify.oncoming_taxi{background:url(oncoming_taxi.png) no-repeat;background-size:1.5em}.emojify.articulated_lorry{background:url(articulated_lorry.png) no-repeat;background-size:1.5em}.emojify.bus{background:url(bus.png) no-repeat;background-size:1.5em}.emojify.oncoming_bus{background:url(oncoming_bus.png) no-repeat;background-size:1.5em}.emojify.rotating_light{background:url(rotating_light.png) no-repeat;background-size:1.5em}.emojify.police_car{background:url(police_car.png) no-repeat;background-size:1.5em}.emojify.oncoming_police_car{background:url(oncoming_police_car.png) no-repeat;background-size:1.5em}.emojify.fire_engine{background:url(fire_engine.png) no-repeat;background-size:1.5em}.emojify.ambulance{background:url(ambulance.png) no-repeat;background-size:1.5em}.emojify.minibus{background:url(minibus.png) no-repeat;background-size:1.5em}.emojify.truck{background:url(truck.png) no-repeat;background-size:1.5em}.emojify.train{background:url(train.png) no-repeat;background-size:1.5em}.emojify.station{background:url(station.png) no-repeat;background-size:1.5em}.emojify.train2{background:url(train2.png) no-repeat;background-size:1.5em}.emojify.bullettrain_front{background:url(bullettrain_front.png) no-repeat;background-size:1.5em}.emojify.bullettrain_side{background:url(bullettrain_side.png) no-repeat;background-size:1.5em}.emojify.light_rail{background:url(light_rail.png) no-repeat;background-size:1.5em}.emojify.monorail{background:url(monorail.png) no-repeat;background-size:1.5em}.emojify.railway_car{background:url(railway_car.png) no-repeat;background-size:1.5em}.emojify.trolleybus{background:url(trolleybus.png) no-repeat;background-size:1.5em}.emojify.ticket{background:url(ticket.png) no-repeat;background-size:1.5em}.emojify.fuelpump{background:url(fuelpump.png) no-repeat;background-size:1.5em}.emojify.vertical_traffic_light{background:url(vertical_traffic_light.png) no-repeat;background-size:1.5em}.emojify.traffic_light{background:url(traffic_light.png) no-repeat;background-size:1.5em}.emojify.warning{background:url(warning.png) no-repeat;background-size:1.5em}.emojify.construction{background:url(construction.png) no-repeat;background-size:1.5em}.emojify.beginner{background:url(beginner.png) no-repeat;background-size:1.5em}.emojify.atm{background:url(atm.png) no-repeat;background-size:1.5em}.emojify.slot_machine{background:url(slot_machine.png) no-repeat;background-size:1.5em}.emojify.busstop{background:url(busstop.png) no-repeat;background-size:1.5em}.emojify.barber{background:url(barber.png) no-repeat;background-size:1.5em}.emojify.hotsprings{background:url(hotsprings.png) no-repeat;background-size:1.5em}.emojify.checkered_flag{background:url(checkered_flag.png) no-repeat;background-size:1.5em}.emojify.crossed_flags{background:url(crossed_flags.png) no-repeat;background-size:1.5em}.emojify.izakaya_lantern{background:url(izakaya_lantern.png) no-repeat;background-size:1.5em}.emojify.moyai{background:url(moyai.png) no-repeat;background-size:1.5em}.emojify.circus_tent{background:url(circus_tent.png) no-repeat;background-size:1.5em}.emojify.performing_arts{background:url(performing_arts.png) no-repeat;background-size:1.5em}.emojify.round_pushpin{background:url(round_pushpin.png) no-repeat;background-size:1.5em}.emojify.triangular_flag_on_post{background:url(triangular_flag_on_post.png) no-repeat;background-size:1.5em}.emojify.jp{background:url(jp.png) no-repeat;background-size:1.5em}.emojify.kr{background:url(kr.png) no-repeat;background-size:1.5em}.emojify.cn{background:url(cn.png) no-repeat;background-size:1.5em}.emojify.us{background:url(us.png) no-repeat;background-size:1.5em}.emojify.fr{background:url(fr.png) no-repeat;background-size:1.5em}.emojify.es{background:url(es.png) no-repeat;background-size:1.5em}.emojify.it{background:url(it.png) no-repeat;background-size:1.5em}.emojify.ru{background:url(ru.png) no-repeat;background-size:1.5em}.emojify.gb{background:url(gb.png) no-repeat;background-size:1.5em}.emojify.uk{background:url(uk.png) no-repeat;background-size:1.5em}.emojify.de{background:url(de.png) no-repeat;background-size:1.5em}.emojify.one{background:url(one.png) no-repeat;background-size:1.5em}.emojify.two{background:url(two.png) no-repeat;background-size:1.5em}.emojify.three{background:url(three.png) no-repeat;background-size:1.5em}.emojify.four{background:url(four.png) no-repeat;background-size:1.5em}.emojify.five{background:url(five.png) no-repeat;background-size:1.5em}.emojify.six{background:url(six.png) no-repeat;background-size:1.5em}.emojify.seven{background:url(seven.png) no-repeat;background-size:1.5em}.emojify.eight{background:url(eight.png) no-repeat;background-size:1.5em}.emojify.nine{background:url(nine.png) no-repeat;background-size:1.5em}.emojify.keycap_ten{background:url(keycap_ten.png) no-repeat;background-size:1.5em}.emojify.onetwothreefour{background:url(onetwothreefour.png) no-repeat;background-size:1.5em}.emojify.zero{background:url(zero.png) no-repeat;background-size:1.5em}.emojify.hash{background:url(hash.png) no-repeat;background-size:1.5em}.emojify.symbols{background:url(symbols.png) no-repeat;background-size:1.5em}.emojify.arrow_backward{background:url(arrow_backward.png) no-repeat;background-size:1.5em}.emojify.arrow_down{background:url(arrow_down.png) no-repeat;background-size:1.5em}.emojify.arrow_forward{background:url(arrow_forward.png) no-repeat;background-size:1.5em}.emojify.arrow_left{background:url(arrow_left.png) no-repeat;background-size:1.5em}.emojify.capital_abcd{background:url(capital_abcd.png) no-repeat;background-size:1.5em}.emojify.abcd{background:url(abcd.png) no-repeat;background-size:1.5em}.emojify.abc{background:url(abc.png) no-repeat;background-size:1.5em}.emojify.arrow_lower_left{background:url(arrow_lower_left.png) no-repeat;background-size:1.5em}.emojify.arrow_lower_right{background:url(arrow_lower_right.png) no-repeat;background-size:1.5em}.emojify.arrow_right{background:url(arrow_right.png) no-repeat;background-size:1.5em}.emojify.arrow_up{background:url(arrow_up.png) no-repeat;background-size:1.5em}.emojify.arrow_upper_left{background:url(arrow_upper_left.png) no-repeat;background-size:1.5em}.emojify.arrow_upper_right{background:url(arrow_upper_right.png) no-repeat;background-size:1.5em}.emojify.arrow_double_down{background:url(arrow_double_down.png) no-repeat;background-size:1.5em}.emojify.arrow_double_up{background:url(arrow_double_up.png) no-repeat;background-size:1.5em}.emojify.arrow_down_small{background:url(arrow_down_small.png) no-repeat;background-size:1.5em}.emojify.arrow_heading_down{background:url(arrow_heading_down.png) no-repeat;background-size:1.5em}.emojify.arrow_heading_up{background:url(arrow_heading_up.png) no-repeat;background-size:1.5em}.emojify.leftwards_arrow_with_hook{background:url(leftwards_arrow_with_hook.png) no-repeat;background-size:1.5em}.emojify.arrow_right_hook{background:url(arrow_right_hook.png) no-repeat;background-size:1.5em}.emojify.left_right_arrow{background:url(left_right_arrow.png) no-repeat;background-size:1.5em}.emojify.arrow_up_down{background:url(arrow_up_down.png) no-repeat;background-size:1.5em}.emojify.arrow_up_small{background:url(arrow_up_small.png) no-repeat;background-size:1.5em}.emojify.arrows_clockwise{background:url(arrows_clockwise.png) no-repeat;background-size:1.5em}.emojify.arrows_counterclockwise{background:url(arrows_counterclockwise.png) no-repeat;background-size:1.5em}.emojify.rewind{background:url(rewind.png) no-repeat;background-size:1.5em}.emojify.fast_forward{background:url(fast_forward.png) no-repeat;background-size:1.5em}.emojify.information_source{background:url(information_source.png) no-repeat;background-size:1.5em}.emojify.ok{background:url(ok.png) no-repeat;background-size:1.5em}.emojify.twisted_rightwards_arrows{background:url(twisted_rightwards_arrows.png) no-repeat;background-size:1.5em}.emojify.repeat{background:url(repeat.png) no-repeat;background-size:1.5em}.emojify.repeat_one{background:url(repeat_one.png) no-repeat;background-size:1.5em}.emojify.new{background:url(new.png) no-repeat;background-size:1.5em}.emojify.top{background:url(top.png) no-repeat;background-size:1.5em}.emojify.up{background:url(up.png) no-repeat;background-size:1.5em}.emojify.cool{background:url(cool.png) no-repeat;background-size:1.5em}.emojify.free{background:url(free.png) no-repeat;background-size:1.5em}.emojify.ng{background:url(ng.png) no-repeat;background-size:1.5em}.emojify.cinema{background:url(cinema.png) no-repeat;background-size:1.5em}.emojify.koko{background:url(koko.png) no-repeat;background-size:1.5em}.emojify.signal_strength{background:url(signal_strength.png) no-repeat;background-size:1.5em}.emojify.u5272{background:url(u5272.png) no-repeat;background-size:1.5em}.emojify.u5408{background:url(u5408.png) no-repeat;background-size:1.5em}.emojify.u55b6{background:url(u55b6.png) no-repeat;background-size:1.5em}.emojify.u6307{background:url(u6307.png) no-repeat;background-size:1.5em}.emojify.u6708{background:url(u6708.png) no-repeat;background-size:1.5em}.emojify.u6709{background:url(u6709.png) no-repeat;background-size:1.5em}.emojify.u6e80{background:url(u6e80.png) no-repeat;background-size:1.5em}.emojify.u7121{background:url(u7121.png) no-repeat;background-size:1.5em}.emojify.u7533{background:url(u7533.png) no-repeat;background-size:1.5em}.emojify.u7a7a{background:url(u7a7a.png) no-repeat;background-size:1.5em}.emojify.u7981{background:url(u7981.png) no-repeat;background-size:1.5em}.emojify.sa{background:url(sa.png) no-repeat;background-size:1.5em}.emojify.restroom{background:url(restroom.png) no-repeat;background-size:1.5em}.emojify.mens{background:url(mens.png) no-repeat;background-size:1.5em}.emojify.womens{background:url(womens.png) no-repeat;background-size:1.5em}.emojify.baby_symbol{background:url(baby_symbol.png) no-repeat;background-size:1.5em}.emojify.no_smoking{background:url(no_smoking.png) no-repeat;background-size:1.5em}.emojify.parking{background:url(parking.png) no-repeat;background-size:1.5em}.emojify.wheelchair{background:url(wheelchair.png) no-repeat;background-size:1.5em}.emojify.metro{background:url(metro.png) no-repeat;background-size:1.5em}.emojify.baggage_claim{background:url(baggage_claim.png) no-repeat;background-size:1.5em}.emojify.accept{background:url(accept.png) no-repeat;background-size:1.5em}.emojify.wc{background:url(wc.png) no-repeat;background-size:1.5em}.emojify.potable_water{background:url(potable_water.png) no-repeat;background-size:1.5em}.emojify.put_litter_in_its_place{background:url(put_litter_in_its_place.png) no-repeat;background-size:1.5em}.emojify.secret{background:url(secret.png) no-repeat;background-size:1.5em}.emojify.congratulations{background:url(congratulations.png) no-repeat;background-size:1.5em}.emojify.m{background:url(m.png) no-repeat;background-size:1.5em}.emojify.passport_control{background:url(passport_control.png) no-repeat;background-size:1.5em}.emojify.left_luggage{background:url(left_luggage.png) no-repeat;background-size:1.5em}.emojify.customs{background:url(customs.png) no-repeat;background-size:1.5em}.emojify.ideograph_advantage{background:url(ideograph_advantage.png) no-repeat;background-size:1.5em}.emojify.cl{background:url(cl.png) no-repeat;background-size:1.5em}.emojify.sos{background:url(sos.png) no-repeat;background-size:1.5em}.emojify.id{background:url(id.png) no-repeat;background-size:1.5em}.emojify.no_entry_sign{background:url(no_entry_sign.png) no-repeat;background-size:1.5em}.emojify.underage{background:url(underage.png) no-repeat;background-size:1.5em}.emojify.no_mobile_phones{background:url(no_mobile_phones.png) no-repeat;background-size:1.5em}.emojify.do_not_litter{background:url(do_not_litter.png) no-repeat;background-size:1.5em}.emojify.non-potable_water{background:url(non-potable_water.png) no-repeat;background-size:1.5em}.emojify.no_bicycles{background:url(no_bicycles.png) no-repeat;background-size:1.5em}.emojify.no_pedestrians{background:url(no_pedestrians.png) no-repeat;background-size:1.5em}.emojify.children_crossing{background:url(children_crossing.png) no-repeat;background-size:1.5em}.emojify.no_entry{background:url(no_entry.png) no-repeat;background-size:1.5em}.emojify.eight_spoked_asterisk{background:url(eight_spoked_asterisk.png) no-repeat;background-size:1.5em}.emojify.eight_pointed_black_star{background:url(eight_pointed_black_star.png) no-repeat;background-size:1.5em}.emojify.heart_decoration{background:url(heart_decoration.png) no-repeat;background-size:1.5em}.emojify.vs{background:url(vs.png) no-repeat;background-size:1.5em}.emojify.vibration_mode{background:url(vibration_mode.png) no-repeat;background-size:1.5em}.emojify.mobile_phone_off{background:url(mobile_phone_off.png) no-repeat;background-size:1.5em}.emojify.chart{background:url(chart.png) no-repeat;background-size:1.5em}.emojify.currency_exchange{background:url(currency_exchange.png) no-repeat;background-size:1.5em}.emojify.aries{background:url(aries.png) no-repeat;background-size:1.5em}.emojify.taurus{background:url(taurus.png) no-repeat;background-size:1.5em}.emojify.gemini{background:url(gemini.png) no-repeat;background-size:1.5em}.emojify.cancer{background:url(cancer.png) no-repeat;background-size:1.5em}.emojify.leo{background:url(leo.png) no-repeat;background-size:1.5em}.emojify.virgo{background:url(virgo.png) no-repeat;background-size:1.5em}.emojify.libra{background:url(libra.png) no-repeat;background-size:1.5em}.emojify.scorpius{background:url(scorpius.png) no-repeat;background-size:1.5em}.emojify.sagittarius{background:url(sagittarius.png) no-repeat;background-size:1.5em}.emojify.capricorn{background:url(capricorn.png) no-repeat;background-size:1.5em}.emojify.aquarius{background:url(aquarius.png) no-repeat;background-size:1.5em}.emojify.pisces{background:url(pisces.png) no-repeat;background-size:1.5em}.emojify.ophiuchus{background:url(ophiuchus.png) no-repeat;background-size:1.5em}.emojify.six_pointed_star{background:url(six_pointed_star.png) no-repeat;background-size:1.5em}.emojify.negative_squared_cross_mark{background:url(negative_squared_cross_mark.png) no-repeat;background-size:1.5em}.emojify.a{background:url(a.png) no-repeat;background-size:1.5em}.emojify.b{background:url(b.png) no-repeat;background-size:1.5em}.emojify.ab{background:url(ab.png) no-repeat;background-size:1.5em}.emojify.o2{background:url(o2.png) no-repeat;background-size:1.5em}.emojify.diamond_shape_with_a_dot_inside{background:url(diamond_shape_with_a_dot_inside.png) no-repeat;background-size:1.5em}.emojify.recycle{background:url(recycle.png) no-repeat;background-size:1.5em}.emojify.end{background:url(end.png) no-repeat;background-size:1.5em}.emojify.on{background:url(on.png) no-repeat;background-size:1.5em}.emojify.soon{background:url(soon.png) no-repeat;background-size:1.5em}.emojify.clock1{background:url(clock1.png) no-repeat;background-size:1.5em}.emojify.clock130{background:url(clock130.png) no-repeat;background-size:1.5em}.emojify.clock10{background:url(clock10.png) no-repeat;background-size:1.5em}.emojify.clock1030{background:url(clock1030.png) no-repeat;background-size:1.5em}.emojify.clock11{background:url(clock11.png) no-repeat;background-size:1.5em}.emojify.clock1130{background:url(clock1130.png) no-repeat;background-size:1.5em}.emojify.clock12{background:url(clock12.png) no-repeat;background-size:1.5em}.emojify.clock1230{background:url(clock1230.png) no-repeat;background-size:1.5em}.emojify.clock2{background:url(clock2.png) no-repeat;background-size:1.5em}.emojify.clock230{background:url(clock230.png) no-repeat;background-size:1.5em}.emojify.clock3{background:url(clock3.png) no-repeat;background-size:1.5em}.emojify.clock330{background:url(clock330.png) no-repeat;background-size:1.5em}.emojify.clock4{background:url(clock4.png) no-repeat;background-size:1.5em}.emojify.clock430{background:url(clock430.png) no-repeat;background-size:1.5em}.emojify.clock5{background:url(clock5.png) no-repeat;background-size:1.5em}.emojify.clock530{background:url(clock530.png) no-repeat;background-size:1.5em}.emojify.clock6{background:url(clock6.png) no-repeat;background-size:1.5em}.emojify.clock630{background:url(clock630.png) no-repeat;background-size:1.5em}.emojify.clock7{background:url(clock7.png) no-repeat;background-size:1.5em}.emojify.clock730{background:url(clock730.png) no-repeat;background-size:1.5em}.emojify.clock8{background:url(clock8.png) no-repeat;background-size:1.5em}.emojify.clock830{background:url(clock830.png) no-repeat;background-size:1.5em}.emojify.clock9{background:url(clock9.png) no-repeat;background-size:1.5em}.emojify.clock930{background:url(clock930.png) no-repeat;background-size:1.5em}.emojify.heavy_dollar_sign{background:url(heavy_dollar_sign.png) no-repeat;background-size:1.5em}.emojify.copyright{background:url(copyright.png) no-repeat;background-size:1.5em}.emojify.registered{background:url(registered.png) no-repeat;background-size:1.5em}.emojify.tm{background:url(tm.png) no-repeat;background-size:1.5em}.emojify.x{background:url(x.png) no-repeat;background-size:1.5em}.emojify.heavy_exclamation_mark{background:url(heavy_exclamation_mark.png) no-repeat;background-size:1.5em}.emojify.bangbang{background:url(bangbang.png) no-repeat;background-size:1.5em}.emojify.interrobang{backgro
Download .txt
gitextract_ku31l5mv/

├── .gitattributes
├── .gitignore
├── .gitmodules
├── Cakefile
├── Gemfile
├── Guardfile
├── LICENSE
├── Makefile
├── Procfile
├── README.md
├── app/
│   ├── controllers/
│   │   ├── account.coffee
│   │   ├── browser.coffee
│   │   ├── editor.coffee
│   │   ├── modal.coffee
│   │   ├── note.item.coffee
│   │   ├── notebook.item.coffee
│   │   ├── panel.coffee
│   │   ├── popover.coffee
│   │   ├── settings.coffee
│   │   ├── sidebar.coffee
│   │   ├── sync.coffee
│   │   └── upgrader.coffee
│   ├── index.coffee
│   ├── init.coffee
│   ├── lib/
│   │   ├── setup.coffee
│   │   └── splitter.js
│   ├── models/
│   │   ├── .gitkeep
│   │   ├── note.coffee
│   │   └── notebook.coffee
│   └── views/
│       ├── .gitkeep
│       ├── note.handlebars
│       └── notebook.handlebars
├── css/
│   ├── font.scss
│   ├── keyframes.scss
│   ├── new.scss
│   └── normalize.scss
├── package.json
├── public/
│   ├── about.html
│   ├── default.json
│   ├── emojify.js
│   ├── handlebars.runtime.js
│   ├── images/
│   │   └── emoji/
│   │       └── emojify.css
│   ├── index.html
│   └── sublime.css
└── src/
    ├── AboutWindow.coffee
    ├── Springseed.coffee
    └── main.coffee
Download .txt
SYMBOL INDEX (8 symbols across 1 files)

FILE: public/emojify.js
  function b (line 3) | function b(a){return" "===a||"	"===a||"\r"===a||"\n"===a||""===a}
  function c (line 3) | function c(a,b,c){var d=i.createElement("img");d.setAttribute("title",":...
  function d (line 3) | function d(a){if(a[1]&&a[2]){var b=a[2];if(l[b])return b}else for(var c=...
  function e (line 3) | function e(a,b){return"<img title=':"+b+":' alt=':"+b+":' class='emoji' ...
  function f (line 3) | function f(){this.lastEmojiTerminatedAt=-1}
  function g (line 3) | function g(a,b){if(!a)return a;b||(b=e);var c=new f;return a.replace(p,f...
  function h (line 3) | function h(a){"undefined"==typeof a&&(a=q.only_crawl_id?i.getElementById...
  function f (line 3) | function f(){return g.lastEmojiTerminatedAt=j+c,h}
Condensed preview — 47 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (220K chars).
[
  {
    "path": ".gitattributes",
    "chars": 89,
    "preview": "* text\n\n# Binary Files.\n*.png binary\n*.jpg binary\n*.gif binary\n*.svg binary\n*.ttf binary\n"
  },
  {
    "path": ".gitignore",
    "chars": 273,
    "preview": "*~\njavascript/*.js\n.sass-cache\nnode_modules\n*.sublime-project\n*.sublime-workspace\n\ncodekit-config.json\nlibpeerconnection"
  },
  {
    "path": ".gitmodules",
    "chars": 130,
    "preview": "[submodule \"app/lib/socket.io-client\"]\n\tpath = app/lib/socket.io-client\n\turl = https://github.com/LearnBoost/socket.io-c"
  },
  {
    "path": "Cakefile",
    "chars": 2171,
    "preview": "\nScrunch = require 'coffee-scrunch'\nuglify  = require 'uglify-js'\nserver  = require 'node-static'\nhttp    = require 'htt"
  },
  {
    "path": "Gemfile",
    "chars": 157,
    "preview": "source 'https://rubygems.org'\n\n# Automatically run `make` everytime a file is changed, see Guardfile for internals.\ngem "
  },
  {
    "path": "Guardfile",
    "chars": 454,
    "preview": "# Only used for development!\n# Always run using bundle! (`bundle exec guard`)\n\n\nguard :shell do\n  watch(/.*\\.coffee$/) d"
  },
  {
    "path": "LICENSE",
    "chars": 1189,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2013-2014 Jono Cooper\nCopyright (c) 2013-2014 Micheal Harker\nCopyright (c) 2013-201"
  },
  {
    "path": "Makefile",
    "chars": 694,
    "preview": "node_bin = ./node_modules/.bin\n\nspsd = app/init.coffee\natom = $(wildcard src/*.coffee)\ncss = css/new.scss\n\nspsd_out = pu"
  },
  {
    "path": "Procfile",
    "chars": 21,
    "preview": "web: serveup ./public"
  },
  {
    "path": "README.md",
    "chars": 2227,
    "preview": "# Springseed\n[![Stories in Ready](https://badge.waffle.io/byhestia/springseed.svg?label=ready&title=Ready)](http://waffl"
  },
  {
    "path": "app/controllers/account.coffee",
    "chars": 1709,
    "preview": "Spine = require 'spine'\n\nclass Account\n  constructor: ->\n\n  @signin: (username, password) ->\n    # Sign in to the Spring"
  },
  {
    "path": "app/controllers/browser.coffee",
    "chars": 2715,
    "preview": "Spine = require 'spine'\n\n# Models\nNote = require '../models/note.coffee'\nNotebook = require '../models/notebook.coffee'\n"
  },
  {
    "path": "app/controllers/editor.coffee",
    "chars": 9680,
    "preview": "Spine = require 'spine'\nmarked = require 'marked'\nhljs = require 'highlight.js'\n\n# Models\nNote = require '../models/note"
  },
  {
    "path": "app/controllers/modal.coffee",
    "chars": 4462,
    "preview": "Spine = require 'spine'\n$ = Spine.$\n\n# Needed.\nNote = require '../models/note.coffee'\nNotebook = require '../models/note"
  },
  {
    "path": "app/controllers/note.item.coffee",
    "chars": 1088,
    "preview": "Spine = require 'spine'\n\n# Models\nNote = require '../models/note.coffee'\n\nclass NoteItem extends Spine.Controller\n\n  ele"
  },
  {
    "path": "app/controllers/notebook.item.coffee",
    "chars": 3968,
    "preview": "Spine = require 'spine'\n\n# Models\nNotebook = require '../models/notebook.coffee'\n\nclass NotebookItem extends Spine.Contr"
  },
  {
    "path": "app/controllers/panel.coffee",
    "chars": 2098,
    "preview": "Spine = require 'spine'\n\n# Models\nNote = require '../models/note.coffee'\nNotebook = require '../models/notebook.coffee'\n"
  },
  {
    "path": "app/controllers/popover.coffee",
    "chars": 1825,
    "preview": "Spine = require 'spine'\n\n# Models\nNotebook = require '../models/notebook.coffee'\n\nModal = require './modal.coffee'\n\nclas"
  },
  {
    "path": "app/controllers/settings.coffee",
    "chars": 3248,
    "preview": "Spine = require 'spine'\n$ = Spine.$\n\nshell = window.require('shell') if window.require\n\nSync = require './sync.coffee'\nA"
  },
  {
    "path": "app/controllers/sidebar.coffee",
    "chars": 3114,
    "preview": "Spine = require 'spine'\n\n# Models\nNote = require '../models/note.coffee'\nNotebook = require '../models/notebook.coffee'\n"
  },
  {
    "path": "app/controllers/sync.coffee",
    "chars": 21179,
    "preview": "Spine = @Spine or require 'spine'\nio = require '../lib/socket.io-client/dist/socket.io.js'\nModel = Spine.Model\n\n# Connec"
  },
  {
    "path": "app/controllers/upgrader.coffee",
    "chars": 4666,
    "preview": "###############\n# If you're reading this code, and you're like\n# ERMAGERD, WHY IS THIS IDIOT USING NODE.JS, S`NOT EVEN A"
  },
  {
    "path": "app/index.coffee",
    "chars": 3937,
    "preview": "require './lib/setup.coffee'\nSpine = require 'spine'\n\nshell = window.require('shell') if window.require\nAnalytics = requ"
  },
  {
    "path": "app/init.coffee",
    "chars": 130,
    "preview": "jQuery  = require 'jqueryify'\nexports = this\njQuery ->\n  App = require './index.coffee'\n  exports.app = new App\n    el: "
  },
  {
    "path": "app/lib/setup.coffee",
    "chars": 76,
    "preview": "require('jqueryify')\n\nrequire('spine')\nrequire '../controllers/sync.coffee'\n"
  },
  {
    "path": "app/lib/splitter.js",
    "chars": 6463,
    "preview": "(function() {\n\n  // Variables\n  var parent;\n  var panels = {};\n  var splitters = {};\n  var parentOffset = 0;\n  var width"
  },
  {
    "path": "app/models/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "app/models/note.coffee",
    "chars": 2648,
    "preview": "Spine = require 'spine'\nNotebook = require './notebook.coffee'\n\nclass window.Note extends Spine.Model\n  @configure 'Note"
  },
  {
    "path": "app/models/notebook.coffee",
    "chars": 775,
    "preview": "Spine = require 'spine'\n\nclass window.Notebook extends Spine.Model\n  @configure 'Notebook',\n    'name',\n    'categories'"
  },
  {
    "path": "app/views/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "app/views/note.handlebars",
    "chars": 148,
    "preview": "<li id=\"note-{{id}}\" draggable=\"true\" data-notebook=\"{{notebook}}\">\n  <h2>{{name}}</h2>\n  <time>{{date}}  - </time><span"
  },
  {
    "path": "app/views/notebook.handlebars",
    "chars": 277,
    "preview": "<li class=\"notebook\" id=\"notebook-{{id}}\"><span class=\"name\">{{name}}</span><span class=\"icon\"></span>\n<ul class=\"catego"
  },
  {
    "path": "css/font.scss",
    "chars": 692,
    "preview": "@font-face {\n  font-family: 'YK Thin';\n  font-style: normal;\n  font-weight: 400;\n  src: url(\"YanoneKaffeesatz-Thin.ttf\")"
  },
  {
    "path": "css/keyframes.scss",
    "chars": 315,
    "preview": "@-webkit-keyframes zoom-in {\n\t0% {\n\t\t-webkit-transform: scale(0.1) transform3d(0,0,0);\n\t}\n\n\t100% {\n\t\t-webkit-transform: "
  },
  {
    "path": "css/new.scss",
    "chars": 11122,
    "preview": "@import \"font\";\n@import \"normalize\";\n@import \"keyframes\";\n\n$light-color: #ecf0f1;\n$gray-color: #AAAAAA;\n$dark-color: #2d"
  },
  {
    "path": "css/normalize.scss",
    "chars": 9035,
    "preview": "/*! normalize.css v1.0.1 | MIT License | git.io/normalize */\n\n/* ======================================================="
  },
  {
    "path": "package.json",
    "chars": 803,
    "preview": "{\n    \"main\": \"src/main.js\",\n    \"name\": \"Springseed\",\n    \"version\": \"2.0.0\",\n    \"repository\": {\n        \"type\":\"git\","
  },
  {
    "path": "public/about.html",
    "chars": 387,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>About</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"application.cs"
  },
  {
    "path": "public/default.json",
    "chars": 703,
    "preview": "[\n\t{\n\t\t\"name\": \"Springseed!\",\n\t\t\"content\": \"Springseed 2.0 is here and there's a lot going on. We finally have a Twitter"
  },
  {
    "path": "public/emojify.js",
    "chars": 11803,
    "preview": "/*! emojify.js - v0.9.2 - \n * Copyright (c) Hassan Khan 2014\n */!function(a){\"use strict\";var b=function(){function b(a)"
  },
  {
    "path": "public/handlebars.runtime.js",
    "chars": 10982,
    "preview": "/*\n\nCopyright (C) 2011 by Yehuda Katz\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "public/images/emoji/emojify.css",
    "chars": 70112,
    "preview": ".emojify{width:1.5em;height:1.5em;display:inline-block;margin-bottom:-0.25em}.emojify.alien{background:url(alien.png) no"
  },
  {
    "path": "public/index.html",
    "chars": 7798,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=utf-8>\n  <title>Springseed</title>\n  <!-- TODO: Find out how to include th"
  },
  {
    "path": "public/sublime.css",
    "chars": 1606,
    "preview": "/*\n\nMonokai Sublime style. Derived from Monokai by noformnocontent http://nn.mit-license.org/\n\n*/\n\npre code {\n  display:"
  },
  {
    "path": "src/AboutWindow.coffee",
    "chars": 535,
    "preview": "# Springseed. Simply awesome note taking.\n# Copyright (c) 2014, Springseed Team\n# All Rights Reserved.\n\napp = require \"a"
  },
  {
    "path": "src/Springseed.coffee",
    "chars": 1777,
    "preview": "# Springseed. Simply awesome note taking.\n# Copyright (c) 2014, Springseed Team\n# All Rights Reserved.\n\napp = require \"a"
  },
  {
    "path": "src/main.coffee",
    "chars": 343,
    "preview": "# Springseed. Simply awesome note taking.\n# Copyright (c) 2014, Springseed Team\n# All Rights Reserved.\n\napp = require \"a"
  }
]

About this extraction

This page contains the full source code of the byhestia/springseed GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 47 files (204.7 KB), approximately 59.0k tokens, and a symbol index with 8 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!