<commit_before>/** @jsx React.DOM */
(function() {
"use strict";

// TODO(david): We might want to split up this file eventually.

var D_KEYCODE = 'D'.charCodeAt(0),
    G_KEYCODE = 'G'.charCodeAt(0),
    H_KEYCODE = 'H'.charCodeAt(0),
    J_KEYCODE = 'J'.charCodeAt(0),
    K_KEYCODE = 'K'.charCodeAt(0),
    L_KEYCODE = 'L'.charCodeAt(0),
    N_KEYCODE = 'N'.charCodeAt(0),
    O_KEYCODE = 'O'.charCodeAt(0),
    P_KEYCODE = 'P'.charCodeAt(0),
    U_KEYCODE = 'U'.charCodeAt(0),
    ENTER_KEYCODE = 13,
    ESCAPE_KEYCODE = 27;

// A cache of all tag IDs and their counts.
var allTags = {};

var clamp = function(num, min, max) {
  return Math.min(Math.max(num, min), max);
};

var capitalizeFirstLetter = function(str) {
  return str.charAt(0).toUpperCase() + str.slice(1);
};

// Adapted from http://stackoverflow.com/a/2880929/392426
var getQueryParams = function() {
  var match,
      pl     = /\+/g,  // Regex for replacing addition symbol with a space
      search = /([^&=]+)=?([^&]*)/g,
      decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
      query  = window.location.search.substring(1),
      urlParams = {};

  while ((match = search.exec(query))) {
    urlParams[decode(match[1])] = decode(match[2]);
  }

  return urlParams;
};

/**
 * Scrolls the window so that the entirety of `domNode` is visible.
 * @param {Element} domNode The DOM node to scroll into view.
 * @param {number=} context An optional amount of context (minimum distance from
 *     top or bottom of screen) to keep in pixels. Defaults to 0.
 */
var scrollToNode = function(domNode, context) {
  context = context || 0;
  var windowTop = $(window).scrollTop();
  var windowHeight = $(window).height();
  var windowBottom = windowHeight + windowTop;
  var elementTop = $(domNode).offset().top;
  var elementBottom = elementTop + $(domNode).height();

  if (elementBottom + context > windowBottom) {
    window.scrollTo(0, elementBottom + 100 - windowHeight);
  } else if (elementTop - context < windowTop) {
    window.scrollTo(0, Math.max(0, elementTop - context));
  }
};

/**
 * Force Backbone's router to navigate to the given destination. By default
 * Backbone is query-parameter agnostic[1] and will not navigate to a new route
 * for which only query params differ. This is admittedly a hack to make
 * Backbone not think that the current route matches the desired route and thus
 * force a navigate.
 *
 * Arguments are the same as documentcloud.github.io/backbone/#Router-navigate
 *
 * [1]: https://github.com/jashkenas/backbone/issues/891
 */
var forceBackboneNavigate = function() {
  // TODO(david): Figure out a less hacky way of doing this.
  Backbone.history.fragment = "_force_backbone_navigate";
  Backbone.history.navigate.apply(Backbone.history, arguments);
};

/**
 * A temporary notice that this site is still a work in progress!
 */
var WipNotice = React.createClass({
  render: function() {
    return <div className="wip-notice">
      Hi, you{"'"}ve discovered a work-in-progress!
      <a href="https://docs.google.com/document/d/1hUYiWCjup9JMWirASnO_Z2k7AJJL-KPgFKZ0C7vvUMU/edit#" target="_blank">
        See this Google Doc for more info
      </a>
      and to leave any feedback. Thank you. :)
    </div>;
  }
});

var Sidebar = React.createClass({
  render: function() {
    var categories = _.map([<commit_msg>"Work in progress" has no hyphens<commit_after>/** @jsx React.DOM */
(function() {
"use strict";

// TODO(david): We might want to split up this file eventually.

var D_KEYCODE = 'D'.charCodeAt(0),
    G_KEYCODE = 'G'.charCodeAt(0),
    H_KEYCODE = 'H'.charCodeAt(0),
    J_KEYCODE = 'J'.charCodeAt(0),
    K_KEYCODE = 'K'.charCodeAt(0),
    L_KEYCODE = 'L'.charCodeAt(0),
    N_KEYCODE = 'N'.charCodeAt(0),
    O_KEYCODE = 'O'.charCodeAt(0),
    P_KEYCODE = 'P'.charCodeAt(0),
    U_KEYCODE = 'U'.charCodeAt(0),
    ENTER_KEYCODE = 13,
    ESCAPE_KEYCODE = 27;

// A cache of all tag IDs and their counts.
var allTags = {};

var clamp = function(num, min, max) {
  return Math.min(Math.max(num, min), max);
};

var capitalizeFirstLetter = function(str) {
  return str.charAt(0).toUpperCase() + str.slice(1);
};

// Adapted from http://stackoverflow.com/a/2880929/392426
var getQueryParams = function() {
  var match,
      pl     = /\+/g,  // Regex for replacing addition symbol with a space
      search = /([^&=]+)=?([^&]*)/g,
      decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
      query  = window.location.search.substring(1),
      urlParams = {};

  while ((match = search.exec(query))) {
    urlParams[decode(match[1])] = decode(match[2]);
  }

  return urlParams;
};

/**
 * Scrolls the window so that the entirety of `domNode` is visible.
 * @param {Element} domNode The DOM node to scroll into view.
 * @param {number=} context An optional amount of context (minimum distance from
 *     top or bottom of screen) to keep in pixels. Defaults to 0.
 */
var scrollToNode = function(domNode, context) {
  context = context || 0;
  var windowTop = $(window).scrollTop();
  var windowHeight = $(window).height();
  var windowBottom = windowHeight + windowTop;
  var elementTop = $(domNode).offset().top;
  var elementBottom = elementTop + $(domNode).height();

  if (elementBottom + context > windowBottom) {
    window.scrollTo(0, elementBottom + 100 - windowHeight);
  } else if (elementTop - context < windowTop) {
    window.scrollTo(0, Math.max(0, elementTop - context));
  }
};

/**
 * Force Backbone's router to navigate to the given destination. By default
 * Backbone is query-parameter agnostic[1] and will not navigate to a new route
 * for which only query params differ. This is admittedly a hack to make
 * Backbone not think that the current route matches the desired route and thus
 * force a navigate.
 *
 * Arguments are the same as documentcloud.github.io/backbone/#Router-navigate
 *
 * [1]: https://github.com/jashkenas/backbone/issues/891
 */
var forceBackboneNavigate = function() {
  // TODO(david): Figure out a less hacky way of doing this.
  Backbone.history.fragment = "_force_backbone_navigate";
  Backbone.history.navigate.apply(Backbone.history, arguments);
};

/**
 * A temporary notice that this site is still a work in progress!
 */
var WipNotice = React.createClass({
  render: function() {
    return <div className="wip-notice">
      Hi, you've discovered a work in progress!
      <a href="https://docs.google.com/document/d/1hUYiWCjup9JMWirASnO_Z2k7AJJL-KPgFKZ0C7vvUMU/edit#" target="_blank">
        See this Google Doc for more info
      </a>
      and to leave any feedback. Thank you. :)
    </div>;
  }
});

var Sidebar = React.createClass({
  render: function() {
    var categories = _.map([
{'fraction_non_alphanumeric': 0.13992869875222816, 'fraction_numerical': 0.015151515151515152, 'mean_word_length': 3.5554803788903926, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 4, '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': '1964092', 'n_tokens_mistral': 2272, 'n_tokens_neox': 2196, 'n_words': 638}