【问题标题】:how to calculate css rules priority in Javascript?如何在Javascript中计算css规则优先级?
【发布时间】:2016-09-05 18:45:11
【问题描述】:

我创建了这段代码来计算 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)

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

注意:

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

【问题讨论】:

  • selectorText 不包含::.match(/::/,gm) 应该返回null
  • 你不能用正则表达式解析 CSS。或者至少不是这样。考虑例如#a, #b,它的特异性是(1,0,0),但这表示(2,0,0)。并且您不能在逗号处拆分并分别计算每个部分,因为某些操作数有逗号。所以你需要一个 CSS 解析器。
  • @user1141649 你需要一个用 JS 编写的 CSS 解析器来公开这些信息。
  • @Oriol 我可以用var selectorText = "div#id, div.body;#a > :matches(.b, #c)"; 之类的字符串替换逗号来替换“^”之类的字符吗? var selectorText = "div#id, div.body;#a > :matches(.b^ #c)"; 我可以使用 .replace 搜索括号的内容并替换它。
  • @user1141649 您想替换括号内的逗号吗?这可能行得通,但是 JS 中的正则表达式无法处理递归,并且嵌套括号的数量可以是任意的。然后您需要撤消替换以递归计算.b, #c 的特异性。

标签: javascript css


【解决方案1】:

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


最初的问题只是“body”选择器,但我想 像这样的任何选择器或多个选择器:“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);

【讨论】:

  • C2 实际上设置为 0,最初错过了将 C2 重新定义为 0 的下一行
  • 这里不正确,建议尝试/\w+(?=[^a-zA-Z]|$)/gm。尝试/^[a-z]+(?=[.#:\s]|$)/i 匹配字符串开头的单词,后跟.#: 或空格字符或输入结尾
  • C2 = "body".match(/^[a-z]+(?=[.#:\s]|$)/i); 应该返回预期结果;例如,"body.aclass".match(/^[a-z]+(?=[.#:\s]|$)/i);"body#aid".match(/^[a-z]+(?=[.#:\s]|$)/i);"body::apseudo".match(/^[a-z]+(?=[.#:\s]|$)/i);"body #achild".match(/^[a-z]+(?=[.#:\s]|$)/i);
  • 啊,但是不能用\s来分割。请参阅div ul li 是选择器。更好的 .split(",").trim()
  • 不要以逗号分隔,它会破坏像#a > :matches(.b, #c)这样的东西。
【解决方案2】:

首先我需要解决如何解析多个选择器。正如 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);

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

添加搜索规则并不难。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-06
    相关资源
    最近更新 更多