written 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/lib/written/app/assets/javascripts/written/attachments/image.coffee +113 -0
 - data/lib/written/app/assets/javascripts/written/core/attachments.coffee +37 -0
 - data/lib/written/app/assets/javascripts/written/core/content.coffee +12 -26
 - data/lib/written/app/assets/javascripts/written/parsers/block/image.coffee +1 -1
 - data/lib/written/app/assets/javascripts/written.coffee +1 -1
 - data/lib/written/app/assets/stylesheets/written.scss +116 -16
 - data/lib/written/version.rb +1 -1
 - data/test/server/app/assets/javascripts/application.coffee +3 -1
 - data/test/server/app/views/posts/show.html.erb +4 -4
 - metadata +4 -3
 - data/lib/written/app/assets/javascripts/written/uploaders/aws.coffee +0 -125
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 3feabb75dd783639d084dd9b58cb552d195a8a38
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: cf8fbadf5551a7d453904460bc4ba4cb5b7f0676
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 43c5f5f0d01986530cdbbba47fcfecdafc6c07b367027b3413603aba5cb33fda21adfb34dff6f1263488eb9a6f4ca50d38ac1194a3eabfe5cef39556535c8370
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 10722bca8267b18cf3a268aefe0ec7bd82afb4445918b8f65c801ddf5484e0c8e212c1f7b0222351032b63fd643df4ac57c9b821e6488ac0b732d8916de65ea2
         
     | 
| 
         @@ -0,0 +1,113 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class Image extends Written.Attachments.Base
         
     | 
| 
      
 2 
     | 
    
         
            +
              constructor: (@node) ->
         
     | 
| 
      
 3 
     | 
    
         
            +
                @input = document.createElement('input')
         
     | 
| 
      
 4 
     | 
    
         
            +
                @input.type = 'file'
         
     | 
| 
      
 5 
     | 
    
         
            +
                @input.addEventListener 'change', @confirm.bind(this, @node)
         
     | 
| 
      
 6 
     | 
    
         
            +
                @node.querySelector('img').addEventListener 'click', @select.bind(this, @node)
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              template: ->
         
     | 
| 
      
 9 
     | 
    
         
            +
                "<div id='WrittenOverlay' contenteditable=false>
         
     | 
| 
      
 10 
     | 
    
         
            +
                    <div id='WrittenDialog'>
         
     | 
| 
      
 11 
     | 
    
         
            +
                      <header>
         
     | 
| 
      
 12 
     | 
    
         
            +
                        <div class='progress'></div>
         
     | 
| 
      
 13 
     | 
    
         
            +
                        <button data-action='cancel'>Cancel</button>
         
     | 
| 
      
 14 
     | 
    
         
            +
                        <h3>Use this image?</h3>
         
     | 
| 
      
 15 
     | 
    
         
            +
                        <button data-action='upload'>Use</button>
         
     | 
| 
      
 16 
     | 
    
         
            +
                      </header>
         
     | 
| 
      
 17 
     | 
    
         
            +
                      <figure>
         
     | 
| 
      
 18 
     | 
    
         
            +
                        <img />
         
     | 
| 
      
 19 
     | 
    
         
            +
                      </figure>
         
     | 
| 
      
 20 
     | 
    
         
            +
                    </div>
         
     | 
| 
      
 21 
     | 
    
         
            +
                  </div>
         
     | 
| 
      
 22 
     | 
    
         
            +
                  ".toHTML()
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              select: (node) =>
         
     | 
| 
      
 25 
     | 
    
         
            +
                @selection = @getSelection()
         
     | 
| 
      
 26 
     | 
    
         
            +
                @input.click()
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              confirm: (node, event) =>
         
     | 
| 
      
 29 
     | 
    
         
            +
                @pause()
         
     | 
| 
      
 30 
     | 
    
         
            +
                @overlay = @template()
         
     | 
| 
      
 31 
     | 
    
         
            +
                @editor().element().appendChild(@overlay)
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                @image(event, @preview.bind(this, @overlay.querySelector('img')))
         
     | 
| 
      
 34 
     | 
    
         
            +
                @overlay.querySelector('button[data-action=cancel]').addEventListener('click', @cancel)
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              preview: (node, event) ->
         
     | 
| 
      
 37 
     | 
    
         
            +
                node.src = event.target.result
         
     | 
| 
      
 38 
     | 
    
         
            +
                @overlay.querySelector('button[data-action=upload]').addEventListener('click', @upload)
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              image: (event, callback) ->
         
     | 
| 
      
 41 
     | 
    
         
            +
                @file = event.target.files[0]
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                reader = new FileReader()
         
     | 
| 
      
 44 
     | 
    
         
            +
                reader.addEventListener('load', callback)
         
     | 
| 
      
 45 
     | 
    
         
            +
                reader.addEventListener('error', @failed)
         
     | 
| 
      
 46 
     | 
    
         
            +
                reader.readAsDataURL(@file)
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
              cancel: =>
         
     | 
| 
      
 49 
     | 
    
         
            +
                @overlay.remove()
         
     | 
| 
      
 50 
     | 
    
         
            +
                @resume()
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
              complete: (name) ->
         
     | 
| 
      
 53 
     | 
    
         
            +
                figcaption = @node.querySelector('figcaption')
         
     | 
