<commit_before>/* @flow */
/* eslint-disable prefer-rest-params */
import 'text-encoding'
import gzipSize from 'gzip-size'

import { RULE_TYPE } from '../utils/styleTypes'

function addStatistics(renderer: Object): Object {
  const statistics: Object = {
    count: {
      classes: 0,
      pseudoClasses: 0
    },
    usage: {},
    size: {},
    reuse: {},

    totalPseudoClasses: 0,
    totalMediaQueryClasses: 0,
    totalClasses: 0,
    totalRenders: 0,
    totalUsage: 0
  }

  function addClassNamesToUsage(classNames: string): void {
    classNames.split(' ').forEach((className) => {
      if (!statistics.usage[className]) {
        statistics.usage[className] = 0
      }
      statistics.usage[className]++
      statistics.totalUsage++
    })
  }

  const existingRenderRule: Function = renderer.renderRule
  renderer.renderRule = function () {
    statistics.totalRenders++
    const classNames: string = existingRenderRule.apply(renderer, arguments)
    addClassNamesToUsage(classNames)
    return classNames
  }

  renderer.subscribe(({ type, selector, media, static: isStatic }: Object) => {
    if (type === RULE_TYPE && !isStatic) {
      statistics.totalClasses++
      const isPseudoSelector: boolean = selector.indexOf(':') > -1
      if (media) {
        statistics.totalMediaQueryClasses++

        if (!statistics.count[media]) {
          statistics.count[media] = {
            pseudoClasses: 0,
            classes: 0
          }
        }

        if (isPseudoSelector) {
          statistics.totalPseudoClasses++
          statistics.count[media].pseudoClasses++
        } else {
          statistics.count[media].classes++
        }
      } else {
        statistics.totalClasses++

        if (isPseudoSelector) {
          statistics.totalPseudoClasses++
          statistics.count.pseudoClasses++
        } else {
          statistics.count.classes++
        }
      }
    }
  })

  function calculateReuse() {
    const quotient = (statistics.totalUsage - statistics.totalClasses) / statistics.totalUsage
    return Math.floor(quotient * 10000) / 10000
  }

  renderer.getStatistics = () => {
    const currentStats = { ...statistics }

    const reuse = calculateReuse()
    currentStats.reuse = {
      percentage: `${reuse * 100}%`,
      number: reuse
    }

    const currentCSS = renderer.renderToString()
    const bytes = new TextEncoder('utf-8').encode(currentCSS).length

    currentStats.size = {
      bytes,
      bytesGzipped: gzipSize.sync(currentCSS),
      kbytes: Math.floor(bytes / 10) / 100,
      kbytesGzipped: Math.floor(gzipSize.sync(currentCSS) / 10) / 100<commit_msg>added different byte size checker<commit_after>/* @flow */
/* eslint-disable prefer-rest-params */
import gzipSize from 'gzip-size'

import { RULE_TYPE } from '../utils/styleTypes'

function lengthInUtf8Bytes(str) {
  // Matches only the 10.. bytes that are non-initial characters in a multi-byte sequence.
  const m = encodeURIComponent(str).match(/%[89ABab]/g)
  return str.length + (m ? m.length : 0)
}

function addStatistics(renderer: Object): Object {
  const statistics: Object = {
    count: {
      classes: 0,
      pseudoClasses: 0
    },
    usage: {},
    size: {},
    reuse: {},
    totalPseudoClasses: 0,
    totalMediaQueryClasses: 0,
    totalClasses: 0,
    totalRenders: 0,
    totalUsage: 0
  }

  function addClassNamesToUsage(classNames: string): void {
    classNames.split(' ').forEach((className) => {
      if (!statistics.usage[className]) {
        statistics.usage[className] = 0
      }
      statistics.usage[className]++
      statistics.totalUsage++
    })
  }

  const existingRenderRule: Function = renderer.renderRule
  renderer.renderRule = function () {
    statistics.totalRenders++
    const classNames: string = existingRenderRule.apply(renderer, arguments)
    addClassNamesToUsage(classNames)
    return classNames
  }

  renderer.subscribe(({ type, selector, media, static: isStatic }: Object) => {
    if (type === RULE_TYPE && !isStatic) {
      statistics.totalClasses++
      const isPseudoSelector: boolean = selector.indexOf(':') > -1
      if (media) {
        statistics.totalMediaQueryClasses++

        if (!statistics.count[media]) {
          statistics.count[media] = {
            pseudoClasses: 0,
            classes: 0
          }
        }

        if (isPseudoSelector) {
          statistics.totalPseudoClasses++
          statistics.count[media].pseudoClasses++
        } else {
          statistics.count[media].classes++
        }
      } else {
        statistics.totalClasses++

        if (isPseudoSelector) {
          statistics.totalPseudoClasses++
          statistics.count.pseudoClasses++
        } else {
          statistics.count.classes++
        }
      }
    }
  })

  function calculateReuse() {
    const quotient = (statistics.totalUsage - statistics.totalClasses) / statistics.totalUsage
    return Math.floor(quotient * 10000) / 10000
  }

  renderer.getStatistics = () => {
    const currentStats = { ...statistics }

    const reuse = calculateReuse()
    currentStats.reuse = {
      percentage: `${reuse * 100}%`,
      number: reuse
    }

    const currentCSS = renderer.renderToString()
    const bytes = lengthInUtf8Bytes(currentCSS)

    currentStats.size = {
      bytes,
      bytesGzipped: gzipSize.sync(currentCSS),
      kbytes: Math.floor(bytes / 10) / 100,
      kbytesGzipped: Math.floor(gzipSize.sync(currentCSS) / 10) / 100
{'fraction_non_alphanumeric': 0.11996336996336997, 'fraction_numerical': 0.01391941391941392, 'mean_word_length': 2.592763157894737, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 11, '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': '2112715', 'n_tokens_mistral': 1669, 'n_tokens_neox': 1607, 'n_words': 323}