我试图理解为什么某些HTML属性未通过W3C验证。我在一个真实的代码库中遇到了这种情况,但这里有一个最小的复制:
<!DOCTYPE html><html lang="en"><head><title>a</title></head><body>
<img alt="1" src="⭐">
<img alt="2" src="/⭐">
<img alt="3" src="/a⭐">
<img alt="4" src="/a/⭐">
<img alt="5" src=" ">
<img alt="6" src="/ "> <!-- Only this is invalid. -->
<img alt="7" src="/a ">
<img alt="8" src="/a/ ">
</body></html>
W3C验证器只报告一个错误,影响第六个图像:
错误:元素
img
上属性src
的值/
错误:路径段中不允许有非法字符:?
。<img alt="6" src="/ ">
为什么只有这一个问题,而不是其他问题?它有什么不同?
问题中描述的行为是由检查器(验证器)代码中的一个错误引起的,该错误现已修复;看见https://github.com/validator/galimatias/pull/2.这个错误没有被注意到,因为测试套件没有覆盖相对URL的情况,该URL以斜杠开头,后跟大于U+FFFF的代码点,就像问题中的U+1F30(彩虹)字符一样。因此,测试套件也进行了更新,以增加对该案例的覆盖范围;看见https://github.com/web-platform-tests/wpt/pull/36213.
顺便说一句,U+2b50(⭐)case没有受到错误的影响,而U+1F308()的情况是:Java使用UTF-16,而U+1 F308在所谓的补充字符(即U+FFFF之上的一组代码点)的范围内,因此,正如上面的注释中所指出的,在UTF-16中,代码点U+1F3308由两个char
值的代理对表示,而U+2b50由一个char
值表示。
char
值数量的差异影响URL解析方式的原因是,HTML检查器的URL解析代码中的状态机维护了一个字符索引,并在状态更改期间递减。因此,如果它处理的URL段可以包含U+FFFF以上的代码点,那么它必须明智地将索引减少多少个字符——对于U+FFFF以上的代码,它需要减少2个字符,否则需要减少1个字符。
为此,代码有一个decrIdx()
方法,它调用Character.charCount()
:
确定表示指定字符(Unicode代码点)所需的
char
值的数目。如果指定的字符等于或大于0x10000,则该方法返回2。否则,该方法返回1。
因此,对检查器进行的代码更改用更智能的启用Character.charCount()
的decrIdx()
调用取代了索引值的简单idx--
递减。