| 
      
 54 
     | 
    
         
            +
                url = figcaption.childNodes[figcaption.childNodes.length - 1]
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                @overlay.addEventListener 'transitionend', =>
         
     | 
| 
      
 57 
     | 
    
         
            +
                  @overlay.remove()
         
     | 
| 
      
 58 
     | 
    
         
            +
                  @resume =>
         
     | 
| 
      
 59 
     | 
    
         
            +
                    figcaption.replaceChild(document.createTextNode("(#{window.AWS.bucket}/#{name})"), url)
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                @overlay.classList.add('fade')
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
              failed: (e) =>
         
     | 
| 
      
 64 
     | 
    
         
            +
                dialog = @overlay.querySelector('#WrittenDialog')
         
     | 
| 
      
 65 
     | 
    
         
            +
                dialog.classList.add 'failed'
         
     | 
| 
      
 66 
     | 
    
         
            +
                dialog.querySelector('h3').textContent = "Failed"
         
     | 
| 
      
 67 
     | 
    
         
            +
                dialog.querySelector('figure').remove()
         
     | 
| 
      
 68 
     | 
    
         
            +
                dialog.appendChild("
         
     | 
| 
      
 69 
     | 
    
         
            +
                  <section>
         
     | 
| 
      
 70 
     | 
    
         
            +
                    <p>An error occured while trying to process your image.</p>
         
     | 
| 
      
 71 
     | 
    
         
            +
                    <button>Close</button>
         
     | 
| 
      
 72 
     | 
    
         
            +
                  </section>
         
     | 
| 
      
 73 
     | 
    
         
            +
                ".toHTML())
         
     | 
| 
      
 74 
     | 
    
         
            +
                dialog.querySelector('button').addEventListener('click', @cancel)
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
              upload: (e) =>
         
     | 
| 
      
 77 
     | 
    
         
            +
                @overlay.querySelector('h3').textContent = "Uploading"
         
     | 
| 
      
 78 
     | 
    
         
            +
                Array.prototype.slice.call(@overlay.querySelectorAll('button')).forEach (button) ->
         
     | 
| 
      
 79 
     | 
    
         
            +
                  button.remove()
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                name = @name(@file.name)
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                form = new FormData()
         
     | 
| 
      
 84 
     | 
    
         
            +
                form.append('key', name)
         
     | 
| 
      
 85 
     | 
    
         
            +
                form.append('acl', 'private')
         
     | 
| 
      
 86 
     | 
    
         
            +
                form.append("AWSAccessKeyId", window.AWS.accessKey)
         
     | 
| 
      
 87 
     | 
    
         
            +
                form.append('policy', window.AWS.policy)
         
     | 
| 
      
 88 
     | 
    
         
            +
                form.append('signature', window.AWS.signature)
         
     | 
| 
      
 89 
     | 
    
         
            +
                form.append('Content-Type', @file.type)
         
     | 
| 
      
 90 
     | 
    
         
            +
                form.append('file', @file, name)
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                xhr = new XMLHttpRequest()
         
     | 
| 
      
 93 
     | 
    
         
            +
                xhr.addEventListener('load', @complete.bind(this, name))
         
     | 
| 
      
 94 
     | 
    
         
            +
                xhr.addEventListener('error', @failed)
         
     | 
| 
      
 95 
     | 
    
         
            +
                xhr.upload.addEventListener('progress', @progress)
         
     | 
| 
      
 96 
     | 
    
         
            +
                xhr.open('POST', window.AWS.bucket)
         
     | 
| 
      
 97 
     | 
    
         
            +
                xhr.send(form)
         
     | 
| 
      
 98 
     | 
    
         
            +
                xhr
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
              progress: (e) =>
         
     | 
| 
      
 102 
     | 
    
         
            +
                value = e.loaded / e.total * 100
         
     | 
| 
      
 103 
     | 
    
         
            +
                @overlay.querySelector('div.progress').style.width = "#{value}%"
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
              name: (filename) ->
         
     | 
| 
      
 106 
     | 
    
         
            +
                hash = 0
         
     | 
| 
      
 107 
     | 
    
         
            +
                for i in [0..filename.length - 1]
         
     | 
| 
      
 108 
     | 
    
         
            +
                  hash += filename.charCodeAt(i) ^ hash
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                hash.toString('16')
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
            Written.Attachments.bind 'figure', Image
         
     | 
| 
         @@ -0,0 +1,37 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            @Written.Attachments = new class Attachments
         
     | 
| 
      
 2 
     | 
    
         
            +
              constructor: ->
         
     | 
| 
      
 3 
     | 
    
         
            +
                @attachments = {}
         
     | 
| 
      
 4 
     | 
    
         
            +
                @nodes = []
         
     | 
| 
      
 5 
     | 
    
         
            +
                
         
     | 
| 
      
 6 
     | 
    
         
            +
              bind: (nodeName, attachment) ->
         
     | 
| 
      
 7 
     | 
    
         
            +
                @attachments[nodeName] = attachment
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              attach: (editor) =>
         
     | 
| 
      
 10 
     | 
    
         
            +
                for name, attachment of @attachments
         
     | 
| 
      
 11 
     | 
    
         
            +
                  nodes = editor.element().querySelectorAll(name)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  for node in nodes
         
     | 
| 
      
 13 
     | 
    
         
            +
                    if @nodes.includes(node)
         
     | 
| 
      
 14 
     | 
    
         
            +
                      continue
         
     | 
| 
      
 15 
     | 
    
         
            +
                    
         
     | 
| 
      
 16 
     | 
    
         
            +
                    attachment = new attachment(node)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    attachment.editor(editor)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @nodes.push(node)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  
         
     | 
| 
      
 20 
     | 
    
         
            +
                  
         
     | 
| 
      
 21 
     | 
    
         
            +
            @Written.Attachments.Base = class Attachment
         
     | 
| 
      
 22 
     | 
    
         
            +
              editor: (editor) ->
         
     | 
| 
      
 23 
     | 
    
         
            +
                @editor = ->
         
     | 
| 
      
 24 
     | 
    
         
            +
                  editor
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                @editor()
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              pause: =>
         
     | 
| 
      
 29 
     | 
    
         
            +
                @editor().observer.pause()
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              resume: (callback) =>
         
     | 
| 
      
 32 
     | 
    
         
            +
                @editor().observer.resume()
         
     | 
| 
      
 33 
     | 
    
         
            +
                if callback?
         
     | 
| 
      
 34 
     | 
    
         
            +
                  callback()
         
     | 
| 
      
 35 
     | 
    
         
            +
                
         
     | 
| 
      
 36 
     | 
    
         
            +
              getSelection: ->
         
     | 
| 
      
 37 
     | 
    
         
            +
                window.getSelection()
         
     | 
| 
         @@ -38,7 +38,8 @@ class @Written 
     | 
|
| 
       38 
38 
     | 
    
         
             
                document.cursor = cursor
         
     | 
| 
       39 
39 
     | 
    
         | 
| 
       40 
40 
     | 
    
         | 
| 
       41 
     | 
    
         
            -
                 
     | 
| 
      
 41 
     | 
    
         
            +
                @render(document)
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
       42 
43 
     | 
    
         
             
                document.cursor.focus(document.toString().length)
         
     | 
| 
       43 
44 
     | 
    
         | 
| 
       44 
45 
     | 
    
         
             
                @history = new Written.History(document)
         
     | 
| 
         @@ -54,7 +55,7 @@ class @Written 
     | 
|
| 
       54 
55 
     | 
    
         
             
              changeTo: (text) =>
         
     | 
| 
       55 
56 
     | 
    
         
             
                document = new Written.Document(text, @parsers)
         
     | 
| 
       56 
57 
     | 
    
         
             
                @history.push(document)
         
     | 
| 
       57 
     | 
    
         
            -
                 
     | 
| 
      
 58 
     | 
    
         
            +
                @render(document)
         
     | 
| 
       58 
59 
     | 
    
         | 
| 
       59 
60 
     | 
    
         
             
              changed: (e) =>
         
     | 
| 
       60 
61 
     | 
    
         
             
                oldDocument = @history.current
         
     | 
| 
         @@ -63,33 +64,14 @@ class @Written 
     | 
|
| 
       63 
64 
     | 
    
         
             
                if @element().children.length > 0 && oldDocument.toString().localeCompare(newDocument.toString()) == 0
         
     | 
| 
       64 
65 
     | 
    
         
             
                  return
         
     | 
| 
       65 
66 
     | 
    
         | 
| 
       66 
     | 
    
         
            -
                newDocument.applyTo(@element())
         
     | 
| 
       67 
67 
     | 
    
         
             
                @history.push(newDocument)
         
     | 
| 
      
 68 
     | 
    
         
            +
                @render(newDocument)
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
       68 
70 
     | 
    
         
             
                @dispatch('written:changed', document: newDocument)
         
     | 
| 
       69 
71 
     | 
    
         | 
| 
       70 
72 
     | 
    
         
             
              cursor: =>
         
     | 
| 
       71 
73 
     | 
    
         
             
                @history.current.cursor = new Written.Cursor(@element(), window.getSelection())
         
     | 
| 
       72 
74 
     | 
    
         | 
| 
       73 
     | 
    
         
            -
              update: (document) =>
         
     | 
| 
       74 
     | 
    
         
            -
                elements = Array.prototype.slice.call(@element().children)
         
     | 
| 
       75 
     | 
    
         
            -
             
     | 
| 
       76 
     | 
    
         
            -
                for block, index in document.blocks
         
     | 
| 
       77 
     | 
    
         
            -
                  node = block.markdown()
         
     | 
| 
       78 
     | 
    
         
            -
                  element = elements[index]
         
     | 
| 
       79 
     | 
    
         
            -
             
     | 
| 
       80 
     | 
    
         
            -
                  if element?
         
     | 
| 
       81 
     | 
    
         
            -
                    if !block.identical(element, node)
         
     | 
| 
       82 
     | 
    
         
            -
                      @element().replaceChild(node, element)
         
     | 
| 
       83 
     | 
    
         
            -
                  else
         
     | 
| 
       84 
     | 
    
         
            -
                    @element().appendChild(node)
         
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
       86 
     | 
    
         
            -
                if elements.length > index
         
     | 
| 
       87 
     | 
    
         
            -
                  for i in [index..elements.length - 1]
         
     | 
| 
       88 
     | 
    
         
            -
                    elements[i].remove()
         
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
                document.cursor.focus()
         
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
       92 
     | 
    
         
            -
             
     | 
| 
       93 
75 
     | 
    
         
             
              linefeed: (e) =>
         
     | 
| 
       94 
76 
     | 
    
         
             
                return unless e.which == 13
         
     | 
| 
       95 
77 
     | 
    
         
             
                e.preventDefault()
         
     | 
| 
         @@ -117,10 +99,14 @@ class @Written 
     | 
|
| 
       117 
99 
     | 
    
         
             
                  if cursor.offset < document.toString().length
         
     | 
| 
       118 
100 
     | 
    
         
             
                    cursor.offset += 1
         
     | 
| 
       119 
101 
     | 
    
         | 
| 
       120 
     | 
    
         
            -
                   
     | 
| 
      
 102 
     | 
    
         
            +
                  @render(document)
         
     | 
| 
       121 
103 
     | 
    
         
             
                  @history.push(document)
         
     | 
| 
       122 
104 
     | 
    
         | 
| 
       123 
105 
     | 
    
         | 
| 
      
 106 
     | 
    
         
            +
              render: (document) =>
         
     | 
| 
      
 107 
     | 
    
         
            +
                document.applyTo(@element())
         
     | 
| 
      
 108 
     | 
    
         
            +
                Written.Attachments.attach(this)
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
       124 
110 
     | 
    
         
             
              undo: (e) =>
         
     | 
| 
       125 
111 
     | 
    
         
             
                if e.code == 'KeyZ' && e.metaKey && !e.shiftKey
         
     | 
| 
       126 
112 
     | 
    
         
             
                  e.preventDefault()
         
     | 
| 
         @@ -130,7 +116,7 @@ class @Written 
     | 
|
| 
       130 
116 
     | 
    
         | 
| 
       131 
117 
     | 
    
         
             
                if document = @history.previous()
         
     | 
| 
       132 
118 
     | 
    
         
             
                  @history.current = document
         
     | 
| 
       133 
     | 
    
         
            -
                   
     | 
| 
      
 119 
     | 
    
         
            +
                  @render(document)
         
     | 
| 
       134 
120 
     | 
    
         | 
| 
       135 
121 
     | 
    
         
             
              redo: (e) =>
         
     | 
| 
       136 
122 
     | 
    
         
             
                if e.code == 'KeyZ' && e.metaKey && e.shiftKey
         
     | 
| 
         @@ -141,7 +127,7 @@ class @Written 
     | 
|
| 
       141 
127 
     | 
    
         | 
| 
       142 
128 
     | 
    
         
             
                if document = @history.next()
         
     | 
| 
       143 
129 
     | 
    
         
             
                  @history.current = document
         
     | 
| 
       144 
     | 
    
         
            -
                  @history.current 
     | 
| 
      
 130 
     | 
    
         
            +
                  @render(@history.current)
         
     | 
| 
       145 
131 
     | 
    
         | 
| 
       146 
132 
     | 
    
         
             
              toString: =>
         
     | 
| 
       147 
133 
     | 
    
         
             
                texts = []
         
     | 
| 
         @@ -18,7 +18,7 @@ class Image 
     | 
|
| 
       18 
18 
     | 
    
         
             
                rendered.querySelector('img').src == img.src
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
       20 
20 
     | 
    
         
             
              markdown: =>
         
     | 
| 
       21 
     | 
    
         
            -
                figure = "<figure><div contenteditable='false'>< 
     | 
| 
      
 21 
     | 
    
         
            +
                figure = "<figure><div contenteditable='false'><img/></div><figcaption /></figure>".toHTML()
         
     | 
| 
       22 
22 
     | 
    
         
             
                caption = figure.querySelector('figcaption')
         
     | 
| 
       23 
23 
     | 
    
         
             
                container = figure.querySelector('div')
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
         @@ -1,4 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            [data-editor="written"] {
         
     | 
| 
      
 2 
     | 
    
         
            +
              position: relative;
         
     | 
| 
       2 
3 
     | 
    
         
             
              white-space: pre-wrap;
         
     | 
| 
       3 
4 
     | 
    
         
             
              padding: 1em;
         
     | 
| 
       4 
5 
     | 
    
         | 
| 
         @@ -29,23 +30,9 @@ 
     | 
|
| 
       29 
30 
     | 
    
         
             
            [data-editor="written"] figure > div {
         
     | 
| 
       30 
31 
     | 
    
         
             
              position: relative;
         
     | 
| 
       31 
32 
     | 
    
         
             
              display: flex;
         
     | 
| 
      
 33 
     | 
    
         
            +
              align-items: center;
         
     | 
| 
      
 34 
     | 
    
         
            +
              justify-content: center;
         
     | 
| 
       32 
35 
     | 
    
         
             
              padding: 4px;
         
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
              &[data-uploadable] {
         
     | 
| 
       35 
     | 
    
         
            -
                cursor: pointer;
         
     | 
| 
       36 
     | 
    
         
            -
              }
         
     | 
| 
       37 
     | 
    
         
            -
            }
         
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
            [data-editor="written"] figure > div > div.progress {
         
     | 
| 
       40 
     | 
    
         
            -
              position: absolute;
         
     | 
| 
       41 
     | 
    
         
            -
              top: 0;
         
     | 
| 
       42 
     | 
    
         
            -
              left: 0;
         
     | 
| 
       43 
     | 
    
         
            -
              transition: width 0.24s ease;
         
     | 
| 
       44 
     | 
    
         
            -
            }
         
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
       46 
     | 
    
         
            -
            [data-editor="written"] figure[data-status='uploading'] div.progress {
         
     | 
| 
       47 
     | 
    
         
            -
              background-color: green;
         
     | 
| 
       48 
     | 
    
         
            -
              height: 1px;
         
     | 
| 
       49 
36 
     | 
    
         
             
            }
         
     | 
| 
       50 
37 
     | 
    
         | 
| 
       51 
38 
     | 
    
         
             
            [data-editor="written"] figure img {
         
     | 
| 
         @@ -99,3 +86,116 @@ 
     | 
|
| 
       99 
86 
     | 
    
         
             
              display: block;
         
     | 
| 
       100 
87 
     | 
    
         
             
              white-space: pre-line;
         
     | 
| 
       101 
88 
     | 
    
         
             
            }
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
            [data-editor="written"] > #WrittenOverlay {
         
     | 
| 
      
 91 
     | 
    
         
            +
              position: absolute;
         
     | 
| 
      
 92 
     | 
    
         
            +
              top: 0;
         
     | 
| 
      
 93 
     | 
    
         
            +
              left: 0;
         
     | 
| 
      
 94 
     | 
    
         
            +
              right: 0;
         
     | 
| 
      
 95 
     | 
    
         
            +
              bottom: 0;
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
              display: flex;
         
     | 
| 
      
 98 
     | 
    
         
            +
              align-items: center;
         
     | 
| 
      
 99 
     | 
    
         
            +
              justify-content: center;
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
              background-color: rgba(230, 230, 230, 0.8);
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
              transition: opacity 0.2s ease-out;
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
              &.fade {
         
     | 
| 
      
 106 
     | 
    
         
            +
                opacity: 0;
         
     | 
| 
      
 107 
     | 
    
         
            +
              }
         
     | 
| 
      
 108 
     | 
    
         
            +
            }
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
            [data-editor="written"] > #WrittenOverlay > #WrittenDialog {
         
     | 
| 
      
 111 
     | 
    
         
            +
              display: flex;
         
     | 
| 
      
 112 
     | 
    
         
            +
              flex-direction: column;
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
              min-width: 300px;
         
     | 
| 
      
 115 
     | 
    
         
            +
              width: 100vw;
         
     | 
| 
      
 116 
     | 
    
         
            +
              max-width: 700px;
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
              max-height: 800px;
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
              background: white;
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
              box-shadow: 0 0 3px rgba(150, 150, 150, 0.5);
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
              overflow: hidden;
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
              button {
         
     | 
| 
      
 127 
     | 
    
         
            +
                outline: none;
         
     | 
| 
      
 128 
     | 
    
         
            +
              }
         
     | 
| 
      
 129 
     | 
    
         
            +
            }
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
            [data-editor="written"] > #WrittenOverlay > #WrittenDialog figure {
         
     | 
