<commit_before>/* eslint-env browser */

const STYLES_HYDRATOR = /\.([^{:]+)(:[^{]+)?{(?:[^}]*;)?([^}]*?)}/g;
const KEYFRAMES_HYRDATOR = /@keyframes ([^{]+)\{((?:[^{]+\{[^}]*\})*)\}/g;
const FONT_FACE_HYDRATOR = /@font-face\{font-family:([^;]+);([^}]*)\}/g;

type hydratorT =
  | typeof STYLES_HYDRATOR
  | typeof KEYFRAMES_HYRDATOR
  | typeof FONT_FACE_HYDRATOR;

function hydrateStyles<T>(cache: Cache<T>, hydrator: hydratorT, css: string) {
  let match;
  while ((match = hydrator.exec(css))) {
    const [, id, pseudo, key] = match;
    const fullKey = pseudo ? `${pseudo}${key}` : key;
    cache.cache[fullKey] = id; // set cache without triggering side effects
    cache.idGenerator.increment(); // increment id
  }
}

function hydrate<T>(cache: Cache<T>, hydrator: hydratorT, css: string) {
  let match;
  while ((match = hydrator.exec(css))) {
    const [, id, key] = match;
    cache.cache[key] = id; // set cache without triggering side effects
    cache.idGenerator.increment(); // increment id
  }
}

import SequentialIDGenerator from "../sequential-id-generator.js";

import type {
  StandardEngine,
  keyframesT,
  fontFaceT,
  baseStyleT,
} from "styletron-standard";

import {Cache, MultiCache} from "../cache.js";

import injectStylePrefixed from "../inject-style-prefixed.js";

import {
  styleBlockToRule,
  atomicSelector,
  keyframesBlockToRule,
  declarationsToBlock,
  keyframesToBlock,
  fontFaceBlockToRule,
} from "../css.js";

type hydrateT =
  | HTMLCollection<HTMLStyleElement>
  | Array<HTMLStyleElement>
  | NodeList<HTMLStyleElement>;

type optionsT = {
  hydrate?: hydrateT,
  container?: Element,
  prefix?: string,
};

class StyletronClient implements StandardEngine {
  container: Element;
  styleElements: {[string]: HTMLStyleElement};
  fontFaceSheet: HTMLStyleElement;
  keyframesSheet: HTMLStyleElement;

  styleCache: MultiCache<{pseudo: string, block: string}>;
  keyframesCache: Cache<keyframesT>;
  fontFaceCache: Cache<fontFaceT>;

  constructor(opts?: optionsT = {}) {
    this.styleElements = {};

    const styleIdGenerator = new SequentialIDGenerator(opts.prefix);
    const onNewStyle = (cache, id, value) => {
      const {pseudo, block} = value;
      const sheet: CSSStyleSheet = (this.styleElements[cache.key].sheet: any);
      sheet.insertRule(
        styleBlockToRule(atomicSelector(id, pseudo), block),
        sheet.cssRules.length,
      );
    };

    // Setup style cache
    this.styleCache = new MultiCache(
      styleIdGenerator,
      media => {
        const styleElement = document.createElement("style");
        styleElement.media = media;
        this.container.appendChild(styleElement);
        this.styleElements[media] = styleElement;
      },
      onNewStyle,
    );

    this.keyframesCache = new Cache(
      new SequentialIDGenerator(opts.prefix),
      (cache, id, value) => {
        this.styleCache.getCache("");
        const sheet: CSSStyleSheet = (this.styleElements[""].sheet: any);
        sheet.insertRule(
          keyframesBlockToRule(id, keyframesToBlock(value)),
          sheet.cssRules.length,
        );
      },
    );

    this.fontFaceCache = new Cache(
      new SequentialIDGenerator(opts.prefix),
      (cache, id, value) => {
        this.styleCache.getCache("");
        const sheet: CSSStyleSheet = (this.styleElements[""].sheet: any);
        sheet.insertRule(
          fontFaceBlockToRule(id, declarationsToBlock(value)),
          sheet.cssRules.length,
        );
      },
    );

    if (opts.container) {
      this.container = opts.container;
    }

    // Hydrate
    if (opts.hydrate && opts.hydrate.length > 0) {
      // infer container from parent element
      if (!this.container) {
        const parentElement = opts.hydrate[0].parentElement;
        if (parentElement !== null && parentElement !== void 0) {
          this.container = parentElement;
        }
      }

      for (let i = 0; i < opts.hydrate.length; i++) {
        const element = opts.hydrate[i];
        const hydrateType = element.dataset.hydrate;
        if (hydrateType === "font-face") {
          hydrate(this.fontFaceCache, FONT_FACE_HYDRATOR, element.textContent);
          continue;
        }
        if (hydrateType === "keyframes") {
          hydrate(this.keyframesCache, KEYFRAMES_HYRDATOR, element.textContent);
          continue;
        }
        const key = element.media ? element.media : "";
        this.styleElements[key] = element;
        const cache = new Cache(styleIdGenerator, onNewStyle);
        cache.key = key;
        hydrateStyles(cache, STYLES_HYDRATOR, element.textContent);
        this.styleCache.caches[key] = cache;
      }
    }

    if (!this.container) {
      if (document.head === null) {
        throw new Error("No container provided and `document.head` was null");
      }
      this.container = document.head;
    }
  }

