修复Twitter等网站在Chrome的字体显示问题

system-ui

Twitter的默认字体栈是

font-family: system-ui, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", sans-serif;

这里别的都好说,问题就出在system-ui这个。

system-ui这个generic font的设计思路很美好:自动调用系统字体,给用户最原生的体验。这个思路用在移动平台上、甚至Mac OS都没有大问题,但是在Windows上问题就很多。

Windows简中默认的字体是微软雅黑,英文则是Segoe UI。当然,Segoe UI是没有CJK字符的,所以会fallback到其他字体。

微软雅黑最大的问题是中文字符还算不错,但是英文和假名都巨丑无比。所以,一旦调用了雅黑来显示日文、英文内容,立刻变得不堪入目。

对比:

雅黑
微软雅黑
Meiryo
Meiryo

所以,一旦system-ui导致调用了雅黑来显示非中文内容,效果立刻变得很差。

由于system-ui的这个问题,有许多主流网站已经刻意将system-ui从其字体栈中删除,例如GitHubBootstrap等等。不知道为什么Twitter目前还没有跟进(而且没记错的话,Twitter是换了新版界面之后才专门加上了system-ui)。这里有个CSSWG的相关讨论(发帖人是Chrome/Google团队的CJK字体专家Koji Ishii)。

Chrome对于system-ui的处理

不过既然标题专门提到了“Chrome”,就知道这事情没有这么简单。

确实,system-ui的behavior在Chrome和Firefox是不一致的。其核心区别在于,如何处理lang参数。

很久以前在S1发过一贴专门讲不同浏览器不同语言的fallback机制(待更新),不过这里不展开。具体到这个问题,就是Firefox面对system-ui,仍然会根据语言来选择在选项里设置的字体,而Chrome会原封不动的直接套用系统默认字体——对于简体中文Win来说,就是微软雅黑。

回到Twitter上的话,Twitter其实有个很优秀的功能就是对于每条tweet会自动分析语言,然后给那个div套上lang='xx'的选项。所以,大部分日文推是已经加了lang=ja了的(如果没加这个问题会变得更复杂)。对于Firefox,面对system-ui,看到lang=ja他会先选择你设置的日文默认无衬线字体——没记错的话默认是Meiryo——显示效果就比较美观。而Chrome里则会无脑显示为微软雅黑。

用这个HTML可以很快速地对比两者。

可以看到,对于指定了“Segoe UI”的场合,由于Segoe UI无法显示CJK字符,会fallback到其他字体。这里,无论是Firefox还是Chrome都会根据lang来选择合适的fallback字体(ja=Meiryo、zh-cn=雅黑。en的话,由于我浏览器语言优先级是zh>ja,也是雅黑)。

对于指定了system-ui的场合,Firefox的逻辑是和其他西文字体完全一样的,对于CJK字符会根据语言选择fallback字体。唯一的区别在于这里对于lang=en的场合他是选用了有衬线字体TNR,因为Firefox字体设置里对于Latin的默认比例字体是衬线而不是无衬线。不过一般网站的CSS都会在字体最后指定sans-serif,所以实践中不会见到。

补充:我后来听说,Firefox似乎其实根本就不支持system-ui这个关键字。所以其效果等价于根本不加这个关键词。但是上面的分析的结论也没错就是了。

而Chrome那边如上文所述,会直接选用雅黑。由于雅黑字符集全,自然所有字符都雅黑了。假名巨丑,中日不同形的字符也会变成中文字形(这里的“将”)。另外,Chrome对于lang=en汉字会fallback到宋体而不是微软雅黑也是个多年以来的quirk了,我倒是不是特别不喜欢宋体所以不是太有所谓。

另外,强调一遍以上的都是在简中系统测试的。如果你的系统是英文,那默认字体则是Segoe UI,所以是从小(字符集)往大(字符集)fallback,不会受到雅黑的污染。

Workaround

在Chrome 78之前,我是使用了一个全局的Stylus rule来对付system-ui的:

@font-face {
    font-family: system-ui;
    src: local("Segoe UI");
}

但是在Chrome 79之后,你无法再使用@font-face来重新定义保留关键字了,说是这样才符合标准(那个标准我读了几遍都读不出这层意味,专门去CSSWG问了下,不过那边的专家都说确实不应该能覆盖。另外,Firefox从来就不支持用@font-face覆盖generic keyword。)

既然现在不行了,那只好手动替换Twitter了:

@-moz-document domain("twitter.com") {
* {
font-family: "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", sans-serif !important;
}
}

顺便一提,我还替换了几个在Windows字体渲染效果极差的字体:

@font-face {
font-family: "M PLUS 1p";
src: local("Meiryo");
}
@font-face {
font-family: "mplus-1p-regular";
src: local("Meiryo");
}
@font-face {
font-family: "M PLUS 1p";
font-weight: bold;
src: local("Meiryo Bold");
}

浏览器对full range视频的支持

为什么会去折腾full range video这个小众的东西?这次还真不是我闲的蛋疼,事实是我发现很多Twitch直播已经开始用full range了(例子有现在火热进行中的Supermajor(PGL)和之前的Epicenter),然后用Firefox看就发现颜色不对,对比度爆表。

之前有“控诉”过Firefox对视频的支持程度落后Chrome一个世纪,当时提出了几个Chorme支持、Firefox不支持的东西:

  • RGB视频
  • 4:4:4或者4:4:2视频
  • Full range视频
  • 对nV显卡的支持不好

当然,这几条还是对的,但是我今天发现Chrome对full range的支持也不是完美,所以还是客观起见,详细说明一下。

说到这个话题,不得不先重复一遍我之前在各种场合提过多次的所谓“对nV显卡的支持不好”具体啥意思。其实,就是在Win 7 + nVidia显卡的默认设置下,Firefox播放视频的色域(color range)会错误。这里的“错误”,严谨地说是limited range(就是99%的视频)不会正确拉伸到full range。

这个问题的产生原因是Win7不支持D3D11 DXVA,而Firefox没有对D3D9 DXVA进行优化。其实,之前Chrome也有这个bug,但是在我提出之后Chrome几个月后就修复了。这个问题的解决方案,除了换A/I GPU或者升级到Win 10这种废话,就是

  1. 软解视频,即把media.hardware-video-decoding.enabled设为false
  2. 修改nVidia控制面板的一个设置,从“通过视频播放器设置”改成手动设为full range:

QQ图片20180609164804

我之前一直是用2,倒是不会影响本地播放器的播放(本地播放器我本来就没开DXVA)。