| 
      
 132 
     | 
    
         
            +
              img {
         
     | 
| 
      
 133 
     | 
    
         
            +
                border: none;
         
     | 
| 
      
 134 
     | 
    
         
            +
              }
         
     | 
| 
      
 135 
     | 
    
         
            +
            }
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
            [data-editor="written"] > #WrittenOverlay > #WrittenDialog div.progress {
         
     | 
| 
      
 138 
     | 
    
         
            +
              position: absolute;
         
     | 
| 
      
 139 
     | 
    
         
            +
              top: 0;
         
     | 
| 
      
 140 
     | 
    
         
            +
              left: 0;
         
     | 
| 
      
 141 
     | 
    
         
            +
              bottom: 0;
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
              transition: width 0.2s ease;
         
     | 
| 
      
 144 
     | 
    
         
            +
              background-color: #2B99E8;
         
     | 
| 
      
 145 
     | 
    
         
            +
              box-shadow: 0 0 2px rgba(0, 147, 255, 0.41);
         
     | 
| 
      
 146 
     | 
    
         
            +
            }
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
            [data-editor="written"] > #WrittenOverlay > #WrittenDialog header {
         
     | 
| 
      
 149 
     | 
    
         
            +
              position: relative;
         
     | 
| 
      
 150 
     | 
    
         
            +
              display: flex;
         
     | 
