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

如何在Javascript中计算css规则优先级?,javascript,css,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

我创建了这个代码来计算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”选择器,但我认为任何选择器或多个选择器都是这样的:“div#menu ul li、div#id、div.class”选择器可以包含伪类、伪元素、属性选择器。在C2正则表达式的情况下,我试图找到最后一个字符串中的元素总数为5个元素(那么C2应该是5个元素)。
selectorText
不包含
::
C1=selectorText.match(/::/gm)
应返回
null
<代码>C1=!C1?0:C1.5cm返回
0
C2=selectorText.match(/\\w+[$\s\\\.:\\[]/gm)
返回
null
C2=!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(布尔值)
.map(el=>el.trim().match(/^[a-z]+(?=[.#::\s]|$)/i)[0]);

console.log(C2);
selectorText
不包含
C1=selectorText.match(/::/gm);
应返回
null
C1=!C1?0:C1.length;
返回
0
C2=selectorText.match(/\\w+[$\s\\:\[\\[]/gm)
返回
null
C2=!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(布尔值)
.map(el=>el.trim().match(/^[a-z]+(?=[.#::\s]|$)/i)[0]);

console.log(C2);
首先,我需要解决如何解析多个选择器的问题。正如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;
};
很抱歉,示例中的选择器无效,但这只是说明解析。您可以编辑它以获得有效的选择器


添加搜索规则并不困难。

首先,我需要解决如何解析多个选择器的问题。正如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;
};
很抱歉,示例中的选择器无效,但这只是说明解析。您可以编辑它以获得有效的选择器


添加搜索规则并不难。<>代码>选择文本> /代码>不包含代码>:/>代码>代码>匹配(//://GM)应该返回<代码> null <代码>。不能用正则表达式解析CSS。或者至少不这样。例如,考虑代码< > A,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>:匹配(.b ^#c)”;
我可以使用.replace搜索括号中的内容并替换它。@user1141649是否要替换括号中的逗号?这可能可行,但JS中的正则表达式无法处理递归,嵌套括号的数量可以是任意的。然后,您需要撤消替换以计算特定的Type的<代码> > b,y> C >代码> >不包含<代码>:/<代码> >代码>匹配(//://GM)应该返回<代码> null >代码>不能用正则表达式解析CSS。或者至少不是这样的。例如,考虑代码< > A,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>:匹配(.b ^#c)”;
我可以使用。替换以搜索方括号的内容