如何在Javascript中计算css规则优先级?

时间:2016-09-04 18:16:03

标签: javascript css

我已创建此代码来计算css规则优先级

var selectorText = "body";
A = selectorText.match(/#/gm); // id
A = !A ? 0 : A.length;
B1 = selectorText.match(/\\./gm); // class
B1 = !B1 ? 0 : B1.length;
B2 = selectorText.match(/[[]/gm); // attribute selector
B2 = !B2 ? 0 : B2.length;
B3 = selectorText.match(/[\\w\\d_\\s^]:(?!:)/gm); // pseudo třída
B3 = !B3 ? 0 : B3.length;
B = B1 + B2 + B3;
C1 = selectorText.match(/::/gm); // pseudo element
C1 = !C1 ? 0 : C1.length;
C2 = selectorText.match(/\\w+[$\\s#\\.:\\[]/gm); // element
C2 = !C2 ? 0 : C2.length;
C = C1 + C2;
A *= 10000;
B *= 100;
alert(C)

选择器中的匹配项不得超过100个(A,B或C)。 由于某种原因,C的结果是0(但我使用“body”选择器)。你能建议如何纠正最后一场比赛吗?你也看到代码中有任何错误吗?

注意:

原始问题只是“body”选择器,但我想到任何选择器或多个这样的选择器:“div#menu ul li,div#id,div.class”选择器可以包含伪类,伪元素,属性选择器。在C2正则表达式的情况下,我试图找到在最后一个字符串中总共有5个元素的元素数(然后C2应该是5)。

2 个答案:

答案 0 :(得分:2)

selectorText不包含::C1 = selectorText.match(/::/gm);应该返回null; C1 = !C1 ? 0 : C1.length;返回0; C2 = selectorText.match(/\\w+[$\s#\\.:\\[]/gm);返回nullC2 = !C2 ? 0 : C2.length;返回0; C = C1 + C2;等于0;那是0 + 0 = 0

  

原始问题只是“身体”选择器,但我想到了   任何选择器或多个选择器如下:“div#menu ul li,div#id,   div.class“选择器可以包含伪类,伪元素,   属性选择器。在C2正则表达式的情况下,我试图找到   最后一个字符串中的元素总数为5个元素   (那么C2应该是5)

您可以.split()RegExp /,|\s/一起使用,字符分割多个选择器; .map().filter(Boolean)删除空字符串.match()RegExp /^[a-z]+(?=[.#:\s]|$)/i以匹配元素。

var selectorText = "div#menu ul li, div#id, div.class";
C2 = selectorText.split(/,|\s/).filter(Boolean)
     .map(el => el.trim().match(/^[a-z]+(?=[.#:\s]|$)/i)[0]);
console.log(C2);

答案 1 :(得分:0)

首先,我需要解决如何解析多个选择器的问题。正如Oriol所说,我不能用正则表达式解析多个选择器。这个功能可以满足我的需要。

String.prototype.findStrings = function (s = ',') {
  var prev = null, prevEscaped = null, typq = null, 
      typp = null, depRB = 0, depSB = 0;  
  var obj = { length: 0, 
    results: { array: [], A: null, B: null, C: null }
    };
  var action = null;
  if (s.constructor === Array)
    {
    action = 1;
    }
  else
    {
    if (typeof s === 'string' || s instanceof String)
      action = 0;
    }
  if ( action === null)
    return false;
  for (var i=0; i<this.length; i++)
    {
    // not escaped:
    if (!prevEscaped)
      { // not escaped:
      switch (this[i])
        {
        case '\\':
          prevEscaped = true;
          prev = '\\'; // previous escaped
        break;
        case '"':
          if (!typq)
            {
              typq = '"';
            }
          else if ( typq=='"' ) 
            { // end quotes
              typq = null;
              continue;
            }
        break;
        case "'": 
          if (!typq)
            {
            typq = "'";
            }
          else if ( typq=="'" ) 
            { // end quotes
            typq = null;
            continue;
            }
        break;
        }
      }
    else
      {  // is escaped - do nothing
      prevEscaped = false;
      prev = null;
      continue;
      }

    if (!typq) // no quotes block
      {
      switch (this[i])
        {
        case '(':
          if (!typp)
              typp = '('; // defines higher priority of () parenthesis
          depRB++;
        break;
        case "[": 
          if (!typp)
              typp = '[';
          depSB++;
        break;
        case ")": 
          depRB--;
          if (!depRB)
            {
            if ( typp == "(" )
              {
              typp = null; // end block of parenthesis
              continue;
              }
            }
        break;
        case "]": 
          depSB--;
          if (!depSB)
            {
            if ( typp == "[" )
              {
              typp = null; // end block of parenthesis
              continue;
              }
            }
        break;
        }
      }
    if (typp)    // commas inside block of parenthesis of higher priority are skipped
      continue;

    if (!action) // Separate by string s
      {
      if ( this[i] == s )
        { 
        obj.results.array.push(i);
        obj.length++;
        }
      }
    else 
      {
      }    
    // Block of no quotes, no parenthesis follows

    } // end for

  // Last item
  obj.results.array.push(i);
  obj.length++;
  return obj;
};
/* Return array of strings */
String.prototype.splitFromArray = function (arr, autotrim = true) {
  var prev = 0, results = [];
  for (var i = 0; i<arr.length; i++)
    {
    var s = "";
    s = this.substring(prev+1,arr[i]).trim();    
    results.push( s );
    prev = arr[i];
    }
return results;
};

这是这样实现的:

var test = '#a > :matches(.b, #c) , input.match(title="\\City \\"of ' + "'" + 'silly' + "'" +' people.", data=' + "'alpha=" + '"' + "string" + '"' + ",beta=2'" + ' value="New York"), article.class1 ul li'; 
var separators = test.findStrings();
console.log(separators);
var myArr = test.splitFromArray(separators.results.array);
console.log(myArr);

很抱歉,选择器在示例中无效,但这只是说明解析。您可以对其进行编辑以获得有效的选择器。

添加搜索规则并不难。