FixCJK!

1) Use real bold to replace synthetic SimSun bold; 2) Regular SimSun/中易宋体 can also be substituted; 3) Reassign font fallback list (Latin AND CJK). Browser serif/sans settings are overridden; 4) Use Latin fonts for Latin part in Latin/CJK mixed texts; 5) Fix conflicting CJK punctuations. (Currently “”‘’ are fixed).

目前为 2016-05-19 提交的版本。查看 最新版本

// ==UserScript==
// @name         FixCJK!
// @namespace    https://github.com/stecue/fixcjk
// @version      0.9.4
// @description  1) Use real bold to replace synthetic SimSun bold; 2) Regular SimSun/中易宋体 can also be substituted; 3) Reassign font fallback list (Latin AND CJK). Browser serif/sans settings are overridden; 4) Use Latin fonts for Latin part in Latin/CJK mixed texts; 5) Fix conflicting CJK punctuations. (Currently “”‘’ are fixed).
// @author       [email protected]
// @license      GPLv3
// @match        http://*/*
// @match        https://*/*
// @exclude      http://*action=edit*/*
// @exclude      https://*action=edit*/*
// @grant        none
// ==/UserScript==
(function () {
    'use strict';
    // You can change the the following fonts/settings until the "var FixPunct=" line.
    var CJKdefault = 'SimSun,"WenQuanYi Zen Hei Sharp"'; //The default CJK font. Regular weight.
    var CJKserif = '"Microsoft YaHei","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 = '"Microsoft YaHei","Noto Sans CJK SC"'; //Sans-serif fonts for CJK. Regular weight.
    var CJKBold = '"Microsoft YaHei","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 CJKPunct = 'SimHei,"WenQuanYi Micro Hei","Noto Sans CJK SC",SimSun'; //The font to use for CJK quotation marks.
    var LatinInSimSun = 'Ubuntu Mono'; //The Latin font in a paragraph whose font was specified to "SimSun" only.
    var LatinSans = 'Lato,"Open Sans",Arial'; //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 = 'Consolas,"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. No side effects found so far.
    var FixPunct = true; //If Latin punctions in CJK paragraph need to be fixed. Usually one needs full-width punctions in CJK context. Turn it off if the script runs too slow or HTML strings are adding to your editing area.
    //Do not change following code unless you know the results!
    var re_simsun = / *simsun *| *宋体 *| *ËÎÌå */gi;
    var all = document.getElementsByTagName('*');
    var debug_00 = false;
    var debug_01 = false; //Turn on colors while debug_01.
    var debug_02 = false;
    var debug_03 = false;
    var debug_04 = false;
    var debug_left = false; //debug what's left.
    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 qpreCJK = CJKdefault;
    var qCJK = LatinInSimSun + ',' + CJKdefault + ',' + 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 + ',' + CJKdefault + ',' + qsig_default + ',' + 'monospace'; //To replace "monospace".
    var i = 0;
    var max = all.length;
    var child = all[i].firstChild;
    var if_replace = false;
    var font_str = window.getComputedStyle(all[i], null).getPropertyValue('font-family');
    var fweight = window.getComputedStyle(all[i], null).getPropertyValue('font-weight');
    var re_sans0 = /^ ?sans ?$|^ ?sans-serif ?$/i;
    var re_serif = /^ ?serif ?$/i;
    var re_mono0 = /^ ?mono ?$|^ ?monospace ?$/i;
    //Check if the font definitions are valid
    function check_fonts(font_var, fvname) {
        var fl = font_var.split(',');
        for (i = 0; i < fl.length; i++) {
            if (!(fl[i].match(/^[^" ][^"]+[^" ]$|^"[^ ][^"]+[^ ]"$/))) {
                alert('Check your font definition: ' + fl[i] + ' in ' + fvname);
                return false;
            }
        }
        return true;
    }
    if (check_fonts(CJKdefault, 'CJKdefault') === false)
        return false;
    else if (check_fonts(CJKserif, 'CJKserif') === false)
        return false;
    else if (check_fonts(CJKsans, 'CJKsans') === false)
        return false;
    else if (check_fonts(CJKBold, 'CJKBold') === false)
        return false;
    else if (check_fonts(LatinInSimSun, 'LatinInSimSun') === false)
        return false;
    else if (check_fonts(LatinSans, 'LatinSans') === false)
        return false;
    else if (check_fonts(LatinSerif, 'LatinSerif') === false)
        return false;
    else if (check_fonts(LatinMono, 'LatinMono') === false)
        return false;
    else {
    }
    function list_has(font_str, family) {
        /// Fucntion to check matches
        var allfonts = font_str.split(',');
        for (var j = 0, maxl = allfonts.length; j < maxl; j++) {
            if (allfonts[j].match(family)) {
                return j;
            }
        }
        return false;
    }
    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];
        }
        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;
    }
    function dequote(font_str) {
        /// Function to dequote non-standard font lists.
        var strl=font_str.split(','); //font list;
        for (var k=0;k < strl.length; k++) {
            while (strl[k].charAt(0).match(/["' ]/)) {
                strl[k]=strl[k].slice(1);
            }
            while (strl[k].charAt(strl[k].length-1).match(/["' ]/)) {
                strl[k]=strl[k].slice(0,-1);
            }
        }
        var dequoted=strl[0];
        for (k=1;k<strl.length;k++) {
            dequoted=dequoted+','+strl[k];
        }
        return dequoted;
    }
    if (debug_00===true) {console.log(dequote('"SimSun","Times New Roman"""""'));}
    qpreCJK = dequote(qpreCJK);
    qCJK = dequote(qCJK);//LatinInSimSun + ',' + CJKdefault + ',' + qsig_default;
    qSimSun = dequote(qSimSun);//LatinInSimSun + ',' + CJKserif + ',' + qsig_sun;
    qHei = dequote(qHei);//LatinInSimSun + ',' + CJKsans + ',' + qsig_hei;
    qBold = dequote(qBold);//LatinInSimSun + ',' + CJKBold + ',' + qsig_bold;
    qsans = dequote(qsans);//LatinSans + ',' + CJKsans + ',' + qsig_hei + ',' + 'sans-serif'; //To replace "sans-serif"
    qserif = dequote(qserif);//LatinSerif + ',' + CJKserif + ',' + qsig_sun + ',' + 'serif'; //To replace "serif"
    qmono = dequote(qmono);//LatinMono + ',' + CJKdefault + ',' + qsig_default + ',' + 'monospace'; //To replace "monospace".
    if (debug_00===true) {alert('Entering Loops...');}
    /// ===== First round: Replace all bold fonts to CJKBold ===== ///
    for (i = 0; i < max; i++) {
        child = all[i].firstChild;
        if_replace = false;
        //Only change if current node (not child node) contains CJK characters.
        font_str = dequote(window.getComputedStyle(all[i], null).getPropertyValue('font-family'));
        fweight = window.getComputedStyle(all[i], 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
                if (debug_01===true) {all[i].style.color="Blue";} //Bold-->Blue;
                if (font_str.match(re_simsun)) {
                    //all[i].style.color="Sienna"; //SimSun --> Sienna
                    all[i].style.fontFamily = font_str.replace(re_simsun, qBold);
                    if (!(has_genfam(all[i].style.fontFamily))) {
                        all[i].style.fontFamily = all[i].style.fontFamily + ',' + 'sans-serif';
                    }
                }        //Test if contains Sans
                else if (list_has(font_str, re_sans0) !== false) {
                    //all[i].style.color="Salmon";
                    all[i].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[i].style.color="SeaGreen";
                    all[i].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[i].style.color="Maroon";
                    all[i].style.fontFamily = LatinMono + ',' + replace_font(font_str, re_mono0, qBold) + ',' + 'monospace';
                }        //Just append the fonts to the font preference list.
                else {
                    //all[i].style.color="Fuchsia"; //qBold+"false-safe" sans-serif;
                    all[i].style.fontFamily = font_str + ',' + qBold + ',' + '  sans-serif';
                    //console.log(all[i].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[i].firstChild;
        if_replace = false;
        //Only change if current node (not child node) contains CJK characters.
        font_str = dequote(window.getComputedStyle(all[i], null).getPropertyValue('font-family'));
        fweight = window.getComputedStyle(all[i], null).getPropertyValue('font-weight');
        //console.log(child.nodeType);
        while (child) {
            if (child.nodeType == 3) {
                //all[i].style.color='Teal'; //text-->teal;
                //Just check and fix the improper SimSun use
                if (font_str.match(re_simsun)) {
                    //all[i].style.color="Sienna";
                    if (fweight == 'bold' || fweight > 500) {
                        //all[i].style.color="Grey";
                        if_replace = false;
                        //console.log(child.data);
                        //return false;
                    }
                    else {
                        //all[i].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[i].style.color="Grey";
                            if_replace = false;
                        }
                        else {
                            if (debug_02 ===true) {all[i].style.color="Indigo";} //Improperly used SimSun. It shouldn't be used for non-CJK fonts.
                            all[i].style.fontFamily = font_str.replace(re_simsun, qSimSun);
                            if (all[i].style.fontFamily.length<1) {
                                console.log(font_str);console.log(font_str.replace(re_simsun, qSimSun));
                            }
                            if (!(has_genfam(all[i].style.fontFamily))) {
                                all[i].style.fontFamily = all[i].style.fontFamily + ',' + 'sans-serif';
                            }              //all[i].style.color="Indigo"; //Improperly used SimSun. It shouldn't be used for non-CJK fonts.

                            if_replace = false;
                            //all[i].style.color="Grey";
                        }
                    }
                }
                if (child.data.match(/[\u3400-\u9FBF]/)) {
                    if_replace = true;
                    //all[i].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[i].style.color="Black";
                        if_replace = false;
                    }          //break;

                }
            }
            child = child.nextSibling;
        }
        if (if_replace === true) {
            //Test if contains Sans
            if (list_has(font_str, re_sans0) !== false) {
                //all[i].style.color="Salmon";
                all[i].style.fontFamily = replace_font(font_str, re_sans0, qsans);
            }      //Test if contains serif
            else if (list_has(font_str, re_serif) !== false) {
                //all[i].style.color="SeaGreen";
                all[i].style.fontFamily = replace_font(font_str, re_serif, qserif);
            }      //Test if contains monospace
            else if (list_has(font_str, re_mono0) !== false) {
                //all[i].style.color="Maroon";
                all[i].style.fontFamily = replace_font(font_str, re_mono0, qmono);
            }
            else {
                //all[i].style.color='Fuchsia';
                if (font_str.match(re_simsun)) {
                    //all[i].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[i].style.fontFamily = font_str.replace(re_simsun, qSimSun) + ',' + 'serif';
                }
                else {
                    //all[i].style.color='Fuchsia';
                    all[i].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++) {
        //all[i].style.color="SeaGreen";
        font_str = dequote(window.getComputedStyle(all[i], 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[i].style.color="Salmon";
                all[i].style.fontFamily = replace_font(font_str, re_sans0, qsans);
            }      //Test if contains serif
            else if (list_has(font_str, re_serif) !== false) {
                //all[i].style.color="SeaGreen";
                all[i].style.fontFamily = replace_font(font_str, re_serif, qserif);
            }      //Test if contains monospace
            else if (list_has(font_str, re_mono0) !== false) {
                //all[i].style.color="Maroon";
                all[i].style.fontFamily = replace_font(font_str, re_mono0, qmono);
            }
            else {
                if (debug_03 === true) { all[i].style.color='Fuchsia'; }
                if (font_str.match(re_simsun)) {
                    if (debug_03 === true) {all[i].style.color='Sienna'; }
                    //This is needed because some elements cannot be captured in "child elements" processing. (Such as the menues on JD.com) No idea why.
                    all[i].style.fontFamily = font_str.replace(re_simsun, qSimSun) + ',' + 'serif';
                }
                else {
                    if (debug_03 === true) { all[i].style.color='Olive';}
                    all[i].style.fontFamily = font_str + ',' + qCJK + ',' + 'sans-serif';
                }
            }
        }
        else {
            //all[i].style.color="Silver"; //Signed-->Silver
        }
    }
    //alert('Timer Set!');
    //setTimeout(function(){
    //    var all_r=document.getElementsByTagName('*');
    //    var max_r=all_r.length;
    //    if (max!==max_r)
    //        {
    //            console.log(max);
    //            console.log(max_r);
    //            location.reload();
    //        }
    //}, 2*1000);
    //for(i=0;i<max;i++){all[i].style.color="Black";}
    //location.reload();
    //altert('Reloaded!');
    /// NOT IMPLEMENTED YET ///
    if (FixPunct === false) {
        return false;
    }
    else {
        //return true;
    }
    i=0;
    all = document.getElementsByTagName('*');
    var puncnode=new Array('');
    var numnodes=0;
    var delete_all_spaces=true;
    for (i = 0; i < max; i++) {
        child = all[i].firstChild;
        if_replace = false;
        //Only change if current node (not child node) contains CJK characters.
        //font_str = dequote(window.getComputedStyle(all[i], null).getPropertyValue('font-family'));
        //fweight = window.getComputedStyle(all[i], null).getPropertyValue('font-weight');
        //console.log(child.nodeType);
        font_str = dequote(window.getComputedStyle(all[i], null).getPropertyValue('font-family'));
        while (child) {
            if (child.nodeType == 3) {
                //console.log(child.data);
                //use "mg" to also match paragraphs with punctions at the end or beginning of a line.
                if ((child.data.match(/[“‘][ \n\t]*[\u3400-\u9FBF?!:;《》、]+|[\u3400-\u9FBF?!:;《》、][ \n\t]*[”’]/mg)) && (!(font_str.match('monospace')))) {
                    //console.log(i);
                    //console.log(all[i].innerHTML);
                    if (debug_04===true) {all[i].style.color='Purple';} //Punctions-->Purple;
                    numnodes++;
                    puncnode.push(i);
                    break;
                }
                else if ((delete_all_spaces===true) && (child.data.match(/[,。?!:;》、][\n]?[][^ |$]/mg))) {
                    if (debug_04===true) {all[i].style.color='Purple';} //Punctions-->Purple;
                    numnodes++;
                    puncnode.push(i);
                    break;
                }
                else {
                }
            }
            child = child.nextSibling;
        }
    }
    var currpunc=0;
    var currHTML='';
    var fsize = '';
    var psize = '';
    var funit = '';
    var changhai_style=false;
    var kern_punct=2.0;
    var kern_dq=10.0;
    var kern_sq=3.0;
    var tmp_str='';
    var kern_ind_left_dq=8.0;
    var kern_ind_right_dq=8.0;
    var kern_ind_right_dq_tail=3.0; //different from above one b/c the possible extra \n (which will show as a space in most cases).
    var kern_other='-3px'; //kern for ,. before right ”
    var kern_dq_right_end='-3px';
    var kern_dq_right_left='-6px';
    //var kern_dq_right='-1px';
    //var kern_dq_right_tail='-5px';
    while(numnodes>0) {
        numnodes--;
        //Simply inserting blanck space, like changhai.org.
        currpunc=puncnode.pop();
        currHTML=all[currpunc].innerHTML;
        if (changhai_style===true) {
            currHTML=currHTML.replace(/([\u3400-\u9FBF]?)([“‘])([\u3400-\u9FBF]+)/g,'$1 $2$3');
            currHTML=currHTML.replace(/([\u3400-\u9FBF])([”’])([^,, ])/g,'$1$2 $3');
            if (debug_04===true) {console.log(currHTML);}
            all[currpunc].innerHTML=currHTML;
            continue;
        }
        //We need to strip the space before and after quotation marks before fixing punctions, but not \n
        if (delete_all_spaces===true) {
            currHTML=currHTML.replace(/([,。?!:;》、][\n]?)[]([^ |$])/g,'$1$2');
        }
        currHTML=currHTML.replace(/[ ]?([“‘])[ ]?([\n]?[\u3400-\u9FBF]+)/mg,'$1$2');
        currHTML=currHTML.replace(/([\u3400-\u9FBF,。?!:;]+[\n]?)[ ]?([”’])[ ]?/mg,'$1$2');
        //Add space/backspace between ">" and "“"
        if (currHTML.match(/(>[\n]?)[ ]*([“‘])/mg)) {
            if (debug_04===true) {console.log('Before Replacement: '+currHTML);}
            currHTML=currHTML.replace(/(>[\n]?)[ ]*([“‘])/mg,'$1\u0008$2');
            if (debug_04===true) {console.log('After Replacement: '+currHTML);}
        }
        //all[currpunc].innerHTML=currHTML; continue;
        //Now let's fix the punctions.
        fsize=window.getComputedStyle(all[currpunc], null).getPropertyValue('font-size');
        funit=fsize.replace(/^["']*[0-9.]+/,'');
        fsize=fsize.replace(/[^0-9.]+$/,'');
        fsize=fsize.replace(/[^0-9.]+$/,'');
        //Use more negative kerning for consective punction marks.
        psize=(-Number(fsize)/kern_punct).toString();
        psize=psize+funit;
        ///----[?!:;]“ does not need special treatment. Just compress [,。]---///
        //--TWO PUNCTS: End with '” (right mark)' and NONE '“' after:--//
        tmp_str='$1<span style="letter-spacing:'+kern_other+';">$2</span>'+'<span style="font-family:'+dequote(CJKPunct)+';letter-spacing:'+kern_dq_right_end+';">$3</span>$4';
        currHTML=currHTML.replace(/([\u3400-\u9FBF?!:;《》、][\n]?)([,。][\n]?)([’”])([^“‘]|$)/mg,tmp_str); // "?!:;" are in the middle of the "font space".
        tmp_str='$1<span style="font-family:'+dequote(CJKPunct)+';letter-spacing:'+psize+';">$2</span>$3$4';
        currHTML=currHTML.replace(/([\u3400-\u9FBF?!:;《》、][a-zA-Z_0-9]*[\n]?)([’”])([,。])([^“‘]|$)/mg,tmp_str);
        //--TWO PUNCTS: End with [,。] and ONE '“' (left mark) after:--//
        tmp_str='$1<span style="letter-spacing:'+kern_dq_right_left+';">$2</span>'+'<span style="font-family:'+dequote(CJKPunct)+';">$3</span>$4';
        currHTML=currHTML.replace(/([^’”]|^)([,。][\n]?)([“‘])([\n]?[\u3400-\u9FBF])/mg,tmp_str);
        //--TWO PUNCTS: ”“ (right-left)--//
        tmp_str='$1<span style="font-family:'+dequote(CJKPunct)+';letter-spacing:'+kern_dq_right_left+';">$2</span>'+'<span style="font-family:'+dequote(CJKPunct)+';">$3</span>$4';
        currHTML=currHTML.replace(/([^’”,。]|^)([\n]?[’”])([“‘])([\n]?[\u3400-\u9FBF])/mg,tmp_str);
        //--THREE PUNCTS: [,。]”“-//
        tmp_str='$1<span style="letter-spacing:'+kern_other+';">$2</span>'+'<span style="font-family:'+dequote(CJKPunct)+';letter-spacing:'+kern_dq_right_left+';">$3</span>';
        tmp_str=tmp_str+'<span style="font-family:'+dequote(CJKPunct)+';">$4</span>$5';
        currHTML=currHTML.replace(/([\u3400-\u9FBF][a-zA-Z_0-9]*[\n]?)([,。][\n]?)([’”])([“‘][\n]?)([?!:;\u3400-\u9FBF])/mg,tmp_str); //all[currpunc].innerHTML=currHTML; continue;
        //--THREE PUNCTS: ”[,。]“-//
        tmp_str='$1<span style="font-family:'+dequote(CJKPunct)+';letter-spacing:'+kern_dq_right_left+';">$2</span>'+'<span style="letter-spacing:'+kern_dq_right_left+';">$3</span>';
        tmp_str=tmp_str+'<span style="font-family:'+dequote(CJKPunct)+';">$4</span>$5';
        currHTML=currHTML.replace(/([\u3400-\u9FBF?!:;《》、][a-zA-Z_0-9]*[\n]?)([’”])([,。])([“‘][\n]?)([?!:;\u3400-\u9FBF])/mg,tmp_str); //all[currpunc].innerHTML=currHTML; continue;
        ///---Done with conseqtive puncts--///
        //-----Use normal kerning for individual double quotation marks.---//
        psize=(-Number(fsize)/kern_ind_left_dq).toString();
        psize=psize+funit;
        ////// Why do I need to start with non-space character?
        currHTML=currHTML.replace(/([^ \n”。,][\n]?|^)([“])([\n]?[\u3400-\u9FBF]+)/mg,'<span style="letter-spacing:'+psize+'">$1</span><span style="font-family:'+dequote(CJKPunct)+',sans-serif;">$2</span>$3');
        psize=(-Number(fsize)/kern_ind_right_dq).toString();
        psize=psize+funit;
        currHTML=currHTML.replace(/([\u3400-\u9FBF?!:;《》、][a-zA-Z_0-9]*[\n]?)([”])([^“,。\n])/mg,'$1<span style="font-family:'+dequote(CJKPunct)+';letter-spacing:'+psize+';">$2</span>$3');
        psize=(-Number(fsize)/kern_ind_right_dq_tail).toString();
        psize=psize+funit;
        currHTML=currHTML.replace(/([\u3400-\u9FBF?!:;《》、][a-zA-Z_0-9]*[\n]?)([”])([\n]|$)/mg,'$1<span style="font-family:'+dequote(CJKPunct)+';letter-spacing:'+psize+';">$2</span>$3');
        ///===== User more negative spacing for single quotation marks. =====//
        // However, left quotation marks will overwrite the character on the left with too negative spacing.) ---///
        psize=(-Number(fsize)/kern_sq).toString();
        psize=psize+funit;
        var Unified_Algo=true; //Unified replacement algorithm for double and single quotations.
        if (Unified_Algo===true) {
            currHTML=currHTML.replace(/([^ \n”。,][\n]?|^)([‘])([\n]?[\u3400-\u9FBF]+)/mg,'<span style="letter-spacing:'+psize+'">$1</span><span style="font-family:'+dequote(CJKPunct)+',sans-serif;">$2</span>$3');
            currHTML=currHTML.replace(/([\u3400-\u9FBF?!:;《》、][a-zA-Z_0-9]*[\n]?)([’])([^“,。\n])/mg,'$1<span style="font-family:'+dequote(CJKPunct)+';letter-spacing:'+psize+';">$2</span>$3');
            currHTML=currHTML.replace(/([\u3400-\u9FBF?!:;《》、][a-zA-Z_0-9]*[\n]?)([’])([\n]|$)/mg,'$1<span style="font-family:'+dequote(CJKPunct)+';letter-spacing:'+psize+';">$2</span>$3');
        }
        else {
            currHTML=currHTML.replace(/([\u3400-\u9FBF,。?!:;《》、])([‘])([\n]?[\u3400-\u9FBF?!:;《》、]+)/mg,'<span style="letter-spacing:'+psize+'">$1</span><span style="font-family:'+dequote(CJKPunct)+',sans-serif;">$2</span>$3');
            currHTML=currHTML.replace(/([\u3400-\u9FBF,。?!:;《》、][\n]?)([’])/g,'$1<span style="font-family:'+dequote(CJKPunct)+';letter-spacing:'+psize+';">$2</span>');
        }
        all[currpunc].innerHTML=currHTML;
        if (debug_04===true) {all[currpunc].style.color="Pink";}
    }
    if (debug_left===true) {console.log('Finished!');}
}
) ();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址