<commit_before>/*

high performance StyleSheet for css-in-js systems

- uses multiple style tags behind the scenes for millions of rules
- uses `insertRule` for appending in production for *much* faster performance
- 'polyfills' on server side


// usage

import StyleSheet from 'glamor/lib/sheet'
let styleSheet = new StyleSheet()

styleSheet.inject()
- 'injects' the stylesheet into the page (or into memory if on server)

styleSheet.insert('#box { border: 1px solid red; }')
- appends a css rule into the stylesheet

styleSheet.flush()
- empties the stylesheet of all its contents


*/

function last(arr) {
  return arr[arr.length -1]
}

function sheetForTag(tag) {
  for(let i = 0; i < document.styleSheets.length; i++) {
    if(document.styleSheets[i].ownerNode === tag) {
      return document.styleSheets[i]
    }
  }
}

const isBrowser = typeof document !== 'undefined'
const isDev = (x => (x === 'development') || !x)(process.env.NODE_ENV)
const isTest = process.env.NODE_ENV === 'test'

const oldIE = (() => {
  if(isBrowser) {
    let div = document.createElement('div')
    div.innerHTML = '<!--[if lt IE 10]><i></i><![endif]-->'
    return div.getElementsByTagName('i').length === 1
  }
})()

function makeStyleTag() {
  let tag = document.createElement('style')
  tag.type = 'text/css'
  tag.appendChild(document.createTextNode(''));
  (document.head || document.getElementsByTagName('head')[0]).appendChild(tag)
  return tag
}