| 
      
 151 
     | 
    
         
            +
              justify-content: space-between;
         
     | 
| 
      
 152 
     | 
    
         
            +
              border-bottom: 1px solid rgba(200, 200, 200, 200);
         
     | 
| 
      
 153 
     | 
    
         
            +
              box-shadow: 0 2px whitesmoke;
         
     | 
| 
      
 154 
     | 
    
         
            +
              background-color: whitesmoke;
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
              h3 {
         
     | 
| 
      
 157 
     | 
    
         
            +
                flex: 1;
         
     | 
| 
      
 158 
     | 
    
         
            +
                margin: 0;
         
     | 
| 
      
 159 
     | 
    
         
            +
                text-align: center;
         
     | 
| 
      
 160 
     | 
    
         
            +
                z-index: 1;
         
     | 
| 
      
 161 
     | 
    
         
            +
                line-height: 2em;
         
     | 
| 
      
 162 
     | 
    
         
            +
              }
         
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
      
 164 
     | 
    
         
            +
              button {
         
     | 
| 
      
 165 
     | 
    
         
            +
                border: none;
         
     | 
| 
      
 166 
     | 
    
         
            +
                text-transform: uppercase;
         
     | 
| 
      
 167 
     | 
    
         
            +
                color: white;
         
     | 
| 
      
 168 
     | 
    
         
            +
                width: 100px;
         
     | 
| 
      
 169 
     | 
    
         
            +
             
     | 
| 
      
 170 
     | 
    
         
            +
                &[data-action=cancel] {
         
     | 
| 
      
 171 
     | 
    
         
            +
                  background-color: red;
         
     | 
| 
      
 172 
     | 
    
         
            +
                }
         
     | 
| 
      
 173 
     | 
    
         
            +
             
     | 
| 
      
 174 
     | 
    
         
            +
                &[data-action=upload] {
         
     | 
| 
      
 175 
     | 
    
         
            +
                  background-color: green;
         
     | 
| 
      
 176 
     | 
    
         
            +
                }
         
     | 
| 
      
 177 
     | 
    
         
            +
              }
         
     | 
