javascript - Parsing CSS by javascript. Inconsistency across Edge and Chrome
问题描述
I am parsing with JS a CSS and I am trying to get the Unicode integer value of the "content" CSS rule but it's being handled differently across Edge and Chrome.
In Edge, the 'content' is a string of 7 chars:
In Chrome, it's a string of 3 chars:
csDef
is my JS variable.
Here's how the CSS rule looks like:
Why is the value treated differently across the web-browses? And in JS, and how can I get the Unicode integer value correctly across these web-browsers?
EDIT:
Here's how I load the CSS rules:
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
is the content of a file obtained by using a File
object, I have an input type="file"
and user selects the file from disk.
解决方案
免责声明:我没有明确的答案,但我从分析中学到了很多,我认为结果可能会引起其他人的兴趣。
首先,让我分享两个测试用例。基于 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说:
如果 property 是声明中 CSS 声明的属性名称的区分大小写匹配,则返回调用 序列化该声明的 CSS 值的结果。
……这就是我完全迷路的地方。
无论如何,我们谈论的是仍在积极开发中并且需要由不同供应商实现的复杂 Web 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";}'));
PS我最初对此发表的一些评论\f102
是完全错误的。这是一个完全有效的CSS 字符转义:
转义以反斜杠开头,后跟表示字符的十六进制 Unicode 代码点值的十六进制数字。
… 映射到一个完全有效的 Unicode 字符,尽管它位于Private Use Area块中:
根据定义,Unicode 联盟不会分配字符的一系列代码点。[...] 故意将它们保留为未定义,以便第三方可以定义自己的字符,而不会与 Unicode 联盟分配冲突。
换句话说,它是为私人使用而保留的。有哪些用途?例如,您似乎正在使用的Ionicons 字体图标(将符号映射到未使用的 Unicode 位置的常规字体,因此它不会干扰常规文本):
<link href="https://unpkg.com/ionicons@4.2.2/dist/css/ionicons.min.css" rel="stylesheet">
<i class="icon ion-ios-add"></i>
推荐阅读
- python - 将numpy 2d数组分成相等的部分
- amazon-web-services - CodeBuild 提取到 S3 存储桶中的文件夹
- reactjs - Material-UI - TypeScript - 通用自动完成
- protocol-buffers - 通过 UDP 解码 protobuf
- ssis - 尝试在 SSIS 中加载带有平面文件源的 UTF-8 CSV 文件,不断收到错误消息说它是 ANSI 文件格式
- cakephp - CakePHP 4 多个复选框
- c++ - 如何通过 MATLAB 引擎将 C++ 数组数据发送到 MATLAB
- kubernetes - 在具有特定标签的节点上获取 pod
- parameters - 迭代器的通用可变和非可变参数
- sql - 未包含在组中的非聚合值在哪里?