我正在用JS解析CSS,并试图获取“内容” CSS规则的Unicode整数值,但是在Edge和Chrome中,它的处理方式有所不同。
在Edge中,“内容”是7个字符的字符串:
在Chrome中,它是3个字符的字符串:
csDef
是我的JS变量。
这是CSS规则的样子:
为什么在网络浏览中对价值的对待不同? 在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"
,用户从磁盘中选择了文件。
答案 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>€</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>