| 
      
 178 
     | 
    
         
            +
             
     | 
| 
      
 179 
     | 
    
         
            +
            }
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
            [data-editor="written"] > #WrittenOverlay > #WrittenDialog.failed header {
         
     | 
| 
      
 182 
     | 
    
         
            +
              background-color: #CA1414;
         
     | 
| 
      
 183 
     | 
    
         
            +
              color: white;
         
     | 
| 
      
 184 
     | 
    
         
            +
            }
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
            [data-editor="written"] > #WrittenOverlay > #WrittenDialog.failed section {
         
     | 
| 
      
 187 
     | 
    
         
            +
              display: flex;
         
     | 
| 
      
 188 
     | 
    
         
            +
              flex-direction: column;
         
     | 
| 
      
 189 
     | 
    
         
            +
              padding: 12px;
         
     | 
| 
      
 190 
     | 
    
         
            +
              text-align: center;
         
     | 
| 
      
 191 
     | 
    
         
            +
            }
         
     | 
| 
      
 192 
     | 
    
         
            +
             
     | 
| 
      
 193 
     | 
    
         
            +
            [data-editor="written"] > #WrittenOverlay > #WrittenDialog.failed button {
         
     | 
| 
      
 194 
     | 
    
         
            +
              background-color: #CA1414;
         
     | 
