closure/goog/html/cssspecificity.js
function calculateSpecificity(selector) {
  var specificity = [0, 0, 0, 0];

  // Cannot use RegExp literals for all regular expressions, IE does not accept
  // the syntax.

  // Matches a backslash followed by six hexadecimal digits followed by an
  // optional single whitespace character.
  var escapeHexadecimalRegex = new RegExp('\\\\[0-9A-Fa-f]{6}\\s?', 'g');
  // Matches a backslash followed by fewer than six hexadecimal digits
  // followed by a mandatory single whitespace character.
  var escapeHexadecimalRegex2 = new RegExp('\\\\[0-9A-Fa-f]{1,5}\\s', 'g');
  // Matches a backslash followed by any character
  var escapeSpecialCharacter = /\\./g;
  selector = replaceWithPlainText(selector, escapeHexadecimalRegex);
  selector = replaceWithPlainText(selector, escapeHexadecimalRegex2);
  selector = replaceWithPlainText(selector, escapeSpecialCharacter);

  // Remove the negation pseudo-class (:not) but leave its argument because
  // specificity is calculated on its argument.
  var pseudoClassWithNotRegex = new RegExp(':not\\(([^\\)]*)\\)', 'g');
  selector = selector.replace(pseudoClassWithNotRegex, '     $1 ');

  // Remove anything after a left brace in case a user has pasted in a rule,
  // not just a selector.
  var rulesRegex = new RegExp('{[^]*', 'gm');
  selector = selector.replace(rulesRegex, '');

  // The following regular expressions assume that selectors matching the
  // preceding regular expressions have been removed.

  // SPECIFICITY 2: Counts attribute selectors.
  var attributeRegex = new RegExp('(\\[[^\\]]+\\])', 'g');
  selector = replaceWithEmptyText(selector, specificity, attributeRegex, 2);

  // SPECIFICITY 1: Counts ID selectors.
  var idRegex = new RegExp('(#[^\\#\\s\\+>~\\.\\[:]+)', 'g');
  selector = replaceWithEmptyText(selector, specificity, idRegex, 1);

  // SPECIFICITY 2: Counts class selectors.
  var classRegex = new RegExp('(\\.[^\\s\\+>~\\.\\[:]+)', 'g');
  selector = replaceWithEmptyText(selector, specificity, classRegex, 2);

  // SPECIFICITY 3: Counts pseudo-element selectors.
  var pseudoElementRegex =
      /(::[^\s\+>~\.\[:]+|:first-line|:first-letter|:before|:after)/gi;
  selector = replaceWithEmptyText(selector, specificity, pseudoElementRegex, 3);

  // SPECIFICITY 2: Counts pseudo-class selectors.
  // A regex for pseudo classes with brackets. For example:
  //   :nth-child()
  //   :nth-last-child()
  //   :nth-of-type()
  //   :nth-last-type()
  //   :lang()
  var pseudoClassWithBracketsRegex = /(:[\w-]+\([^\)]*\))/gi;
  selector = replaceWithEmptyText(
      selector, specificity, pseudoClassWithBracketsRegex, 2);
  // A regex for other pseudo classes, which don't have brackets.
  var pseudoClassRegex = /(:[^\s\+>~\.\[:]+)/g;
  selector = replaceWithEmptyText(selector, specificity, pseudoClassRegex, 2);

  // Remove universal selector and separator characters.
  selector = selector.replace(/[\*\s\+>~]/g, ' ');

  // Remove any stray dots or hashes which aren't attached to words.
  // These may be present if the user is live-editing this selector.
  selector = selector.replace(/[#\.]/g, ' ');

  // SPECIFICITY 3: The only things left should be element selectors.
  var elementRegex = /([^\s\+>~\.\[:]+)/g;
  selector = replaceWithEmptyText(selector, specificity, elementRegex, 3);

  return specificity;
}
function calculateSpecificity(selector) {
  var specificity = [0, 0, 0, 0];

  // Cannot use RegExp literals for all regular expressions, IE does not accept
  // the syntax.

  // Matches a backslash followed by six hexadecimal digits followed by an
  // optional single whitespace character.
  var escapeHexadecimalRegex = new RegExp('\\\\[0-9A-Fa-f]{6}\\s?', 'g');
  // Matches a backslash followed by fewer than six hexadecimal digits
  // followed by a mandatory single whitespace character.
  var escapeHexadecimalRegex2 = new RegExp('\\\\[0-9A-Fa-f]{1,5}\\s', 'g');
  // Matches a backslash followed by any character
  var escapeSpecialCharacter = /\\./g;
  selector = replaceWithPlainText(selector, escapeHexadecimalRegex);
  selector = replaceWithPlainText(selector, escapeHexadecimalRegex2);
  selector = replaceWithPlainText(selector, escapeSpecialCharacter);

  // Remove the negation pseudo-class (:not) but leave its argument because
  // specificity is calculated on its argument.
  var pseudoClassWithNotRegex = new RegExp(':not\\(([^\\)]*)\\)', 'g');
  selector = selector.replace(pseudoClassWithNotRegex, '     $1 ');

  // Remove anything after a left brace in case a user has pasted in a rule,
  // not just a selector.
  var rulesRegex = new RegExp('{[^]*', 'gm');
  selector = selector.replace(rulesRegex, '');

  // The following regular expressions assume that selectors matching the
  // preceding regular expressions have been removed.

  // SPECIFICITY 2: Counts attribute selectors.
  var attributeRegex = new RegExp('(\\[[^\\]]+\\])', 'g');
  selector = replaceWithEmptyText(selector, specificity, attributeRegex, 2);

  // SPECIFICITY 1: Counts ID selectors.
  var idRegex = new RegExp('(#[^\\#\\s\\+>~\\.\\[:]+)', 'g');
  selector = replaceWithEmptyText(selector, specificity, idRegex, 1);

  // SPECIFICITY 2: Counts class selectors.
  var classRegex = new RegExp('(\\.[^\\s\\+>~\\.\\[:]+)', 'g');
  selector = replaceWithEmptyText(selector, specificity, classRegex, 2);

  // SPECIFICITY 3: Counts pseudo-element selectors.
  var pseudoElementRegex =
      /(::[^\s\+>~\.\[:]+|:first-line|:first-letter|:before|:after)/gi;
  selector = replaceWithEmptyText(selector, specificity, pseudoElementRegex, 3);

  // SPECIFICITY 2: Counts pseudo-class selectors.
  // A regex for pseudo classes with brackets. For example:
  //   :nth-child()
  //   :nth-last-child()
  //   :nth-of-type()
  //   :nth-last-type()
  //   :lang()
  var pseudoClassWithBracketsRegex = /(:[\w-]+\([^\)]*\))/gi;
  selector = replaceWithEmptyText(
      selector, specificity, pseudoClassWithBracketsRegex, 2);
  // A regex for other pseudo classes, which don't have brackets.
  var pseudoClassRegex = /(:[^\s\+>~\.\[:]+)/g;
  selector = replaceWithEmptyText(selector, specificity, pseudoClassRegex, 2);

  // Remove universal selector and separator characters.
  selector = selector.replace(/[\*\s\+>~]/g, ' ');

  // Remove any stray dots or hashes which aren't attached to words.
  // These may be present if the user is live-editing this selector.
  selector = selector.replace(/[#\.]/g, ' ');

  // SPECIFICITY 3: The only things left should be element selectors.
  var elementRegex = /([^\s\+>~\.\[:]+)/g;
  selector = replaceWithEmptyText(selector, specificity, elementRegex, 3);

  return specificity;
}
function calculateSpecificity ( selector ) { var specificity = [ 0 , 0 , 0 , 0 ] ; // Cannot use RegExp literals for all regular expressions, IE does not accept // the syntax. // Matches a backslash followed by six hexadecimal digits followed by an // optional single whitespace character. var escapeHexadecimalRegex = new RegExp ( '\\\\[0-9A-Fa-f]{6}\\s?' , 'g' ) ; // Matches a backslash followed by fewer than six hexadecimal digits // followed by a mandatory single whitespace character. var escapeHexadecimalRegex2 = new RegExp ( '\\\\[0-9A-Fa-f]{1,5}\\s' , 'g' ) ; // Matches a backslash followed by any character var escapeSpecialCharacter = / \\. / g ; selector = replaceWithPlainText ( selector , escapeHexadecimalRegex ) ; selector = replaceWithPlainText ( selector , escapeHexadecimalRegex2 ) ; selector = replaceWithPlainText ( selector , escapeSpecialCharacter ) ; // Remove the negation pseudo-class (:not) but leave its argument because // specificity is calculated on its argument. var pseudoClassWithNotRegex = new RegExp ( ':not\\(([^\\)]*)\\)' , 'g' ) ; selector = selector . replace ( pseudoClassWithNotRegex , '     $1 ' ) ; // Remove anything after a left brace in case a user has pasted in a rule, // not just a selector. var rulesRegex = new RegExp ( '{[^]*' , 'gm' ) ; selector = selector . replace ( rulesRegex , '' ) ; // The following regular expressions assume that selectors matching the // preceding regular expressions have been removed. // SPECIFICITY 2: Counts attribute selectors. var attributeRegex = new RegExp ( '(\\[[^\\]]+\\])' , 'g' ) ; selector = replaceWithEmptyText ( selector , specificity , attributeRegex , 2 ) ; // SPECIFICITY 1: Counts ID selectors. var idRegex = new RegExp ( '(#[^\\#\\s\\+>~\\.\\[:]+)' , 'g' ) ; selector = replaceWithEmptyText ( selector , specificity , idRegex , 1 ) ; // SPECIFICITY 2: Counts class selectors. var classRegex = new RegExp ( '(\\.[^\\s\\+>~\\.\\[:]+)' , 'g' ) ; selector = replaceWithEmptyText ( selector , specificity , classRegex , 2 ) ; // SPECIFICITY 3: Counts pseudo-element selectors. var pseudoElementRegex = / (::[^\s\+>~\.\[:]+|:first-line|:first-letter|:before|:after) / gi ; selector = replaceWithEmptyText ( selector , specificity , pseudoElementRegex , 3 ) ; // SPECIFICITY 2: Counts pseudo-class selectors. // A regex for pseudo classes with brackets. For example: //   :nth-child() //   :nth-last-child() //   :nth-of-type() //   :nth-last-type() //   :lang() var pseudoClassWithBracketsRegex = / (:[\w-]+\([^\)]*\)) / gi ; selector = replaceWithEmptyText ( selector , specificity , pseudoClassWithBracketsRegex , 2 ) ; // A regex for other pseudo classes, which don't have brackets. var pseudoClassRegex = / (:[^\s\+>~\.\[:]+) / g ; selector = replaceWithEmptyText ( selector , specificity , pseudoClassRegex , 2 ) ; // Remove universal selector and separator characters. selector = selector . replace ( / [\*\s\+>~] / g , ' ' ) ; // Remove any stray dots or hashes which aren't attached to words. // These may be present if the user is live-editing this selector. selector = selector . replace ( / [#\.] / g , ' ' ) ; // SPECIFICITY 3: The only things left should be element selectors. var elementRegex = / ([^\s\+>~\.\[:]+) / g ; selector = replaceWithEmptyText ( selector , specificity , elementRegex , 3 ) ; return specificity ; }
Calculates the specificity of CSS selectors
@see http://www.w3.org/TR/css3-selectors/#specificity
@see https://github.com/keeganstreet/specificity
@see https://specificity.keegan.st/
@param {string} selector
@return {!Array<number>} The CSS specificity.
Calculates the specificity of CSS selectors