** 非常重要!!! 由于本论坛的编辑器总是“自作聪明”地在中英文之间加空格而我还没看到如何关掉,所以如果从下面的代码区直接拷贝粘贴的话, *var re_simsun=/ *simsun *| * 宋体 /gi 这一行是不可以直接使用的!代码粘贴到 TamperMonkey 后,你需要把这一行中“宋体”和它之前的那个“星号”之间的空格手动删去,脚本才能正常工作!紧跟着“宋体”之后的那个空格不要删掉!建议通过 github 获得代码 github.com/stecue/fixcjk/blob/master/FixCJK!.user.js 或者通过 OpenUserJS 网站直接安装 openuserjs.org/scripts/stecuegmail.com/FixCJK! **
------------------------------------------------ 正文的分隔线 ---------------------------------------------------
今天脚本升级到 v0.8。提供了定义修复级别的变量 ( FixRegular , FixRegular 和 FixMore 都为 false,则仅仅修复中文粗体。设定 var FixRegular=true 将常规自重的中易宋体也一并替换,并且中英文混排中的英文字符采用英文字体。再设定 var FixMore=true 之后将开启强力中文字体修正。所有 JavaScript 能遍历到的页面元素全部附上中文字体设定。这对之前无法设定的输入框之类很可能也有效。由于脚本中采用“附加”的方式修改字体,一般不会破坏英文元素的原有字体。如有渲染异常请跟帖说明或者 email 本人。
用户可以在变量定义区域设定自己喜欢的字体。变量的名字非常直接,请参看后面的注释。以 CJK 开头的四个变量最为重要,请务必使用你的系统有的字体(可以用 fc-match 命令检查)。如果要在一个变量内指定多个字体(优先使用靠左边的字体),请参考 LatinSerif 的定义。简言之,如果字体名有空格,请用英文双引号将字体名围起来,用英文逗号做分隔符。整个字体列表再用英文单引号围起来。
var all = document.getElementsByTagName(’’);* 这一行以及之后的代码一般不需要用户修改。当然,十分欢迎反馈意见!
本次升级后,由于本脚本不仅仅可以设定中文粗体,所以名字也相应更改为“FixCJK!”。
// ==UserScript==
// @name FixCJK!
// @namespace https://forum.suse.org.cn/
// @version 0.8
// @description 1) Use real bold to replace synthetic SimSun bold; 2) Use Latin fonts for Latin part in Latin/CJK mixed texts; 3) Assign general CJK fonts.
// @author stecue@gmail.com
// @match http://*/*
// @match https://*/*
// @grant none
// ==/UserScript==
(function () {
'use strict';
// You can change the the following fonts/settings until the "var all=" line.
var CJKdefault ='WenQuanYi Zen Hei Sharp'; //The default CJK font. Regular weight.
var CJKserif='WenQuanYi Micro Hei'; //Serif fonts for CJK. "SimSun" with regular weight will be replaced by the font specified here. Although It is intended for regular weight but some element with bold weight still use the font here. Therefore "SimSun" itself is not a good choice because it does not have a real bold font.
var CJKsans='Noto Sans CJK SC'; //Sans-serif fonts for CJK. Regular weight.
var CJKBold='WenQuanYi Micro Hei'; //The "good CJK font" to replace SimSun bold. Note that some elements still use font in CJKserif defined above such as the menus on JD.com.
var LatinInSimSun='Ubuntu Mono'; //The Latin font in a paragraph whose font was specified to "SimSun" only.
var LatinSans='Open Sans'; //Sans-serif fonts for Latin script. It will be overridden by a non-virtual font in the CSS font list if present.
var LatinSerif='Constantia,"Liberation Serif","Times New Roman"'; //Serif fonts for Latin script. It will be overridden by a non-virtual font in the CSS font list if present.
var LatinMono='DejaVu Sans Mono'; //Monospace fonts for Latin script. It will be overridden by a non-virtual font in the CSS font list if present.
var FixRegular=true; //Also fix regular fonts. You need to keep this true if you want to use "LatinInSimSun" in Latin/CJK mixed context.
var FixMore=true; //Appendent CJK fonts to all elements. Might have side effects ?
var FixPunct=false; //If Latin punctions in CJK paragraph need to be fixed. Usually one needs full-width punctions in CJK context. Not implemented yet.
//Do not change following code unless you know the results!
var re_simsun=/ *simsun *| * 宋体 */gi;
var all = document.getElementsByTagName('*');
var sig_sun='RealCJKBold 宋'; // signature to check if change is sucssful or not.
var sig_hei='RealCJKBold 黑'; // signature to check if change is sucssful or not.
var sig_bold='RealCJKBold 粗'; // signature to check if change is sucssful or not.
var sig_default='RealCJKBold 默'; // signature to check if change is sucssful or not.
var qsig_sun='"'+sig_sun +'"'; //Quoted sinagure; Actually no need to quote.
var qsig_hei='"'+sig_hei +'"'; //Quoted sinagure;
var qsig_bold='"'+sig_bold+'"';
var qsig_default='"'+sig_default+'"';
var qpreCJK = '"' + CJKdefault + '"'; //Quoted "CJK font".
var qCJK = qpreCJK+','+qsig_default;
var qSimSun = LatinInSimSun+','+CJKserif+','+qsig_sun;
var qHei = LatinInSimSun+','+CJKsans+','+qsig_hei;
var qBold = LatinInSimSun+','+CJKBold+','+qsig_bold;
var qsans = LatinSans+',' + CJKsans +','+qsig_hei+','+'sans-serif'; //To replace "sans-serif"
var qserif = LatinSerif+','+ CJKserif+','+qsig_sun+','+'serif'; //To replace "serif"
var qmono = LatinMono+','+qCJK+','+'monospace'; //qCJK comes with signature;
var i=0;
var max=all.length;
var child = all*.firstChild;
var if_replace = false;
var font_str = window.getComputedStyle(all*, null).getPropertyValue('font-family');
var font_last=];
var fweight = window.getComputedStyle(all*, null).getPropertyValue('font-weight');
var re_sans0=/^ ?sans ?$|^ ?sans-serif ?$/i ;
var re_serif=/^ ?serif ?$/i;
var re_mono0=/^ ?mono ?$|^ ?monospace ?$/i;
//fucntion to check matches
function list_has(font_str,family ) {
var allfonts=font_str.split(',');
for (var j=0,maxl=allfonts.length;j< maxl;j++) {
if (allfonts[j].match(family)) {
return j;
}
}
return false;
}
//alert(list_has('sans-serif,sans011,serif',re_sans0) !== false);
//return true;
function replace_font(font_str,family,qBold) {
var allfonts=font_str.split(',');
var j=0;
var maxl=allfonts.length;
for (j=0;j< maxl;j++) {
if (allfonts[j].match(family)) {
allfonts[j]=qBold;
}
}
var toReturn=allfonts[0];
for (j=1;j< maxl;j++) {
toReturn=toReturn+','+allfonts[j];
}
//alert(qBold);
return toReturn;
}
function has_genfam(font_str) {
//Test if font_str include general families.
if (list_has(font_str,re_sans0)){
return true;
}
else if (list_has(font_str,re_serif)){
return true;
}
else if (list_has(font_str,re_mono0)){
return true;
}
return false;
}
/// First round: Replace all bold fonts to CJKBold ///
for (i=0; i < max; i++) {
child = all*.firstChild;
if_replace = false;
//Only change if current node (not child node) contains CJK characters.
font_str = window.getComputedStyle(all*, null).getPropertyValue('font-family');
fweight = window.getComputedStyle(all*, null).getPropertyValue('font-weight');
while (child) {
if (child.nodeType == 3 && (child.data.match(/\u3400-\u9FBF]/)) && (fweight == 'bold' || fweight > 500) && (!(font_str.match(sig_bold)))) {
//Test if contains SimSun
//all*.style.color="Blue"; //Bold-->Blue;
if (font_str.match(re_simsun)) {
//all*.style.color="Sienna"; //SimSun --> Sienna
all*.style.fontFamily = font_str.replace(re_simsun, qBold);
if (!(has_genfam(all*.style.fontFamily))) {
all*.style.fontFamily=all*.style.fontFamily+','+'sans-serif';
}
}
//Test if contains Sans
else if (list_has(font_str, re_sans0) !== false ) {
//all*.style.color="Salmon";
all*.style.fontFamily = LatinSans+','+replace_font(font_str,re_sans0,qBold)+','+'sans-serif';
}
//Test if contains serif
else if (list_has(font_str, re_serif) !== false ) {
//all*.style.color="SeaGreen";
all*.style.fontFamily = LatinSerif+','+replace_font(font_str,re_serif,qBold)+','+'serif';
}
//Test if contains monospace
else if (list_has(font_str, re_mono0) !== false ) {
//all*.style.color="Maroon";
all*.style.fontFamily = LatinMono+','+replace_font(font_str,re_mono0,qBold)+','+'monospace';
}
//Just append the fonts to the font preference list.
else {
//all*.style.color="Fuchsia"; //qBold+"false-safe" sans-serif;
all*.style.fontFamily = font_str+','+qBold+','+' sans-serif';
//alert(all*.style.fontFamily);
}
}
child = child.nextSibling;
}
}
if (FixRegular===false) {
return false;
}
/// Second Round: Deal with regular weight. ///
max=all.length;
for (i=0; i < max; i++) {
child = all*.firstChild;
if_replace = false;
//Only change if current node (not child node) contains CJK characters.
font_str = window.getComputedStyle(all*, null).getPropertyValue('font-family');
fweight = window.getComputedStyle(all*, null).getPropertyValue('font-weight');
//alert(child.nodeType);
while (child) {
if (child.nodeType == 3) {
//all*.style.color='Teal'; //text-->teal;
//Just check and fix the improper SimSun use
if (font_str.match(re_simsun)) {
//all*.style.color="Sienna";
if (fweight == 'bold' || fweight > 500) {
//all*.style.color="Grey";
if_replace=false;
//alert(child.data);
//return false;
}
else {
//all*.style.color="Orange";
if (font_str.match(sig_sun) || font_str.match(sig_hei) || font_str.match(sig_bold) || font_str.match(sig_default)) {
//do nothing if already replaced;
//all*.style.color="Grey";
if_replace=false;
}
else {
//all*.style.color="Indigo"; //Improperly used SimSun. It shouldn't be used for non-CJK fonts.
all*.style.fontFamily = font_str.replace(re_simsun, qSimSun);
if (!(has_genfam(all*.style.fontFamily))){
all*.style.fontFamily=all*.style.fontFamily+','+'sans-serif';
}
//all*.style.color="Indigo"; //Improperly used SimSun. It shouldn't be used for non-CJK fonts.
if_replace=false;
//all*.style.color="Grey";
}
}
}
if (child.data.match(/\u3400-\u9FBF]/)) {
if_replace=true;
//all*.style.color="Cyan"; //CJK-->Cyan
if (font_str.match(sig_sun) || font_str.match(sig_hei) || font_str.match(sig_bold) || font_str.match(sig_default)) {
//do nothing if already replaced;
//all*.style.color="Black";
if_replace=false;
}
//break;
}
}
child = child.nextSibling;
}
//continue;
if (if_replace === true) {
//Test if contains Sans
if (list_has(font_str, re_sans0) !== false ) {
//all*.style.color="Salmon";
all*.style.fontFamily = replace_font(font_str,re_sans0,qsans);
}
//Test if contains serif
else if (list_has(font_str, re_serif) !== false ) {
//all*.style.color="SeaGreen";
all*.style.fontFamily = replace_font(font_str,re_serif,qserif);
}
//Test if contains monospace
else if (list_has(font_str, re_mono0) !== false ) {
//all*.style.color="Maroon";
all*.style.fontFamily = replace_font(font_str,re_mono0,qmono);
}
else {
//all*.style.color='Fuchsia';
if (font_str.match(re_simsun)) {
//all*.style.color='Fuchsia';
//This is needed because some elements cannot be captured in "child elements" processing. (Such as the menues on JD.com) No idea why.
all*.style.fontFamily = font_str.replace(re_simsun, qSimSun)+','+'serif';
}
else {
//all*.style.color='Fuchsia';
all*.style.fontFamily = font_str + ',' + qCJK +','+'sans-serif';
}
}
}
}
/// The final round: Add CJKdefault to all elements ///
if (FixMore===false) {
return false;
}
max=all.length;
for (i=0; i < max; i++) {
font_str = window.getComputedStyle(all*, null).getPropertyValue('font-family');
if (!(font_str.match(sig_sun) || font_str.match(sig_hei) || font_str.match(sig_bold) || font_str.match(sig_default))) {
if (list_has(font_str, re_sans0) !== false ) {
//all*.style.color="Salmon";
all*.style.fontFamily = replace_font(font_str,re_sans0,qsans);
}
//Test if contains serif
else if (list_has(font_str, re_serif) !== false ) {
//all*.style.color="SeaGreen";
all*.style.fontFamily = replace_font(font_str,re_serif,qserif);
}
//Test if contains monospace
else if (list_has(font_str, re_mono0) !== false ) {
//all*.style.color="Maroon";
all*.style.fontFamily = replace_font(font_str,re_mono0,qmono);
}
else {
//all*.style.color='Fuchsia';
if (font_str.match(re_simsun)){
//all*.style.color='Fuchsia';
//This is needed because some elements cannot be captured in "child elements" processing. (Such as the menues on JD.com) No idea why.
all*.style.fontFamily = font_str.replace(re_simsun, qSimSun)+','+'serif';
}
else {
//all*.style.color='Fuchsia';
all*.style.fontFamily = font_str + ',' + qCJK +','+'sans-serif';
}
}
}
}
/// NOT IMPLEMENTED YET ///
if (FixPunct===false) {
return false;
}
else {
return true;
}
}
) ();