  renderStyle(style: baseStyleT): string {
    return injectStylePrefixed(this.styleCache, style, "", "");
  }

  renderFontFace(fontFace: fontFaceT): string {
    const key = declarationsToBlock(fontFace);
    return this.fontFaceCache.addValue(key, fontFace);
  }

  renderKeyframes(keyframes: keyframesT): string {
    const key = keyframesToBlock(keyframes);
    return this.keyframesCache.addValue(key, keyframes);
  }
}

export default StyletronClient;
<commit_msg>Annotate styletron-engine-atomic/src/client.js with @flow to ensure types can be used in consumers<commit_after>// @flow

/* eslint-env browser */

const STYLES_HYDRATOR = /\.([^{:]+)(:[^{]+)?{(?:[^}]*;)?([^}]*?)}/g;
const KEYFRAMES_HYRDATOR = /@keyframes ([^{]+)\{((?:[^{]+\{[^}]*\})*)\}/g;
const FONT_FACE_HYDRATOR = /@font-face\{font-family:([^;]+);([^}]*)\}/g;

type hydratorT =
  | typeof STYLES_HYDRATOR
  | typeof KEYFRAMES_HYRDATOR
  | typeof FONT_FACE_HYDRATOR;

function hydrateStyles<T>(cache: Cache<T>, hydrator: hydratorT, css: string) {
  let match;
  while ((match = hydrator.exec(css))) {
    const [, id, pseudo, key] = match;
    const fullKey = pseudo ? `${pseudo}${key}` : key;
    cache.cache[fullKey] = id; // set cache without triggering side effects
    cache.idGenerator.increment(); // increment id
  }
}

function hydrate<T>(cache: Cache<T>, hydrator: hydratorT, css: string) {
  let match;
  while ((match = hydrator.exec(css))) {
    const [, id, key] = match;
    cache.cache[key] = id; // set cache without triggering side effects
    cache.idGenerator.increment(); // increment id
  }
}

import SequentialIDGenerator from "../sequential-id-generator.js";

import type {
  StandardEngine,
  keyframesT,
  fontFaceT,
  baseStyleT,
} from "styletron-standard";

import {Cache, MultiCache} from "../cache.js";

import injectStylePrefixed from "../inject-style-prefixed.js";

import {
  styleBlockToRule,
  atomicSelector,
  keyframesBlockToRule,
  declarationsToBlock,
  keyframesToBlock,
  fontFaceBlockToRule,
} from "../css.js";

type hydrateT =
  | HTMLCollection<HTMLStyleElement>
  | Array<HTMLStyleElement>
  | NodeList<HTMLStyleElement>;

type optionsT = {
  hydrate?: hydrateT,
  container?: Element,
  prefix?: string,
};