| 
      
 195 
     | 
    
         
            +
              text-align: center;
         
     | 
| 
      
 196 
     | 
    
         
            +
              color: white;
         
     | 
| 
      
 197 
     | 
    
         
            +
              width: 80%;
         
     | 
| 
      
 198 
     | 
    
         
            +
              margin: 12px auto;
         
     | 
| 
      
 199 
     | 
    
         
            +
              padding: 4px;
         
     | 
| 
      
 200 
     | 
    
         
            +
              border: none;
         
     | 
| 
      
 201 
     | 
    
         
            +
            }
         
     | 
    
        data/lib/written/version.rb
    CHANGED
    
    
| 
         @@ -3,12 +3,12 @@ 
     | 
|
| 
       3 
3 
     | 
    
         
             
            1. this is a list
         
     | 
| 
       4 
4 
     | 
    
         
             
            2. this is another list
         
     | 
| 
       5 
5 
     | 
    
         
             
            3. this is another list
         
     | 
| 
       6 
     | 
    
         
            -
            - this is  
     | 
| 
       7 
     | 
    
         
            -
            3. this is [a](http://google.com)  
     | 
| 
       8 
     | 
    
         
            -
            test *boo* and them *some* or  
     | 
| 
      
 6 
     | 
    
         
            +
            - this is *a* list
         
     | 
| 
      
 7 
     | 
    
         
            +
            3. this is [a](http://google.com) _list_. It's special, isn't *it*?
         
     | 
| 
      
 8 
     | 
    
         
            +
            test *boo* and them *some* or *some!!* a
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
            
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
            ~~~javascript
         
     | 
| 
       14 
14 
     | 
    
         
             
            var test = "hello"
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: written
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.2.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Pier-Olivier Thibault
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2016-05- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2016-05-20 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies: []
         
     | 
| 
       13 
13 
     | 
    
         
             
            description: Written is a rich Markdown editor for the web.
         
     | 
| 
       14 
14 
     | 
    
         
             
            email: pothibo@gmail.com
         
     | 
| 
         @@ -25,6 +25,8 @@ files: 
     | 
|
| 
       25 
25 
     | 
    
         
             
            - lib/written.rb
         
     | 
| 
       26 
26 
     | 
    
         
             
            - lib/written/app/assets/images/written/placeholder.png
         
     | 
| 
       27 
27 
     | 
    
         
             
            - lib/written/app/assets/javascripts/written.coffee
         
     | 
| 
      
 28 
     | 
    
         
            +
            - lib/written/app/assets/javascripts/written/attachments/image.coffee
         
     | 
| 
      
 29 
     | 
    
         
            +
            - lib/written/app/assets/javascripts/written/core/attachments.coffee
         
     | 
| 
       28 
30 
     | 
    
         
             
            - lib/written/app/assets/javascripts/written/core/content.coffee
         
     | 
| 
       29 
31 
     | 
    
         
             
            - lib/written/app/assets/javascripts/written/core/cursor.coffee
         
     | 
| 
       30 
32 
     | 
    
         
             
            - lib/written/app/assets/javascripts/written/core/document.coffee
         
     | 
| 
         @@ -43,7 +45,6 @@ files: 
     | 
|
| 
       43 
45 
     | 
    
         
             
            - lib/written/app/assets/javascripts/written/parsers/inline/link.coffee
         
     | 
| 
       44 
46 
     | 
    
         
             
            - lib/written/app/assets/javascripts/written/parsers/inline/strong.coffee
         
     | 
| 
       45 
47 
     | 
    
         
             
            - lib/written/app/assets/javascripts/written/parsers/parsers.coffee
         
     | 
| 
       46 
     | 
    
         
            -
            - lib/written/app/assets/javascripts/written/uploaders/aws.coffee
         
     | 
| 
       47 
48 
     | 
    
         
             
            - lib/written/app/assets/stylesheets/written.scss
         
     | 
| 
       48 
49 
     | 
    
         
             
            - lib/written/railtie.rb
         
     | 
| 
       49 
50 
     | 
    
         
             
            - lib/written/version.rb
         
     | 
| 
         @@ -1,125 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            class Written.Uploaders.AWS
         
     | 
| 
       2 
     | 
    
         
            -
              constructor: (settings) ->
         
     | 
| 
       3 
     | 
    
         
            -
                Images.settings = settings
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
              initialize: (node, observer) =>
         
     | 
| 
       6 
     | 
    
         
            -
                img = node.querySelector('img')
         
     | 
| 
       7 
     | 
    
         
            -
                container = node.querySelector('div')
         
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
                node.dataset.uploadable = true
         
     | 
| 
       10 
     | 
    
         
            -
                node.addEventListener 'written:uploader:error', @error, true
         
     | 
| 
       11 
     | 
    
         
            -
                node.addEventListener 'written:uploader:uploading', @progress, true
         
     | 
| 
       12 
     | 
    
         
            -
                node.addEventListener 'written:uploader:completed', @uploaded, true
         
     | 
| 
       13 
     | 
    
         
            -
                node.addEventListener 'change', @input.bind(this, node, observer), true
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
                container.addEventListener 'click', @open.bind(this, node), true
         
     | 
| 
       16 
     | 
    
         
            -
                image = Images.get(img.dataset.image)
         
     | 
| 
       17 
     | 
    
         
            -
                if image
         
     | 
| 
       18 
     | 
    
         
            -
                  image.node = node
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
              open: (node, e) =>
         
     | 
| 
       21 
     | 
    
         
            -
                node.querySelector('input')?.click()
         
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
              uploaded: (e) =>
         
     | 
| 
       24 
     | 
    
         
            -
                caption = e.target.querySelector('figcaption')
         
     | 
| 
       25 
     | 
    
         
            -
                img = e.target.querySelector('img')
         
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
                text = caption.childNodes[caption.childNodes.length - 1]
         
     | 
| 
       28 
     | 
    
         
            -
                text.textContent = "(#{e.image.url})"
         
     | 
| 
       29 
     | 
    
         
            -
                img.src = e.image.url
         
     | 
| 
       30 
     | 
    
         
            -
                selection = window.getSelection()
         
     | 
| 
       31 
     | 
    
         
            -
                selection.removeAllRanges()
         
     | 
| 
       32 
     | 
    
         
            -
                range = document.createRange()
         
     | 
| 
       33 
     | 
    
         
            -
                range.setEnd(text, text.textContent.length - 1)
         
     | 
| 
       34 
     | 
    
         
            -
                selection.addRange(range)
         
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
              error: (e) =>
         
     | 
| 
       37 
     | 
    
         
            -
                console.log(e)
         
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
              input: (node, history, e) =>
         
     | 
| 
       40 
     | 
    
         
            -
                file = e.target.files[0]
         
     | 
| 
       41 
     | 
    
         
            -
                @process(file, node, history)
         
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
              process: (file, node) =>
         
     | 
| 
       44 
     | 
    
         
            -
                caption = node.querySelector('figcaption')
         
     | 
| 
       45 
     | 
    
         
            -
                progress = node.querySelector('div.progress')
         
     | 
| 
       46 
     | 
    
         
            -
                filename = [Images.settings.namespace, @hash(file.name)].join('/')
         
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
     | 
    
         
            -
                image = Images.get(filename)
         
     | 
| 
       49 
     | 
    
         
            -
                if !image
         
     | 
| 
       50 
     | 
    
         
            -
                  image = Images.upload(filename, file)
         
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
                image.node = node
         
     | 
| 
       53 
     | 
    
         
            -
                progress.style.width = image.progress
         
     | 
| 
       54 
     | 
    
         
            -
                node.dataset.status = image.status
         
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
     | 
    
         
            -
                text = caption.childNodes[caption.childNodes.length - 1]
         
     | 
| 
       57 
     | 
    
         
            -
                text.textContent = "(#{filename})"
         
     | 
| 
       58 
     | 
    
         
            -
                selection = window.getSelection()
         
     | 
| 
       59 
     | 
    
         
            -
                selection.removeAllRanges()
         
     | 
| 
       60 
     | 
    
         
            -
                range = document.createRange()
         
     | 
| 
       61 
     | 
    
         
            -
                range.setEnd(text, text.textContent.length - 1)
         
     | 
| 
       62 
     | 
    
         
            -
                selection.addRange(range)
         
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
              hash: (filename) ->
         
     | 
| 
       65 
     | 
    
         
            -
                hash = 0
         
     | 
| 
       66 
     | 
    
         
            -
                for i in [0..filename.length - 1]
         
     | 
| 
       67 
     | 
    
         
            -
                  hash += filename.charCodeAt(i) ^ hash
         
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
     | 
    
         
            -
                hash.toString('16')
         
     | 
| 
       70 
     | 
    
         
            -
             
     | 
| 
       71 
     | 
    
         
            -
            Images = new class
         
     | 
| 
       72 
     | 
    
         
            -
              constructor: ->
         
     | 
| 
       73 
     | 
    
         
            -
                @cache = {}
         
     | 
| 
       74 
     | 
    
         
            -
             
     | 
| 
       75 
     | 
    
         
            -
              failed: (image, event) ->
         
     | 
| 
       76 
     | 
    
         
            -
                image.status = 'failed'
         
     | 
| 
       77 
     | 
    
         
            -
                
         
     | 
| 
       78 
     | 
    
         
            -
                if image.node?
         
     | 
| 
       79 
     | 
    
         
            -
                  event = new CustomEvent('written:uploader:error', {bubbles: true})
         
     | 
| 
       80 
     | 
    
         
            -
                  event.image = image
         
     | 
| 
       81 
     | 
    
         
            -
                  image.node.dispatchEvent(event)
         
     | 
| 
       82 
     | 
    
         
            -
             
     | 
| 
       83 
     | 
    
         
            -
              update: (image, event) ->
         
     | 
| 
       84 
     | 
    
         
            -
                image.status = 'completed'
         
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
       86 
     | 
    
         
            -
                if image.node?
         
     | 
| 
       87 
     | 
    
         
            -
                  event = new CustomEvent('written:uploader:completed', {bubbles: true})
         
     | 
| 
       88 
     | 
    
         
            -
                  event.image = image
         
     | 
| 
       89 
     | 
    
         
            -
                  image.node.dispatchEvent(event)
         
     | 
| 
       90 
     | 
    
         
            -
             
     | 
| 
       91 
     | 
    
         
            -
              upload: (name, file) =>
         
     | 
| 
       92 
     | 
    
         
            -
                image = {
         
     | 
| 
       93 
     | 
    
         
            -
                  url: "#{@settings.url}/#{name}"
         
     | 
| 
       94 
     | 
    
         
            -
                  name: name
         
     | 
| 
       95 
     | 
    
         
            -
                  status: 'uploading'
         
     | 
| 
       96 
     | 
    
         
            -
                  progress: 0
         
     | 
| 
       97 
     | 
    
         
            -
                }
         
     | 
| 
       98 
     | 
    
         
            -
             
     | 
| 
       99 
     | 
    
         
            -
                form = new FormData()
         
     | 
| 
       100 
     | 
    
         
            -
                form.append('key', name)
         
     | 
| 
       101 
     | 
    
         
            -
                form.append('acl', 'private')
         
     | 
| 
       102 
     | 
    
         
            -
                form.append("AWSAccessKeyId", @settings.accessKey)
         
     | 
| 
       103 
     | 
    
         
            -
                form.append('policy', @settings.policy)
         
     | 
| 
       104 
     | 
    
         
            -
                form.append('signature', @settings.signature)
         
     | 
| 
       105 
     | 
    
         
            -
                form.append('Content-Type', file.type)
         
     | 
| 
       106 
     | 
    
         
            -
                form.append('file', file, name)
         
     | 
| 
       107 
     | 
    
         
            -
             
     | 
| 
       108 
     | 
    
         
            -
             
     | 
| 
       109 
     | 
    
         
            -
                image.xhr = @send(form, @settings.url)
         
     | 
| 
       110 
     | 
    
         
            -
                image.xhr.addEventListener('load', @update.bind(this, image))
         
     | 
| 
       111 
     | 
    
         
            -
                image.xhr.addEventListener('error', @failed.bind(this, image))
         
     | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
       113 
     | 
    
         
            -
                @cache[image.name] = image
         
     | 
| 
       114 
     | 
    
         
            -
             
     | 
| 
       115 
     | 
    
         
            -
             
     | 
| 
       116 
     | 
    
         
            -
              get: (name) ->
         
     | 
| 
       117 
     | 
    
         
            -
                @cache[name]
         
     | 
| 
       118 
     | 
    
         
            -
             
     | 
| 
       119 
     | 
    
         
            -
              send: (form, url) =>
         
     | 
| 
       120 
     | 
    
         
            -
                xhr = new XMLHttpRequest()
         
     | 
| 
       121 
     | 
    
         
            -
                xhr.open('POST', url)
         
     | 
| 
       122 
     | 
    
         
            -
                xhr.send(form)
         
     | 
| 
       123 
     | 
    
         
            -
                xhr
         
     | 
| 
       124 
     | 
    
         
            -
             
     | 
| 
       125 
     | 
    
         
            -
             
     |