<commit_before>((window, $) ->

  # given raw CSS, remove all code comments
  removeCssComments = (css) -> css.replace /\/\*.*?\*\//g, ""

  # given a string, chop off whitespace at the beginning and end
  trim = (s) -> if s then s.replace(/^\s*/, "").replace(/\s*$/, "") else ""

  # given raw css, return an array of selector/style pairs for each rule
  parseCssRules = (css) ->
    result = []
    cleanCss = removeCssComments(css)
    rules = cleanCss.match /([^\{]+[^\}]*\})/g
    for rule in rules
      styleStart = rule.indexOf "{"
      styleEnd = rule.indexOf "}"
      selector = rule.substring 0, styleStart
      styles = rule.substring styleStart + 1, styleEnd
      if /[^\s]/.test(selector)
        result.push
          selector: trim(selector)
          styles: trim(styles).replace /\n/g, " "
    result

  # given a rule's properties, return an array of name/value pairs for each property
  #
  # KNOWN ISSUE:
  # If a property includes a quote with a semicolon or colon, these will not split 
  # properly. That situation is so rare that I am choosing not to account for it.
  parseProperties = (properties) ->
    result = []
    properties = properties.split ";"
    for index, property of properties
      [name, value] = property.split(":")
      if name or value
        result.push
          name: trim(name)
          value: trim(value)
    result

  # given a rule's selector, split it into multiple rules if necessary
  parseSelectors = (selector) -> selector.split(",")

  # parse the raw css, then perform a callback on each rule
  # the filtered css is built from the return value of the callback function
  filterCss = (css, callback) ->
    result = ""
    rules = parseCssRules(css)
    result += callback(rule) + "\n" for index, rule of rules
    result

  # given raw css, add !important onto every property
  filterImportant = (css) ->
    filterCss css, (rule) ->
      newStyles = ""
      for index, property of parseProperties(rule.styles)
        newStyles += "#{property.name}:#{property.value} !important;"
      "#{rule.selector} {#{newStyles}}"

  # given raw css, add some arbitrary text before every selector
  # special case if the selector starts with "self":
  #   remove "self" and append the rest of the selector directly to the prefix (no space)
  filterPrefixSelectors = (css, prefix) ->
    filterCss css, (rule) ->
      selectors = parseSelectors(rule.selector)
      newSelectors = []
      for index, selector of selectors
        if /^self/.test(selector)
          newSelectors.push prefix unless newSelectors.length
          newSelectors[newSelectors.length-1] += selector.replace /^self/, ""
        else
          newSelectors.push "#{prefix} #{selector}"
      "#{newSelectors.join(",")}{#{rule.styles}}"

  # given a DOM element, return an array of its 
  # ancestors (including itself) from least to greatest depth
  ancestors = (elem) ->
    result = []
    currentNode = elem
    while currentNode.parentNode && currentNode.parentNode.nodeType == 1
      result.unshift currentNode
      currentNode = currentNode.parentNode
    result

  # given a DOM element, generate a very specific css selector for it
  cssSelector = (elem) ->
    result = elem.tagName.toLowerCase()
    result += "#" + elem.id if elem.id
    result

  # given a DOM element "elem" and raw CSS, modify the CSS to only affect 
  # elements within "elem".
  window.injectCss = (elem, css, options) ->
    options = {} unless options
    randId = "injectedCss#{Math.random() * 0x100000000}".replace ".", ""

    # set some data on elem so we can pick it out of a crowd
    elem.id = randId if !elem.id
    elem.setAttribute "class", (elem.getAttribute("class") || "") + " " + randId
    elem.injectedCss = [] if !elem.injectedCss

    # generate the most specific css selector of elem
    specificSelector = ""
    specificSelector += cssSelector(elem) + " " for index, elem of ancestors(elem)
    specificSelector = trim(specificSelector)

    # generate a new specific selector for each rule
    # add !important onto each property if that option is set
    outputCss = filterPrefixSelectors css, specificSelector
    outputCss = filterImportant outputCss if options.important

    # create the <style> element
    styleElem = document.createElement("style")
    styleElem.id = "#{randId}_style"
    styleElem.setAttribute "data-injected-css-handle", elem.id
    styleElem.setAttribute "type", "text/css"

    # insert after either the last <style> or the first <script>
    styles = document.getElementsByTagName "style"
    domTarget = if styles.length then styles[styles.length-1] else document.getElementsByTagName("script")[0]
    domTarget.parentNode.insertBefore(styleElem, domTarget.nextSibling)
    elem.injectedCss.push styleElem

    # update the content on the <style> elem
    # this must be done after its in the DOM to prevent IE7 from crashing
    if styleElem.styleSheet
      styleElem.styleSheet.cssText = outputCss
    else
      styleElem.appendChild document.createTextNode(outputCss)

    # return the injected <style> element
    styleElem

  # given an element, delete/remove all associated injectedCss data<commit_msg>typo.<commit_after>((window, $) ->

  # given raw CSS, remove all code comments
  removeCssComments = (css) -> css.replace /\/\*.*?\*\//g, ""

  # given a string, chop off whitespace at the beginning and end
  trim = (s) -> if s then s.replace(/^\s*/, "").replace(/\s*$/, "") else ""

  # given raw css, return an array of selector/style pairs for each rule
  parseCssRules = (css) ->
    result = []
    cleanCss = removeCssComments(css)
    rules = cleanCss.match /([^\{]+[^\}]*\})/g
    for rule in rules
      styleStart = rule.indexOf "{"
      styleEnd = rule.indexOf "}"
      selector = rule.substring 0, styleStart
      styles = rule.substring styleStart + 1, styleEnd
      if /[^\s]/.test(selector)
        result.push
          selector: trim(selector)
          styles: trim(styles).replace /\n/g, " "
    result

  # given a rule's properties, return an array of name/value pairs for each property
  #
  # KNOWN ISSUE:
  # If a property includes a quote with a semicolon or colon, these will not split 
  # properly. That situation is so rare that I am choosing not to account for it.
  parseProperties = (properties) ->
    result = []
    properties = properties.split ";"
    for index, property of properties
      [name, value] = property.split(":")
      if name or value
        result.push
          name: trim(name)
          value: trim(value)
    result

  # given a rule's selector, split it into multiple rules if necessary
  parseSelectors = (selector) -> selector.split(",")

  # parse the raw css, then perform a callback on each rule
  # the filtered css is built from the return value of the callback function
  filterCss = (css, callback) ->
    result = ""
    rules = parseCssRules(css)
    result += callback(rule) + "\n" for index, rule of rules
    result

  # given raw css, add !important onto every property
  filterImportant = (css) ->
    filterCss css, (rule) ->
      newStyles = ""
      for index, property of parseProperties(rule.styles)
        newStyles += "#{property.name}:#{property.value} !important;"
      "#{rule.selector} {#{newStyles}}"

  # given raw css, add some arbitrary text before every selector
  # special case if the selector starts with "self":
  #   remove "self" and append the rest of the selector directly to the prefix (no space)
  filterPrefixSelectors = (css, prefix) ->
    filterCss css, (rule) ->
      selectors = parseSelectors(rule.selector)
      newSelectors = []
      for index, selector of selectors
        if /^self/.test(selector)
          newSelectors.push prefix unless newSelectors.length
          newSelectors[newSelectors.length-1] += selector.replace /^self/, ""
        else
          newSelectors.push "#{prefix} #{selector}"
      "#{newSelectors.join(",")}{#{rule.styles}}"

  # given a DOM element, return an array of its 
  # ancestors (including itself) from least to greatest depth
  ancestors = (elem) ->
    result = []
    currentNode = elem
    while currentNode.parentNode && currentNode.parentNode.nodeType == 1
      result.unshift currentNode
      currentNode = currentNode.parentNode
    result

  # given a DOM element, generate a very specific css selector for it
  cssSelector = (elem) ->
    result = elem.tagName.toLowerCase()
    result += "#" + elem.id if elem.id
    result

  # given a DOM element "elem" and raw CSS, modify the CSS to only affect 
  # elements within "elem".
  window.injectCss = (elem, css, options) ->
    options = {} unless options
    randId = "injectedCss#{Math.random() * 0x100000000}".replace ".", ""

    # set some data on elem so we can pick it out of a crowd
    elem.id = randId if !elem.id
    elem.setAttribute "class", (elem.getAttribute("class") || "") + " " + randId
    elem.injectedCss = [] if !elem.injectedCss

    # generate the most specific css selector of elem
    specificSelector = ""
    specificSelector += cssSelector(elem) + " " for index, elem of ancestors(elem)
    specificSelector = trim(specificSelector)

    # generate a new specific selector for each rule
    # add !important onto each property if that option is set
    outputCss = filterPrefixSelectors css, specificSelector
    outputCss = filterImportant outputCss if options.important

    # create the <style> element
    styleElem = document.createElement("style")
    styleElem.id = "#{randId}_style"
    styleElem.setAttribute "data-injected-css-handle", elem.id
    styleElem.setAttribute "type", "text/css"

    # insert after either the last <style> or the first <script>
    styles = document.getElementsByTagName "style"
    domTarget = if styles.length then styles[styles.length-1] else document.getElementsByTagName("script")[0]
    domTarget.parentNode.insertBefore(styleElem, domTarget.nextSibling)
    elem.injectedCss.push styleElem

    # update the content on the <style> elem
    # this must be done after it's in the DOM to prevent IE7 from crashing
    if styleElem.styleSheet
      styleElem.styleSheet.cssText = outputCss
    else
      styleElem.appendChild document.createTextNode(outputCss)

    # return the injected <style> element
    styleElem

  # given an element, delete/remove all associated injectedCss data
{'fraction_non_alphanumeric': 0.10741490695207791, 'fraction_numerical': 0.003278372384533796, 'mean_word_length': 3.0547302580140734, 'pattern_counts': {'":': 4, '<': 13, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, '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': '3662401', 'n_tokens_mistral': 2974, 'n_tokens_neox': 2932, 'n_words': 1023}