<commit_before>class ChunkPoller
  INTERVAL = 1000
  constructor: ($body, @pollUrl) ->
    @$status = $body.find('[data-deploy-status]')
    @$code = $body.find('code')
    @$body = $body
    @$window = $(window)

  poll: =>
    jQuery.get(@pollUrl, @update)

  update: (response) =>
    @pollUrl = response.url
    @restoreBrowserScroll =>
      @appendChunks(response.chunks)
    @updateDeployStatus(response.deploy)
    unless @deployIsFinished(response.deploy)
      @start()

  restoreBrowserScroll: (callback) ->
    wasScrolledToBottom = @isScrolledToBottom()
    callback()
    if wasScrolledToBottom
      @$window.scrollTop(@$body.height())

  isScrolledToBottom: ->
    @$body.height() - @$window.height() == window.scrollY

  start: ->
    setTimeout(@poll, INTERVAL)

  updateDeployStatus: (deploy) ->
    @$status.attr('data-deploy-status', deploy.status)

  deployIsFinished: (deploy) ->
    @$status.attr('data-deploy-status') not in ['pending', 'running']

  appendChunks: (chunks) ->
    return unless chunks.length

    text = chunks.map((c) -> c.text).join('')
    @$code.append(@colorize(text))

  colorize: (text) ->
    ansi_up.ansi_to_html(text)

jQuery ->
  poller = new ChunkPoller($('body'), $('code').data('next-chunks-url'))
  poller.start()

  $('code').each ->
    $(this).html(ChunkPoller::colorize(this.innerHTML))<commit_msg>Fix potential XSS in deploy poller<commit_after>class ChunkPoller
  INTERVAL = 1000
  constructor: ($body, @pollUrl) ->
    @$status = $body.find('[data-deploy-status]')
    @$code = $body.find('code')
    @$body = $body
    @$window = $(window)

  poll: =>
    jQuery.get(@pollUrl, @update)

  update: (response) =>
    @pollUrl = response.url
    @restoreBrowserScroll =>
      @appendChunks(response.chunks)
    @updateDeployStatus(response.deploy)
    unless @deployIsFinished(response.deploy)
      @start()

  restoreBrowserScroll: (callback) ->
    wasScrolledToBottom = @isScrolledToBottom()
    callback()
    if wasScrolledToBottom
      @$window.scrollTop(@$body.height())

  isScrolledToBottom: ->
    @$body.height() - @$window.height() == window.scrollY

  start: ->
    setTimeout(@poll, INTERVAL)

  updateDeployStatus: (deploy) ->
    @$status.attr('data-deploy-status', deploy.status)

  deployIsFinished: (deploy) ->
    @$status.attr('data-deploy-status') not in ['pending', 'running']

  appendChunks: (chunks) ->
    return unless chunks.length

    text = chunks.map((c) -> c.text).join('')
    @$code.append(@colorize(@escapeHTML(text)))

  colorize: (text) ->
    ansi_up.ansi_to_html(text)


  ENTITIES = {
    '&': '&amp;'
    '<': '&lt;'
    '>': '&gt;'
    '"': '&quot;'
    "'": '&#x27;'
  }
  ESCAPE_PATTERN = new RegExp("[#{Object.keys(ENTITIES).join('')}]", 'g')

  escapeHTML: (html) ->
    html.replace ESCAPE_PATTERN, (char) ->
      ENTITIES[char]

jQuery ->
  poller = new ChunkPoller($('body'), $('code').data('next-chunks-url'))
  poller.start()

  $('code').each ->
    $(this).html(ChunkPoller::colorize(this.innerHTML))
{'fraction_non_alphanumeric': 0.18702416418404502, 'fraction_numerical': 0.0033101621979476996, 'mean_word_length': 3.6420890937019967, 'pattern_counts': {'":': 1, '<': 4, '<?xml version=': 0, '>': 34, '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': '4874482', 'n_tokens_mistral': 1112, 'n_tokens_neox': 1046, 'n_words': 168}