export class StyleSheet {
  constructor({
    speedy = !isDev && !isTest,
    maxLength = (isBrowser && oldIE) ? 4000 : 65000
  } = {}) {
    StyleSheet.instance = this // for testing TODO: something better
    this.isSpeedy = speedy // the big drawback here is that the css won't be editable in devtools
    this.sheet = undefined
    this.tags = []
    this.maxLength = maxLength
    this.ctr = 0
  }
  inject() {
    if(this.injected) {
      throw new Error('already injected stylesheet!')
    }
    if(isBrowser) {
      // this section is just weird alchemy I found online off many sources
      this.tags[0] = makeStyleTag()
      // this weirdness brought to you by firefox
      this.sheet = sheetForTag(this.tags[0])
    }
    else {
      // server side 'polyfill'. just enough behavior to be useful.
      this.sheet  = {
        cssRules: [],
        insertRule: rule => {
          // enough 'spec compliance' to be able to extract the rules later
          // in other words, just the cssText field
          const serverRule = { cssText: rule }
          this.sheet.cssRules.push(serverRule)
          return {serverRule, appendRule: (newCss => serverRule.cssText += newCss)}
        }
      }
    }
    this.injected = true
  }
  speedy(bool) {
    if(this.ctr !== 0) {
      throw new Error(`cannot change speedy mode after inserting any rule to sheet. Either call speedy(${bool}) earlier in your app, or call flush() before speedy(${bool})`)
    }
    this.isSpeedy = !!bool
  }
  _insert(rule) {
    // this weirdness for perf, and chrome's weird bug
    // https://stackoverflow.com/questions/20007992/chrome-suddenly-stopped-accepting-insertrule
    try {
      this.sheet.insertRule(rule, this.sheet.cssRules.length) // todo - correct index here
    }
    catch(e) {
      if(isDev) {
        // might need beter dx for this
        console.warn('whoops, illegal rule inserted', rule) //eslint-disable-line no-console
      }
    }

  }
  insert(rule) {
    let insertedRule

    if(isBrowser) {
      // this is the ultrafast version, works across browsers
      if(this.isSpeedy && this.sheet.insertRule) {
        this._insert(rule)
      }
      // more browser weirdness. I don't even know
      else if(this.tags.length > 0 && last(this.tags).styleSheet) {
        last(this.tags).styleSheet.cssText+= rule
      }
      else{
        const textNode = document.createTextNode(rule)<commit_msg>Add IE10 support<commit_after>/*

high performance StyleSheet for css-in-js systems

- uses multiple style tags behind the scenes for millions of rules
- uses `insertRule` for appending in production for *much* faster performance
- 'polyfills' on server side


// usage

import StyleSheet from 'glamor/lib/sheet'
let styleSheet = new StyleSheet()

styleSheet.inject()
- 'injects' the stylesheet into the page (or into memory if on server)

styleSheet.insert('#box { border: 1px solid red; }')
- appends a css rule into the stylesheet

styleSheet.flush()
- empties the stylesheet of all its contents


*/

function last(arr) {
  return arr[arr.length -1]
}

function sheetForTag(tag) {
  for(let i = 0; i < document.styleSheets.length; i++) {
    if(document.styleSheets[i].ownerNode === tag) {
      return document.styleSheets[i]
    }
  }
}

const isBrowser = typeof document !== 'undefined'
const isDev = (x => (x === 'development') || !x)(process.env.NODE_ENV)
const isTest = process.env.NODE_ENV === 'test'

const oldIE = (() => {
  if(isBrowser) {
    let div = document.createElement('div')
    div.innerHTML = '<!--[if lt IE 10]><i></i><![endif]-->'
    return div.getElementsByTagName('i').length === 1
  }
})()

function makeStyleTag() {
  let tag = document.createElement('style')
  tag.type = 'text/css'
  tag.appendChild(document.createTextNode(''));
  (document.head || document.getElementsByTagName('head')[0]).appendChild(tag)
  return tag
}


export class StyleSheet {
  constructor({
    speedy = !isDev && !isTest,
    maxLength = (isBrowser && oldIE) ? 4000 : 65000
  } = {}) {
    StyleSheet.instance = this // for testing TODO: something better
    this.isSpeedy = speedy // the big drawback here is that the css won't be editable in devtools
    this.sheet = undefined
    this.tags = []
    this.maxLength = maxLength
    this.ctr = 0
  }
  inject() {
    if(this.injected) {
      throw new Error('already injected stylesheet!')
    }
    if(isBrowser) {
      // this section is just weird alchemy I found online off many sources
      this.tags[0] = makeStyleTag()
      // this weirdness brought to you by firefox
      this.sheet = sheetForTag(this.tags[0])
    }
    else {
      // server side 'polyfill'. just enough behavior to be useful.
      this.sheet  = {
        cssRules: [],
        insertRule: rule => {
          // enough 'spec compliance' to be able to extract the rules later
          // in other words, just the cssText field
          const serverRule = { cssText: rule }
          this.sheet.cssRules.push(serverRule)
          return {serverRule, appendRule: (newCss => serverRule.cssText += newCss)}
        }
      }
    }
    this.injected = true
  }
  speedy(bool) {
    if(this.ctr !== 0) {
      throw new Error(`cannot change speedy mode after inserting any rule to sheet. Either call speedy(${bool}) earlier in your app, or call flush() before speedy(${bool})`)
    }
    this.isSpeedy = !!bool
  }
  _insert(rule) {
    // this weirdness for perf, and chrome's weird bug
    // https://stackoverflow.com/questions/20007992/chrome-suddenly-stopped-accepting-insertrule
    try {
      this.sheet.insertRule(rule, this.sheet.cssRules.length) // todo - correct index here
    }
    catch(e) {
      if(isDev) {
        // might need beter dx for this
        console.warn('whoops, illegal rule inserted', rule) //eslint-disable-line no-console
      }
    }

  }
  insert(rule) {
    let insertedRule

    if(isBrowser) {
      // this is the ultrafast version, works across browsers
      if(this.isSpeedy && this.sheet.insertRule) {
        this._insert(rule)
      }
      else{
        const textNode = document.createTextNode(rule)
{'fraction_non_alphanumeric': 0.12407407407407407, 'fraction_numerical': 0.007804232804232804, 'mean_word_length': 2.8361237950279046, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 20, 'https://': 2, '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': '6170931', 'n_tokens_mistral': 2391, 'n_tokens_neox': 2296, 'n_words': 672}