<commit_before>class Written.Uploaders.AWS
  constructor: (settings) ->
    Images.settings = settings

  initialize: (node, observer) =>
    img = node.querySelector('img')
    container = node.querySelector('div')

    node.dataset.uploadable = true
    node.addEventListener 'written:uploader:error', @error, true
    node.addEventListener 'written:uploader:uploading', @progress, true
    node.addEventListener 'written:uploader:completed', @uploaded, true
    node.addEventListener 'change', @input.bind(this, node, observer), true

    container.addEventListener 'click', @open.bind(this, node), true
    image = Images.get(img.dataset.image)
    if image
      image.node = node

  open: (node, e) =>
    node.querySelector('input')?.click()

  uploaded: (e) =>
    caption = e.target.querySelector('figcaption')
    img = e.target.querySelector('img')

    text = caption.childNodes[caption.childNodes.length - 1]
    text.textContent = "(#{e.image.url})"
    img.src = e.image.url
    selection = window.getSelection()
    selection.removeAllRanges()
    range = document.createRange()
    range.setEnd(text, text.textContent.length - 1)
    selection.addRange(range)

  error: (e) =>
    console.log(e)

  input: (node, history, e) =>
    file = e.target.files[0]
    @process(file, node, history)

  process: (file, node) =>
    caption = node.querySelector('figcaption')
    progress = node.querySelector('div.progress')
    filename = @hash(file.name)

    image = Images.get(filename)
    if !image
      image = Images.upload(filename, file)

    image.node = node
    progress.style.width = image.progress
    node.dataset.status = image.status

    text = caption.childNodes[caption.childNodes.length - 1]
    text.textContent = "(#{filename})"
    selection = window.getSelection()
    selection.removeAllRanges()
    range = document.createRange()
    range.setEnd(text, text.textContent.length - 1)
    selection.addRange(range)

  hash: (filename) ->
    hash = 0
    for i in [0..filename.length - 1]
      hash += filename.charCodeAt(i) ^ hash

    hash.toString('16')

Images = new class
  constructor: ->
    @cache = {}

  failed: (image, event) ->
    image.status = 'failed'
    
    if image.node?
      event = new CustomEvent('written:uploader:error', {bubbles: true})
      event.image = image
      image.node.dispatchEvent(event)

  update: (image, event) ->
    image.status = 'completed'

    if image.node?
      event = new CustomEvent('written:uploader:completed', {bubbles: true})
      event.image = image
      image.node.dispatchEvent(event)

  upload: (name, file) =>
    image = {
      url: "#{@settings.bucket}/#{name}"
      name: name
      status: 'uploading'
      progress: 0
    }

    form = new FormData()
    form.append('key', name)
    form.append('acl', 'private')
    form.append("AWSAccessKeyId", @settings.accessKey)
    form.append('policy', @settings.policy)
    form.append('signature', @settings.signature)
    form.append('Content-Type', file.type)
    form.append('file', file, name)


    image.xhr = @send(form, @settings.bucket)
    image.xhr.addEventListener('load', @update.bind(this, image))
    image.xhr.addEventListener('error', @failed.bind(this, image))<commit_msg>Bucket and the URL should be two different component<commit_after>class Written.Uploaders.AWS
  constructor: (settings) ->
    Images.settings = settings

  initialize: (node, observer) =>
    img = node.querySelector('img')
    container = node.querySelector('div')

    node.dataset.uploadable = true
    node.addEventListener 'written:uploader:error', @error, true
    node.addEventListener 'written:uploader:uploading', @progress, true
    node.addEventListener 'written:uploader:completed', @uploaded, true
    node.addEventListener 'change', @input.bind(this, node, observer), true

    container.addEventListener 'click', @open.bind(this, node), true
    image = Images.get(img.dataset.image)
    if image
      image.node = node

  open: (node, e) =>
    node.querySelector('input')?.click()

  uploaded: (e) =>
    caption = e.target.querySelector('figcaption')
    img = e.target.querySelector('img')

    text = caption.childNodes[caption.childNodes.length - 1]
    text.textContent = "(#{e.image.url})"
    img.src = e.image.url
    selection = window.getSelection()
    selection.removeAllRanges()
    range = document.createRange()
    range.setEnd(text, text.textContent.length - 1)
    selection.addRange(range)

  error: (e) =>
    console.log(e)

  input: (node, history, e) =>
    file = e.target.files[0]
    @process(file, node, history)

  process: (file, node) =>
    caption = node.querySelector('figcaption')
    progress = node.querySelector('div.progress')
    filename = @hash(file.name)

    image = Images.get(filename)
    if !image
      image = Images.upload(filename, file)

    image.node = node
    progress.style.width = image.progress
    node.dataset.status = image.status

    text = caption.childNodes[caption.childNodes.length - 1]
    text.textContent = "(#{filename})"
    selection = window.getSelection()
    selection.removeAllRanges()
    range = document.createRange()
    range.setEnd(text, text.textContent.length - 1)
    selection.addRange(range)

  hash: (filename) ->
    hash = 0
    for i in [0..filename.length - 1]
      hash += filename.charCodeAt(i) ^ hash

    hash.toString('16')

Images = new class
  constructor: ->
    @cache = {}

  failed: (image, event) ->
    image.status = 'failed'
    
    if image.node?
      event = new CustomEvent('written:uploader:error', {bubbles: true})
      event.image = image
      image.node.dispatchEvent(event)

  update: (image, event) ->
    image.status = 'completed'

    if image.node?
      event = new CustomEvent('written:uploader:completed', {bubbles: true})
      event.image = image
      image.node.dispatchEvent(event)

  upload: (name, file) =>
    image = {
      url: "#{@settings.url}/#{name}"
      name: name
      status: 'uploading'
      progress: 0
    }

    form = new FormData()
    form.append('key', name)
    form.append('acl', 'private')
    form.append("AWSAccessKeyId", @settings.accessKey)
    form.append('policy', @settings.policy)
    form.append('signature', @settings.signature)
    form.append('Content-Type', file.type)
    form.append('file', file, name)


    image.xhr = @send(form, @settings.url)
    image.xhr.addEventListener('load', @update.bind(this, image))
    image.xhr.addEventListener('error', @failed.bind(this, image))
{'fraction_non_alphanumeric': 0.14476307314829015, 'fraction_numerical': 0.003373715687777948, 'mean_word_length': 3.316346790205162, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2142177', 'n_tokens_mistral': 2047, 'n_tokens_neox': 1992, 'n_words': 417}