class StyletronClient implements StandardEngine {
  container: Element;
  styleElements: {[string]: HTMLStyleElement};
  fontFaceSheet: HTMLStyleElement;
  keyframesSheet: HTMLStyleElement;

  styleCache: MultiCache<{pseudo: string, block: string}>;
  keyframesCache: Cache<keyframesT>;
  fontFaceCache: Cache<fontFaceT>;

  constructor(opts?: optionsT = {}) {
    this.styleElements = {};

    const styleIdGenerator = new SequentialIDGenerator(opts.prefix);
    const onNewStyle = (cache, id, value) => {
      const {pseudo, block} = value;
      const sheet: CSSStyleSheet = (this.styleElements[cache.key].sheet: any);
      sheet.insertRule(
        styleBlockToRule(atomicSelector(id, pseudo), block),
        sheet.cssRules.length,
      );
    };

    // Setup style cache
    this.styleCache = new MultiCache(
      styleIdGenerator,
      media => {
        const styleElement = document.createElement("style");
        styleElement.media = media;
        this.container.appendChild(styleElement);
        this.styleElements[media] = styleElement;
      },
      onNewStyle,
    );

    this.keyframesCache = new Cache(
      new SequentialIDGenerator(opts.prefix),
      (cache, id, value) => {
        this.styleCache.getCache("");
        const sheet: CSSStyleSheet = (this.styleElements[""].sheet: any);
        sheet.insertRule(
          keyframesBlockToRule(id, keyframesToBlock(value)),
          sheet.cssRules.length,
        );
      },
    );

    this.fontFaceCache = new Cache(
      new SequentialIDGenerator(opts.prefix),
      (cache, id, value) => {
        this.styleCache.getCache("");
        const sheet: CSSStyleSheet = (this.styleElements[""].sheet: any);
        sheet.insertRule(
          fontFaceBlockToRule(id, declarationsToBlock(value)),
          sheet.cssRules.length,
        );
      },
    );

    if (opts.container) {
      this.container = opts.container;
    }

    // Hydrate
    if (opts.hydrate && opts.hydrate.length > 0) {
      // infer container from parent element
      if (!this.container) {
        const parentElement = opts.hydrate[0].parentElement;
        if (parentElement !== null && parentElement !== void 0) {
          this.container = parentElement;
        }
      }

      for (let i = 0; i < opts.hydrate.length; i++) {
        const element = opts.hydrate[i];
        const hydrateType = element.dataset.hydrate;
        if (hydrateType === "font-face") {
          hydrate(this.fontFaceCache, FONT_FACE_HYDRATOR, element.textContent);
          continue;
        }
        if (hydrateType === "keyframes") {
          hydrate(this.keyframesCache, KEYFRAMES_HYRDATOR, element.textContent);
          continue;
        }
        const key = element.media ? element.media : "";
        this.styleElements[key] = element;
        const cache = new Cache(styleIdGenerator, onNewStyle);
        cache.key = key;
        hydrateStyles(cache, STYLES_HYDRATOR, element.textContent);
        this.styleCache.caches[key] = cache;
      }
    }

    if (!this.container) {
      if (document.head === null) {
        throw new Error("No container provided and `document.head` was null");
      }
      this.container = document.head;
    }
  }

  renderStyle(style: baseStyleT): string {
    return injectStylePrefixed(this.styleCache, style, "", "");
  }

  renderFontFace(fontFace: fontFaceT): string {
    const key = declarationsToBlock(fontFace);
    return this.fontFaceCache.addValue(key, fontFace);
  }

  renderKeyframes(keyframes: keyframesT): string {
    const key = keyframesToBlock(keyframes);
    return this.keyframesCache.addValue(key, keyframes);
  }
}

export default StyletronClient;

{'fraction_non_alphanumeric': 0.13815850599275295, 'fraction_numerical': 0.000743287187587104, 'mean_word_length': 3.1052631578947367, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 33, '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': '1366609', 'n_tokens_mistral': 3392, 'n_tokens_neox': 3319, 'n_words': 692}