现在说回full range视频的解码。先说Chrome那边:软解的情况下(设置chrome://flags/#disable-accelerated-video-decode 为Disabled),完美无缺。硬解就不太行了,会把视频强行进行一次伸张,导致颜色被clip。我发的bug ticket在此,这里有个视频可以测试:

当然,你也可以去上述的控制面板手动改成“limited”,来让他不伸张,所以正好得到正确的颜色,但是很显然这样又会毁掉所有的limited range的视频的颜色,所以还是老老实实软解吧。

Firefox除了硬解和Chrome有一样的问题以外,软解也不行——我发的ticket在此

基本内容就是这些了,顺便讲下上面那个视频是怎么造出来的。首先自然是ps里把那个图画出来,然后用FFMPEG做。上次已经提到了记得要加-vf scale=out_color_matrix=bt709来保证输出的YUV是BT.709的,那么full range怎么处理?我网上搜了下意外地发现相关信息相当少,一开始搜到一个什么-color_range 2(这个参数ffmpeg的documentation根本没提到啊喂),后来发现效果其实就是强行在元数据里塞个full range,结果视频的像素数值还都是16-235范围内的,出来就是个灰暗的视频囧。

最后在这贴搜到原来要用-pix_fmt yuvj420p才能输出0-255的视频。-color_range 2都不用加,出来的视频自动metatag都是full range了。我用的完整命令行如下:

ffmpeg -loop 1 -i colortest_hd.bmp -vf scale=out_color_matrix=bt709 -color_primaries 1 -color_trc 1 -colorspace 1 -t 30 -pix_fmt yuvj420p out_420_709_full.mp4

修改content-disposition解决Firefox无法直接打开种子等文件的问题

Firefox有个问题,就是对于某些文件类型,即使你在设置里设置了“始终使用XXX打开”:

001

部分站点击下载该类型文件时仍然会出来弹窗询问。这个问题已经困扰我很多年,其背后原理其实也早已知晓:凡是response header有content-disposition: attachment的HTTP request,即便是有“始终用XXX打开”的设置,也依然会弹出下载框(仅限“Use xxx application”的情况;如果你设的是保存到本地,倒是可以免询问下载)。

根据Bugzilla的ticket,这么设是为用户的安全考虑,防止稀里糊涂就用本地程序打开了什么恶意文件。虽然我个人觉得完全站不住脚:如果网站真的想这么干,他把content-disposition设成别的不就完了?

这个问题最烦的就是种子文件,因为99%的情况我是要直接用uT打开的。常去的tracker里,只有eh的tracker有这个问题,其他几家,DMHY用的是content-type: application/octet-stream,所以根本没有content-disposition的问题;nyaa.si用的则是content-disposition: inline,也无问题。

在pre-57年代其实就有个扩展叫InlineDisposition(还有无数克隆,57能用的应该是这个),可以自动把一切content-disposition: attachment变成inline,但是缺点在于

  1. 没有filter,什么都会变成inline,包括一些网站的图片下载链接也会变成在浏览器里打开,很不方便;
  2. 会导致很多文件下载时文件名乱码——这个更烦一点。为什么?这里按下不表,后面我们会专门谈起。

所以,我也就一直这么忍了过来,就是每次在eh下种子都要多点那么一下确认。

使用Header Editor替换种子文件的 header

今天,我突然发现Header Editor这款很不错的国产插件居然也有修改response header的功能,于是稍微调试了一下,果然可以搞定eh的tracker了。具体规则么,也很简单,就是

  • Rule type:Modify response header,
  • Match type:Domain,
  • ehtracker.org,
  • Execute type:normal
  • Header name:content-disposition
  • Header value:inline

就OK。不过这有个问题:你没发现一个站搞这一出,你就得重新加一条。

通过参考HE的评论区某人的评论,我发现可以用Custom function的方式来处理:先把上面的Rule的Match type改成All,以及Execute type改成Custom function,然后输入以下代码:


for (let a of val) {
if (a.name.toLowerCase() === 'content-disposition' &&
a.value.match(/\.torrent"?$/iu)) {
let res = "inline";
console.log("res: " + res);
a.value = res;
break;
}
}

view raw

1.js

hosted with ❤ by GitHub

不过这里有个小问题,因为我们简单粗暴地把整个content-disposition header给替换成了inline,而没有保持原有的filename字段。虽然对于我们直接打开其实没有什么影响,但是强迫症作祟,我想能否用正则,仅替换最前面的“attachment”为inline,后面的还保留?

let res = a.value.replace(/^attachment/iu, "inline");

这样的形式思路应该没问题,但是实际操作中,会发现这么一改,我发现有时候会导致整个修改完全失效,又回退到原始的header。这是怎么回事呢?

Header的编码

这就不得不牵扯到一个很重要的Header的编码问题了。

拿这个 Ehtracker这个种子为例:

https://ehtracker.org/get/1111939/8ac51291db878d860b7d064be9745ae838a0b7eb.torrent

先观察原始header(这里顺便一提,用Firefox的网络控制台永远只能看到原始header,看不到插件更改之后的):

003

奇怪,文件名部分居然是乱码?但是,在对话框或者真正保存下来的时候却正常:

004

稍加研究,原来HTTP Header的编码(曾)是限制在ISO-8859-1,直到RFC2047起才允许使用其他编码。在实践上,仍在大量使用ISO-8859-1,甚至绝大部分字段只用ASCII。

至于ISO-8859-1,也就是所谓Latin-1,你就大概理解成和GBK类似的西方的二字节编码就行。那么我们把刚才那个字段复制出来:

(C92) [比村乳業 (比村奇石)] 月曜日のたわわ そのIV (オリジナル).zip.torrent

然后用Python稍微处理一下:

mystring = '(C92) [比村乳業 (比村奇石)] 月曜日のたわわ そのIV (オリジナル).zip.torrent'
mystring.encode(encoding='iso-8859-1').decode('utf-8')

输出:'(C92) [比村乳業 (比村奇石)] 月曜日のたわわ そのIV (オリジナル).zip.torrent’

符合预想。

JS的话,原生Byte和多编码转换的支持极为贫乏,一般都得用库,但是这个特例可以用一个trick:

decodeURIComponent(escape('比村奇石'))

这个trick之所以能工作,是因为escape函数是基于RFC 1738,所以用的是latin-1 encoding来encode(是编码成百分号的URL encoding形式,例如ƒ=%83(83是16进制下该符号在latin-1的码位);但是decodeURIComponent却是decode UTF-8 encoding下的URL encoding的字符用的,所以这个操作就相当于latin-1编码成byte再utf-8解码成字符串,也就是还原了我们的真实字符串。

上面是讲我们自个儿如何来翻译这串乱码。那Firefox自己在处理时,工作顺序大概有两种可能:

  1. 从字节码开始
    • ->直接用UTF-8解码->真实文件名字符串
    • ->同时用Latin-1解码->显示为dev tools里那串乱码
  2. 从那串乱码字符串开始
    • ->用Latin-1编码为Byte->用UTF-8解码->得到真实文件名字符串
    • ->直接显示dev tools里那串乱码

虽然浏览器最底层肯定从byte开始处理,而不是字符串,但是这里有必要区分一下两种情况——因为我们替换的时候只能替换字符串而不是byte,所以其实我们的流程更接近2,但是要倒过来:

你的原始非ASCII字符串->用UTF-8编码成byte->用latin-1解码成乱码字符串

当你搞出来这坨乱码字符串之后,替换原始header,Firefox会再按照上面流程2的分支一处理,给你搞出正确的文件名来。

如果你不这么做,直接上汉字比如

a.value = 'attachment; filename=\"汉字.txt\"'

Firefox会发现第一步用latin-1编码就失败(因为超出了latin-1的字符范围了),于是他直接catch错误跳出,完全忽视你对response header的替换,而改用回原始的header了。

至于制作乱码字符串的方法,自然也就是把前面的反过来:

unescape(encodeURIComponent("呵"))

用Python的话就是:

mystring = '呵'
b.encode(encoding='utf-8').decode('iso-8859-1')

输出是å\x91µ,复制到我们刚才的脚本里(没错,包括转义符\x91),稍微简化下:

for (let a of val) {
if (a.name.toLowerCase() === 'content-disposition') {
console.log("orig: " + a.value);
a.value = 'attachment; filename=\"å\x91µ.txt\"';
break;
}
}

然后再点击上面ehtracker那个链接试试,变成“呵.txt”了吧?

我还有个有趣的发现。上面我们看到我们是先把我们的字符串用UTF-8编码成byte,然后byte按Latin-1解码成那串乱码对吧?其实最开始的编码也支持本地locale,对我来说就是GBK:

mystring = '呵'
b.encode(encoding='gbk').decode('iso-8859-1')

这回输出变成了ºÇ,到上面的脚本里替换一下,再点ehtracker的链接,依然可以获得“呵.txt”的文件名。当然,如果你的系统不是简体中文,我就不能保证也工作了。

当然,这俩不能混用,要么就全GBK,要么就全UTF-8。否则轻则部分乱码,重则直接挂掉。

不过细心的读者可能会发现:HE工作时,他读取到的原始header里的字符串应该就是乱码字符串,如果仅仅是替换最前面的attachement为inline(都是ASCII字符),应该根本牵扯不到你这一大堆,永远会work才对啊?

咳,这个我研究了一个多小时,甚至自己写了个扩展调试才发现,有可能是因为我有另外一个扩展Download Filename Encoding 已经自己偷偷把乱码字符串给替换成正常了…所以你再直接塞回header Firefox不认。而且这俩扩展的顺序还不一定,所以时好时坏。之所以说有可能,因为有时候哪怕只要重启一下Firefox就无法重现…不过,凡是bug发生的时候,会看到那个字符串在传入HE的时候就已经是正常字符串(而不是乱码字符串)了。

Edit:经过了又长达X(X远大于我愿意承认的数量…)小时的debugging,我终于发现了根本原因:在Firefox release 57左右有一个很短暂的时期,webRequest.onHeadersReceived.addListener给callback的header是原始字符串,而不是latin-1编码的乱码字符串。这个“Bug”恰好影响且只影响目前的Firefox stable (57.0.4),所以我总是无法稳定重现(因为我平时用的是stable,测试都用beta或者Nightly…)

我用mozregression找到的Bug出现的regression window是9月7日,bug消失的fix window是9月28日。前者倒是能看到有和responseHeader有关的东西,但是后者我翻来覆去看了半天也不知道为啥会影响header的编码。嘛不管了不管了。

这里也得顺便提下,我还试了在Chrome下(WebExt确实方便,直接无缝导入Chrome,就是brower这个对象得还改名chrome),Chrome返回的content-disposition header的就不是乱码,而是真实字符串。

同理,你如果要修改的话,Chrome不需要处理,Firefox就得处理,即


let str = '英文3.torrent';
//Chrome:
header.value = `attachment; filename="${str}"`;
//Firefox:
header.value = `attachment; filename="${unescape(encodeURIComponent(str))}"`;

view raw

2.5.js

hosted with ❤ by GitHub

另外,还学了几个新东西:

一、WebExt写个扩展真的好简单……比起原来的XPI啥的。改response header就简单地加个


browser.webRequest.onHeadersReceived.addListener(function(e) {
//修改请求头
for (header of e.responseHeaders) {
if (header.name.toLowerCase() === 'content-disposition') {
header.value = '改成你想要的';
}
}
return {"responseHeaders": e.responseHeaders};
}, {urls: ["<all_urls>"]}, ['blocking', 'responseHeaders']);

view raw

2.js

hosted with ❤ by GitHub

在background的JS里就OK(权限什么的反而相对比较麻烦些)。完整代码(其实也就是这个+manifest.json)在GitHub上。

另外,测试的时候也别老操人家EH了,我做了个http mock:http://www.mocky.io/v2/5a523c8e2e0000a928c03a73

二、RFC 5987新增加了直接用UTF-8记录文件名的方法(SO讨论),语法为

Content-Disposition: attachment; filename*=UTF-8''{URL编码之后的字符串}

例如“你好.txt”就是(用encodeURIComponent帮你编码)

Content-Disposition: attachment; filename*=UTF-8''%E4%BD%A0%E5%A5%BD.txt

而且不需要双引号括起来文件名了,因为空格都被变成%20了。

用JS的话,就是


//Works in both Chrome and Firefox!
header.value = `attachment; filename*=UTF-8''${encodeURIComponent(str)}`

view raw

3.js

hosted with ❤ by GitHub

Firefox “Quantum” revisited

いよいよ明日!终于Firefox正式版也要更新至所谓的Quantum(57)了。自从上文之后,我本想直接试用测试版的57,不过用了两天还是难受的不行,没坚持下来(主要还是tab操作难受),换回了56正式版。那么这又过了一个多月,情况是否有所改善呢?

本文主要针对基于前文提出的那些问题一一讲解,所以请对照观看。前文已经替代掉的插件就略过不写。

FlagFox

依然还没更新,还没决定用哪个替代,不过这个不太重要。

Greasemonkey

彻底换用TM。以后基于这个原则:凡是Firefox和Chrome能通用的都通用,不想折腾。而且TM确实好用,这个没得说(除了强制更新脚本的UI非常啰嗦以外)。过一段研究下用Google Drive能不能实现跨浏览器Sync。

Image Search Options

作者已经自行更新了WE版本。至于效果嘛……我先贴一下这个新版的菜单你感受一下:

is

至于WE版本的限制,你再感受一下:

Due to limitations in the available WebExtensions APIs, the following feature changes needed to be made:

Direct POST no longer works for websites where no new page is generated by a POST request.

To work around the POST issue, an intermediary “Use IMGDATA to URL Host” option has been added. This option uses POST to upload the image to a temporary host, and then uses a URL provided by that temporary host to perform a GET request with the option’s settings. The intermediary host is also used when data uris and other non-usable URLs are encountered if the selected option is not set to use ::$IMGDATA::.

Right click on context menu items is no longer usable for triggering the alternate option settings. This functionality has been replaced with the shift key, and a checkbox added to the context menu. To use the alternate options, hold down the shift key while clicking on a menu item, or first click the ‘Use Alternate’ option checkbox.

It is no longer possible to add multiple options to the main menu, a submenu will be created automaticly.

It is no longer possible to search for images stored on your local system, we will look into alternative solutions for an upcoming version.

嗯这里面要命的是两点:第一个POST必须用服务器中转的方式;但是即使用了服务器中转,也还是不支持本地图片。这个就很烦了,想搜索QQ里的图再也不能拖进浏览器->直接右键搜索了。第二点是UI限制,现在菜单(单个插件?)只支持一个菜单项,所以所有的选项都必须被包在里面很繁琐;然后不支持右键点击调用备用方式(一般是POST),必须shift。总之就是戴着脚镣跳舞咯。

那这么麻烦我还不如直接用Search By Image这个脚本了。这个脚本对于本地图的支持是先呼出菜单,然后把图片拖进菜单里,基本和原来的操作差不多。另外理论上Chrome里还额外支持ctrl+V粘贴进菜单,但是我试了下复制QQ里的图大概由于QQ的剪贴板对象特殊的原因还是不行,所以没啥大用(复制本地图片一般是可以)。不过也有个缺点,不支持网图直接POST/中转的方法搜索(对于某些有referer检查的网站比如exhentai就会有问题。Chrome可以用先右键复制图片到剪贴板的方式workaround一下,Firefox就吃瘪了)。

Image Zoom

本体就不用幻想更新了,上次提到的三个中最接近的Zoom Image更新了2.0版,现在有fit to screen了,只不过快捷键是右键+中键(而且还不能再按一次复原),但是基本属于可以用的范畴。

Pearl Crescent Page Saver screenshot tool

嗯为了找这个的替代品,我试了市场排名靠前的一坨:

screenshot

这里面很多功能都贼多,有非常详尽的编辑工具,如果你比较需要那些,推荐自己去试试。而且这些插件普遍感觉是由专业团队开发,UI非常漂亮,这个点赞。

不过我在意的是一个功能:截网站全屏,要快快快快,而且不要有烦人的肉眼可见的滚动效果。试了前几个(包括我之前用的Page saver的WE版)发现都有滚动,我几乎怀疑是不是WE根本做不到——直到发现了Screengrab!这个。这个功能不多,就是基本的截全站、选择区域、截当前可见等等,但是菜单简练精干,有复制到剪贴板、保存图片等方便的选项,完全符合我的需求。最最重要的当然是,截全屏多快好省,没有滚动(也因此我发现一个效果,对于那种页面上的悬浮框,不会像其他的截图工具那样出现重复好几次的问题)。

Show Location

没希望。

Tab Mix Plus

这边情况还是和上次一样绝望。

而且在试用Firefox 57的几天内我发现个更为蛋疼的问题:在Firefox里,可以做到按Ctrl+tab按最近浏览的顺序切换(即和Windows的alt+tab一样,按一次会回到上一个你用的标签,按住ctrl不放按多次tab以此类推),而不是单纯地左右。这个功能可以排进我心目中的“Chrome不可理喻的缺失功能”TOP 3。不过自从TMP挂掉我才发现,原来早在1年前左右,有两个和Tab切换相关的选项居然合并了:一个是“是否按照最近浏览的顺序切换”,一个是“切换时是否显示略缩图(而非直接切换)”。如果你想“按最近浏览的顺序切换”,就必须同时“切换时显示略缩图而不是直接切换”。

对于这俩选项的合并,开发者是这么说的

Without previews, switching in recently used order between more than two tabs would be unusable.

这简直笑掉大牙,难不成之前一直这么用的用户都不是正常人了?事实上,如果没有缩略图而直接切换,用户可以在全尺寸的网页中预览(只要按着ctrl不松开),如果不是自己想要的再点击一次tab就是了;结果现在必须要现在那个根本看不清的略缩图里找到自己的tab,完全是可用性的下降。

Pre57可以用TMP单独关闭后者,TMP挂掉了我就不知道怎么办了。

拖拽

我用smartUp Gesture有一段时间了,总体还是不错的,而且还附赠了我原来从来没习惯用过的鼠标手势功能,我现在也偶尔会用手势来完成ctrl+shift+T的功能(但是由于WE的限制,很多页面手势无效[比如空白页],实际用起来并不算完全舒服)。至于拖拽功能,这个插件里有两组拖拽——一个简单一个超级。其实我的需求简单拖拽完全就够,但是他的简单拖拽bug很多,最影响使用的就是有些时候拖拽某些角度时会无效,而同样方向设定在超级拖拽就没问题。另外一个在Chrome发现的问题(估计Firefox也有):如果在一些比较复杂的页面(例如:YouTube带播放列表的播放页面),拖拽会变的奇卡无比,估计是实现方式比较奇怪的原因导致JS负载过重?

xThunder

好像有人在说什么Open with啥的,我没研究还。

结语

那么基本就是这样了。总体而言嘛还是能用的范畴,但是诸多不爽是不可避免的。姑且备份了一份profile,如果实在不行就回滚52ESR先用着再看情况了。另外这里吐槽一下reddit的/r/firefox一片circlejerk、歌舞升平,虽然倒也没啥错,不过实在让人怀疑那里使用扩展数量超过5的power user到底有多少……不过仔细想想之前去问过几个uc的问题,那里大部分连uc是啥都不知道,确实不能指望太多就是了。

迁移至Firefox 57

57终于近在眼前了。9月28日Firefox release通道就要升级到56,作为beta版用户,则近两天应该就有57b的推送。拖了这么久,也是时候整理下自用的传统扩展的情况了。

关于XUL扩展的整体情况,可以参见这个list。可以说比较大型的(样式表,User脚本,广告拦截)且和UI无关的应该都有替代品了。这里主要汇总一下个人用的。

Classic Theme Restorer

很显然不会被移植到57啦。其实CTR的数不胜数的选项中我用的不多,这里记录下自己实际用到的。

标签栏在地址栏下方 – 暂时可以修改userChrome.css(但是这玩意据说也要淘汰):

@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* only needed once */

/* tabs on bottom */
#navigator-toolbox toolbar:not(#nav-bar):not(#toolbar-menubar) {-moz-box-ordinal-group:10}
#TabsToolbar {-moz-box-ordinal-group:1000!important}

更新:我试了下,效果比CTR的实现丑好多,懒得去研究调哪些CSS细节了,直接放弃了tabs on bottom了。

修改回老式搜索框 – 无理。实际上,从之前几个版本就不行了。这里必须发泄一下,这个堪称是Firefox最蠢的改动。之前的搜索框可以很方便地在几个搜索引擎里切换,然后搜索你的关键词。现在呢?必须先输入关键词,再用按钮去选搜搜引擎。缺点在于:

  1. 无法获取非默认引擎的搜索建议;
  2. 无法快速修改默认引擎(唯一的方法:ctrl+箭头一个个选,20+引擎你选去吧),也就是说如果你要连续用非默认引擎搜索多次的话,每次都得去重新找对应引擎的按钮点;
  3. 极其键盘不友好;
  4. 完全无法区分同样icon的不同引擎,例如各种语言版本的维基百科

如果只是技术改进的阵痛也就罢了,关键在于这个东西的引入完全是和雅虎签了引擎协议之后为了强推雅虎搜索,不顾用户体验的阴招,说白了就是出卖了自己的灵魂。其设计的唯一目的就是让用户不能随便地(不进入设置改不了)修改默认引擎,从而保证能stick在Yahoo上。该改动的主持人在Bugzilla各种语焉不详,对于众多抱怨(例如:为什么搜索栏不显示当前引擎图标?)前言不搭后语,甚至遭到众多同样是Mozilla员工的质疑(这个东西从计划到实行只有极短的时间,不符合正常周期,也根本不知道有没有做遥感和UX test)。

因为这个恶心的改动,我几乎把所有的用非默认引擎(例如维基)的操作全部迁徙到了Chrome:Chrome虽然没有搜索栏,但是不知道高到哪里去了:它会自动识别新的搜索引擎,你只需要打对应网址的开头然后tab(例如,英文维基就是en+tab),然后输入关键词就行了。搜索建议什么的全有,流畅至极。所以怎么说Firefox作死呢?当然,Firefox里你也能用给书签加keyword的方式来搞地址栏搜索,但是一,keyword得一一手动设置,二,依然没有搜索建议,和Chrome的比,天上地下。

书签星星恢复到地址栏里,增加RSS按钮 – UI相关,八成无理。更新:我发现原来57默认又把书签星星挪回地址栏了,呵呵。

about:addons显示扩展版本 – 无理——57+应该是不允许修改Fx的内部页面的。

FlagFox

作者号称开发中。暂时替代品:Country Flags & IP Whois 或者 Country Flag +

Gmail™ Notifier (restartless)

改用Chrome也有的Checker Plus for Gmail™,更好用。

Greasemonkey

现在已经有TamperMonkeyViolentmonkey两个用户很多的替代品了,GM自己也在开发WebExt版本。个人还在纠结中,TM在Chrome一直用,感觉UI可以殴打GM;但是毕竟是闭源的,这点VM加分。GM自己的WebExt版怕是等不到…

Image Search Options

图像反向搜索,作者为SauceNAO站长。极少数支持POST反向搜索(可以支持本地图片、有ref限制的网站搜索)的扩展,但是57的API似乎还做不到(同理,Chrome上也没有能比的扩展)。市场里有无数类似的没有一一尝试,这个还行(只支持GET)。

如果这个没有替代品了那绝对是一大损失,这是少数现在Firefox优越于Chrome的地方之一了——在Fx56,我可以直接拖一张本地图(例如从QQ)进Firefox,然后用各种引擎搜索(Chrome自带的图像反向搜索context menu倒是可以搜本地,但是只有Google)。

Image Zoom

另外一个坚守Fx的理由之一,其实这个扩展我大概2、3年前才开始用,但是一下就爱上了。其作用说起来很简单:在任意图片上,按住右键,然后可以用滚轮缩放。另外,可以通过按住右键+点击左键的方式来讲图片放缩为fit to screen。功能虽简单,但是非常实用,尤其是现在许多网站为了省事不用专门的略缩图,很多图片元素其实都是大图,这样可以看得很清楚。

这个扩展虽然有高达十万用户,但是其实作者在13年之后就没有更新过。在5X版本已经开始不太好用,现在我在用的其实是这个Image Zoom (ugly fixes)(虽然叫fix,其实还有点小毛病,比如缩放后mouse up时不能正确地取消右键菜单等。但是勉强能用)。

Fx57之后的替代品有:

Zoom Image:日本人开发的,用户极少,但是这个其实是和之前的Image Zoom最接近的——滚轮的操作完全一致(而且有个选项,可以选择是浮动显示图片还是依然在原有容器内,更方便)。就是还缺少右键+左键fit to screen缩放的功能,希望以后作者能加上。

Image Zoomer:支持右键+左键fit to screen,但是手感很奇怪,另外不支持滚轮,倒是支持按住右键+拖拽的方式,不是特别适应。

Zoom Image To Fit:这个设定也很奇怪了,先右键+左键进入缩放模式,然后可以用滚轮缩放等等。反正用着不舒服。

虽然这仨暂时都不完美,但是至少说明WebExt是可以开发出Image Zoom这样的软件的。There is hope!

Keyword Search

这个扩展的名称起得非常烂,因为完全看不出作用(更糟,甚至误导)。其真实作用是:锁定地址栏为X搜索引擎(例:Google),而不是像Fx默认那样根据搜索栏引擎改变。当然由于上面所提到的,我已经基本不用搜索栏了,但是依然不能否认这扩展的巨大作用。有了这个我可以固定地址栏为Goolge,搜索栏用维基百科什么的。不过由于工作原理所致,地址栏的搜索建议也算是废了(建议依然会出你当前用的搜索引擎的而不是你锁定的)。

暂时没找到替代,感觉也不一定有API。

Pearl Crescent Page Saver screenshot tool

Pre-57最好用的截图软件,但是技术极其原始,甚至不支持e10s(和不重启安装),其实早就该换掉了…Firefox现在自带一个截图工具,非常难用(连自动截图整个网站的功能都暂时没有:本来有后来说是有性能问题暂时阉割了),不过市场有大量WebExt的应该不愁找不到,我暂时还没比较就是了。

RefControl

已经Referer Control替代。功能其实是多一些的,但是这个UI非常拙计和反直觉。

这里多说一句,WebExt的扩展的选项UI大多是类似网页的形式,比起XUL扩展的传统桌面软件UI风格,最大的问题就在于风格不统一,而很多开发者的审美和design经验实在是有点惨不忍睹,所以可以说是群魔乱舞了(Chrome那边也一样),也算是一个笑点。

RightToClick

这个扩展作者居然直接从市场删掉了orz。说白了就是解锁右键菜单,解锁复制,反正就是破网站用JS实现的一堆防复制功能用的。我在Chrome是用Allow Copy这个,蛮好用。

Firefox的WebExt替代方面,市场排名第一的“Enable Right Click and Copy”这个非常辣鸡,每次自动插入JS进网页(而不是点击才使用),导致经常很多网站功能不正常(看评论就知),推荐用这个国人开发的“快乐右键”(Happy Right-Click。唯一的美中不足是图标在地址栏,有点丑且不好定制。顺便一提,我一般测试这种的功能,都是拿某个日文歌词站w(测试的时候注意确实地测试下到底能不能粘贴内容出来;有的网站光解锁select的权限还不行)。

Show Location

国人开发的扩展,更新肯定是没什么希望了(Last Updated: April 25, 2012)。作用就是根据IP显示服务器地址(根据本地的或者离线的纯真数据库)在地址栏,感觉应该WebExt能实现就是了。

Stylish

WebExt之后自然不能修改Fx本身的界面了,那些请移步userChrome.css。扩展本身嘛,作者(就是userstyles.org开发的)一直没回应是否会开发WebExt版本,而且之前Stylish Chrome版被某个用户分析公司收购引发了一些争议,我那边已经换用了一个fork Stylus了。Firefox这边自然也可以用Stylus(虽然UI真的很丑),其他选择有另外一个fork xStyle国产)、Website Theme Manager等。

Tab Mix Plus

另外一个庞大、但是大部分功能要入土的重型扩展——甚至拥有自己的bugzilla ticket

我个人主要用以下几个功能:

  • 强制紧挨当前tab右侧打开所有新tab(包括链接、书签、新建标签页等等):Firefox默认(以及Chrome)是只有当前页面的里的链接会在紧挨着右边打开,其他一律在最后打开。我个人不喜欢这样,鼠标移动太远。
    • 更新:可以用Open Tabs Next to Current,虽然实现很蠢(先开在最后然后再移动,肉眼可以见动画…),但是API限制下只能做到这样了。
  • 保留窗口,即使关闭了所有Tab
    • 更新:Firefox有选项:browser.tabs.closeWindowWithLastTab;false
  • 中键点击Tab栏空白处恢复最后关闭的Tab(默认:新建Tab);
    • 更新:目前没有标签栏事件处理,做不到。
  • 双击Tab栏空白处新建标签页(默认:同Windows默认标题栏,最大化/恢复窗口);
    • 同上:目前没有标签栏事件处理,做不到。
  • UI:将未读标签显示为红色斜体;
  • UI:右侧Tab列表下拉菜单按钮始终显示;
  • UI:控制Tab宽度为100px-250px

目前不知道多少可以用其他扩展或者userChrome.css实现。

uc

就是uc脚本(userChrome.JS)相关。还好我就用一个拖拽的,未来可以用Glitter Drag(国产)替代更新:另外一个国产扩展:smartUp Gesture,还有鼠标手势功能(不如说手势才是主打)。不过作者刚开始移植Fx(之前在Chrome),功能似乎略有残缺。

xThunder

直接调用迅雷下载的工具,比迅雷官方的好用。作者早已跑路不过一直能用。57肯定GG了。

其他

其他的一些曾经用过、但是本来就用得少干脆直接删掉的:

DownThemAll! | Places Maintenance

其他在用的已经是WebExt的在用的扩展一览:

Bookmarks Organizer | EPUBreaderReddit Enhancement SuiteRedirectoruBlock OriginYouku HTML5 PlayerYouTube Plus