通过javascript解析CSS。 Edge和Chrome不一致

时间:2018-11-29 16:35:58

标签: javascript css google-chrome microsoft-edge

我正在用JS解析CSS,并试图获取“内容” CSS规则的Unicode整数值,但是在Edge和Chrome中,它的处理方式有所不同。

在Edge中,“内容”是7个字符的字符串:

enter image description here

在Chrome中,它是3个字符的字符串:

enter image description here

csDef是我的JS变量。

这是CSS规则的样子:

enter image description here

为什么在网络浏览中对价值的对待不同? 在JS中,如何在这些网络浏览器中正确获取Unicode整数值?

编辑:

这是我加载CSS规则的方式:

        var rulesForCssText = function (styleContent) {
            var doc = document.implementation.createHTMLDocument(""),
                styleElement = document.createElement("style");

            styleElement.textContent = styleContent;
            doc.body.appendChild(styleElement);

            return styleElement.sheet.cssRules;
        };

       var cssDefs =  Array.from(rulesForCssText(fileContent));

fileContent是使用File对象获得的文件的内容,我有一个input type="file",用户从磁盘中选择了文件。

1 个答案:

答案 0 :(得分:0)

免责声明 :我没有确切的答案,但我从分析中学到了很多东西,我认为结果可能值得关注其他人。


首先,让我分享两个测试用例。基于CSS的代码再现了您描述的问题:

var d = document.implementation.createHTMLDocument("");
var s = document.createElement("style");
s.textContent = '.foo{content: "\\20ac";}';
d.body.appendChild(s);
var c = s.sheet.cssRules[0].style.getPropertyValue("content");
console.log("String '%s' has length %d", c, c.length);

台式机Firefox和Chrome呈现数字字符引用(String '"€"' has length 3),而Edge则不呈现(String '"\20ac"' has length 7)。

有趣的是,第二个基于HTML的测试用例似乎没有任何问题:

var s = document.getElementsByTagName("span")[0].textContent;
console.log("String '%s' has length %d", s, s.length);
<span>&#x20ac;</span>

两个浏览器都呈现实体(String '€' has length 1)。

那么,谁在这里? CSS Object Model (CSSOM) Editor’s Draft说:

  

如果属性是区分大小写的CSS属性名称匹配   声明中的声明,然后返回调用结果   serialize a CSS value的声明。

...这就是我完全迷路的地方。

无论如何,我们所说的是复杂的Web API,这些API仍在积极开发中,需要由不同的供应商来实施。无论是某个特定实现中的错误还是规范中的遗漏(不太可能),这都是代码需要处理的问题。起点可能是:

function browserRendersCharacterReferences() {
  var d = document.implementation.createHTMLDocument("");
  var s = document.createElement("style");
  s.textContent = '.foo{content: "\\20ac";}';
  d.body.appendChild(s);
  return s.sheet.cssRules[0].style.getPropertyValue("content").length === 1;
}

function renderCharacterEntities(t) {
  // THIS FUNCTION IS WRONG, DON'T USE IT, IT'S JUST A QUICK EXAMPLE
  var r = /\\([\da-f]{4})\s?/gi;
  t = t.replace(r, function (match, codePoint) {
    return String.fromCharCode(parseInt(codePoint, 16));
  } );
  return t;
}

function rulesForCssText(css) {
  var d = document.implementation.createHTMLDocument("");
  var s = document.createElement("style");
  var c;
  s.textContent = css;
  d.body.appendChild(s);
  c = s.sheet.cssRules[0].style.getPropertyValue("content");
  if (!browserRendersCharacterReferences()) {
    c = renderCharacterEntities(c);
  }
  return c;
}

console.log(rulesForCssText('.foo{content: "\\20ac  and \\f102";}'));


P.S。我最初对\f102发表了一些明显错误的评论。这是完全有效的CSS character escape

  

转义符以反斜杠开头,后跟十六进制数字   表示字符的十六进制Unicode代码点值。

…映射到一个完全有效的Unicode字符,尽管在Private Use Area块中是一个字符:

  

根据定义,Unicode联盟不会分配字符的一系列代码点。 […]故意将它们保留为未定义状态,以便第三方可以定义自己的字符而不会与Unicode Consortium分配冲突。

换句话说,它保留供私人使用。有什么样的用法?例如,您似乎正在使用的Ionicons Font Icon(一种常规字体,它将符号映射到未使用的Unicode位置,因此不会干扰常规文本):

<link href="https://unpkg.com/ionicons@4.2.2/dist/css/ionicons.min.css" rel="stylesheet">
<i class="icon ion-ios-add"></i>