Greasy Fork

Greasy Fork is available in English.

VNDB优先原文和中文化

优先显示原文(title->value),以及中文化(mainMap[value]->value)

当前为 2022-06-14 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         VNDB优先原文和中文化
// @namespace    http://tampermonkey.net/
// @version      4.3.2
// @description  优先显示原文(title->value),以及中文化(mainMap[value]->value)
// @author       aotmd
// @match        https://vndb.org/*
// @noframes
// @license MIT
// @run-at document-body
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// @require http://greasyfork.icu/scripts/445990-vndbtranslatorlib/code/VNDBTranslatorLib.js?version=1060790
// ==/UserScript==

/**-----------------------------业务逻辑部分[300行]----------------------------------*/
/** ---------------------------map处理---------------------------*/
let pathname = window.location.pathname;
otherPageRules.forEach((item) => {
    //当regular是正则才执行
    if (item.regular !== undefined && item.regular instanceof RegExp) {
        if (item.regular.test(pathname)) {
            //添加到主map,若存在重复项则覆盖主map
            Object.assign(mainMap, item.map);
            //添加特殊map
            Object.assign(specialMap, item.specialMap);
            //添加titleMap
            Object.assign(titleMap, item.titleMap);
            console.log(item.name + ',规则匹配:' + pathname + '->' + item.regular);
        }
    }
});
/*object转Map, 正则new效率原因,先new出来*/
(function () {
    let tempMap = new Map();
    let k = Object.getOwnPropertyNames(specialMap);
    for (let i = 0, len = k.length; i < len; i++) {
        try {
            tempMap.set(new RegExp(k[i]), specialMap[k[i]]);
        } catch (e) {
            console.log('"' + k[i] + '"不是一个合法正则表达式');
        }
    }
    specialMap = tempMap;
})();
/** ----------------------------END----------------------------*/


/**
 * 递归节点
 * @param el   要处理的节点
 * @param func 调用的函数
 */
function 递归(el, func) {
    const nodeList = el.childNodes;
    /*先处理自己*/
    数据归一化(el,false);
    for (let i = 0; i < nodeList.length; i++) {
        const node = nodeList[i];
        数据归一化(node);
    }
    function 数据归一化(el,recursion=true) {
        if (el.nodeType === 1) {
            //为元素则递归
            if (recursion){
                递归(el, func);
            }
            let attribute, value, flag = false;
            if (el.nodeName === 'INPUT') {
                value = el.getAttribute('value');
                attribute = 'value';
                if (value == null || value.trim().length === 0) {
                    value = el.getAttribute('placeholder');
                    attribute = 'placeholder';
                }
                flag = true;
            } else if (el.nodeName === 'TEXTAREA') {
                value = el.getAttribute('placeholder');
                attribute = 'placeholder';
                flag = true;
            } else if (el.getAttribute('title')!==null&&
                el.title.length!==0) {
                /*过判断用*/
                value = 'title用过判断value值';
                attribute = 'title';
                flag = true;
            }
            if (!flag) return;
            func(el, value, attribute);
        } else if (el.nodeType === 3) {
            //为文本节点则处理数据
            func(el, el.nodeValue);
        }
    }
}
recordsList = [];
let observerMap = new Map();
/**
 * dom修改事件,包括属性,内容,节点修改
 * @param document 侦听对象
 * @param func  执行函数,可选参数(records),表示更改的节点
 */
function dom修改事件(document, func) {
    const MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;//浏览器兼容
    const config = {attributes: true, childList: true, characterData: true, subtree: true};//配置对象
    const observer = new MutationObserver(function (records, itself) {
        recordsList.push(records);
        //进入后停止侦听
        let flag = false;
        let obsArr = [];
        let selfIndex = -1;
        let doc = -1;
        //找到当前对象对应的value,和索引,以及k
        for (let key of observerMap.keys()) {
            let t = observerMap.get(key);
            for (let i = 0; i < t.length; i++) {
                if (itself === t[i][0]) {
                    obsArr = t;
                    selfIndex = i;
                    doc = key;
                    flag = true;
                    break;
                }
            }
            if (flag) {
                break;
            }
        }
        if (selfIndex === -1) {
            console.error('没有找到obs的v');
            return;
        }
        /*停止与之相同config的obs*/
        for (let i = 0; i < obsArr.length; i++) {
            if (JSON.stringify(obsArr[i][1]) === JSON.stringify(obsArr[selfIndex][1])) {
                obsArr[i][0].disconnect()
            }
        }
        /*调用与之相同config的obs*/
        try {
            for (let i = 0; i < obsArr.length; i++) {
                if (JSON.stringify(obsArr[i][1]) === JSON.stringify(obsArr[selfIndex][1])) {
                    obsArr[i][2](records);
                }
            }
        } catch (e) {
            console.error('执行错误')
        }
        //启用与之相同config的obs
        for (let i = 0; i < obsArr.length; i++) {
            if (JSON.stringify(obsArr[i][1]) === JSON.stringify(obsArr[selfIndex][1])) {
                obsArr[i][0].observe(doc, obsArr[i][1]);
            }
        }
    });
    if (observerMap.get(document) !== undefined) {
        let v = observerMap.get(document);
        v.push([observer, config, func]);
        observerMap.set(document, v);
    } else {
        observerMap.set(document, [[observer, config, func]]);
    }
    /*开始侦听*/
    observer.observe(document, config);
}

(function () {
    /*立即执行*/
    console.time('初始原文化 ,时间');
    递归(document.body, 原文化);
    console.timeEnd('初始原文化 ,时间');
    console.time('初始字典翻译,时间');
    递归(document.body, 字典翻译);
    console.timeEnd('初始字典翻译,时间');
    /*当body发生变化时执行*/
    dom修改事件(document.body, (records) => {
        console.time('原文化 ,时间');
        for (let i = 0, len = records.length; i < len; i++) {
            递归(records[i].target, 原文化);
        }
        console.timeEnd('原文化 ,时间');
        console.time('字典翻译,时间');
        for (let i = 0, len = records.length; i < len; i++) {
            递归(records[i].target, 字典翻译);
        }
        console.timeEnd('字典翻译,时间');
    });

    function 原文化(node, value, attribute = 'Text') {
        if (value == null || value.trim().length === 0) return;
        value = value.trim();

        if (attribute === 'Text') {
            let title = node.parentNode.getAttribute("title");
            if (内容判定(title, value)) {
                node.parentNode.setAttribute("title", value);
                node.nodeValue = title;
                // console.log(value+'->'+title)
            }
        } else {
            let title = node.getAttribute("title");
            if (内容判定(title, value)) {
                //若为通常节点则正常设置属性
                node.setAttribute('title', value);
                node.setAttribute(attribute, title);
                // console.log(value+'->'+title)
            }
        }

        /**
         * 显示的部分不为中文或日文,并且交换的部分为中文或日文
         * 且不应只有空格和> (标签链接浏览器页vn匹配)
         * 并且value没有对应翻译值,title没有翻译过[通过查找' \t\n'标记判断]
         * @param title
         * @param value
         * @returns {boolean}
         */
        function 内容判定(title, value) {
            return title != null
                && !/[\u4E00-\u9FA5ぁ-んァ-ヶ]+/.test(value)
                && !/^[> ]+$/.test(value)
                && /[\u4E00-\u9FA5ぁ-んァ-ヶ]+/.test(title)
                && mainMap[value]===undefined
                && title.indexOf(' \t\n')===-1;
        }
    }

    function 字典翻译(node, value, attribute = 'Text') {
        if (value == null || value.trim().length === 0) return;
        value = value.trim();
        /** titleMap翻译*/
        if (attribute==='title'){
            if(mainMap[value] === undefined
                &&node.nodeType === 1&&node.title
                ){
                /*如果为节点类型,value没有翻译,且存在title*/
                let flag=true;
                /*判断子节点文本,若文本为中文日文或匹配mainMap或与title相等,则执行后续操作*/
                let nodelist=node.childNodes;
                for (let i=0;i<nodelist.length;++i){
                    if (nodelist[i].nodeType===3&&
                        (/[\u4E00-\u9FA5ぁ-んァ-ヶ]+/.test(nodelist[i].nodeValue)
                            ||mainMap[nodelist[i].nodeValue] !== undefined
                            ||node.title===nodelist[i].nodeValue)
                    ){
                        flag=false;
                        break;
                    }
                }
                if (flag){/*加上翻译信息*/
                    if (titleMap[node.title] !== undefined) {
                        node.title=titleMap[node.title]+" \t\n"+node.title;
                    }else if (mainMap[node.title]!==undefined){
                        node.title=mainMap[node.title]+" \t\n"+node.title;
                    }
                }
            }
            return;
        }
        /** mainMap翻译*/
        if (mainMap[value] !== undefined) {
            if (attribute === 'Text') {
                //若为文本节点则追加父节点title属性
                let title = node.parentNode.getAttribute('title');
                if (title != null && title.trim() !== value) {
                    node.parentNode.setAttribute('title', title + ' ' + value);
                } else {
                    node.parentNode.setAttribute('title', value);
                }
                node.nodeValue = mainMap[value];
            } else {
                //若为通常节点则正常设置属性
                node.setAttribute('title', value);
                node.setAttribute(attribute, mainMap[value])
            }
        }else {
            /** specialMap正则翻译*/
            //遍历specialMap,正则替换
            for (let key of specialMap.keys()) {
                /*正则匹配*/
                if (key.test(value)) {
                    /*正则替换*/
                    let newValue = value.replace(key, specialMap.get(key));

                    /*若有循环替换符,则进行替换*/
                    let nvs = newValue.split('%%');

                    /*如果map的值没有中文,且带%%%%,则设置flag为true*/
                    let flag = false;
                    if (!/[\u4E00-\u9FA5]+/.test(specialMap.get(key))
                        && nvs.length !== 1 && nvs.length % 2 === 1) {
                        flag = true;
                    }
                    if (nvs.length !== 1 && nvs.length % 2 === 1) {
                        for (let i = 1; i < nvs.length; i += 2) {
                            /*转小写*/
                            let low = nvs[i].split('@@');
                            if (low.length === 3) {
                                nvs[i] = low[1].toLowerCase();
                            }
                            /*匹配mainMap*/
                            if (mainMap[nvs[i]] !== undefined) {
                                nvs[i] = mainMap[nvs[i]];
                                /*若找到map,则重新置flag为false*/
                                flag = false;
                            }
                        }
                        newValue = nvs.join('')
                    }
                    if (flag) {/*如果替换式没有中文,且%%%%也没有匹配,则跳过*/
                        continue;
                    }
                    if (attribute === 'Text') {
                        //若为文本节点则追加父节点title属性
                        let title = node.parentNode.getAttribute('title');
                        if (title != null && title.trim() !== value) {
                            node.parentNode.setAttribute('title', title + ' ' + value);
                        } else {
                            node.parentNode.setAttribute('title', value);
                        }
                        node.nodeValue = newValue;
                    } else {
                        //若为通常节点则正常设置属性
                        node.setAttribute('title', value);
                        node.setAttribute(attribute, newValue)
                    }
                    // console.log(value+'->'+newValue);
                    /*替换后结束遍历*/
                    break;
                }
            }
        }
    }
})();


/**-----------------------------开发用函数部分[350行]----------------------------------*/
/** 开启后通过控制台调用函数即可*/
let 开发者模式 = false;
if (开发者模式) {
    /*exportMap已弃用*/
    /**
     * 导出新的已被翻译的内容到控制台显示
     * <br>即手动在网页上改文本,注意:
     * <br>先在要翻译的文本中间写入翻译后的内容
     * <br>然后用del和backspace删除前后内容
     * <br>开启编辑模式:
     * <br>document.body.contentEditable='true';
     * <br>document.designMode='on';
     */
    exportMap = function () {
        let addMap = {};
        递归(document.body, 数据处理);
        /*导出到控制台处理*/
        console.log(JSON.stringify(addMap));

        function 数据处理(node, value, attribute = 'Text') {
            if (value == null || value.trim().length === 0) return;
            value = value.trim();
            //没有在map中找到翻译
            if (mainMap[value] === undefined) {
                //是中文、不是日文
                if (/[\u4E00-\u9FA5]+/.test(value) &&
                    !/[ぁ-んァ-ヶ]+/.test(value)) {
                    if (attribute === 'Text') {
                        node = node.parentNode;
                    }
                    let title = node.getAttribute('title');
                    //如果title没有翻译,则记录
                    if (title !== null && mainMap[title] === undefined) {
                        addMap[title] = value;
                    }
                }
            }
        }
    };
    /*** 记录所有满足条件的未翻译内容<br>缺点为找不到上下文*/
    noMap = {};
    /*** 记录所有满足条件的未翻译提示信息<br>缺点为找不到上下文*/
    noTitleMap={};
    /*** <s>用以复制value到title[已弃用]</s>
     * <br>现用来导出未翻译的title和value,map->控制台
     * <br>若出现新元素,请手动通过控制台重新调用
     * <br>若干扰项太多,可以通过删除干扰元素,再重新调用
     * */
    copyToTitle = () => {
        //清空
        noMap = {};
        noTitleMap={};
        递归(document.body, 数据处理);
        console.log(JSON.stringify(noMap));
        console.log(JSON.stringify(noTitleMap));

        function 数据处理(node, value, attribute = 'Text') {
            if (value == null || value.trim().length === 0) return;
            value = value.trim();
            //没有在map中找到翻译
            if (mainMap[value] === undefined) {
                //1<长度<300,不为中文、日文,不是纯数字
                if (1 < value.length && value.length < 300
                    && !/[\u4E00-\u9FA5ぁ-んァ-ヶ]+/.test(value)
                    && !/^[\d]+$/.test(value)) {
                    //归一化处理
                    if (attribute === 'Text') {
                        node = node.parentNode;
                    }
                    let title = node.getAttribute('title');
                    //title属性为中文或日文时不执行后续操作
                    if (title != null && /[\u4E00-\u9FA5ぁ-んァ-ヶ]+/.test(title)) {
                        return;
                    }
                    //未翻译的节点title
                    if(title!= null&&titleMap[title]===undefined){
                        let flag=true;
                        /*判断子节点文本,若文本为中文日文或匹配mainMap或与title相等,则不添加到未翻译title*/
                        let nodelist=node.childNodes;
                        for (let i=0;i<nodelist.length;++i){
                            if (nodelist[i].nodeType===3&&
                                (/[\u4E00-\u9FA5ぁ-んァ-ヶ]+/.test(nodelist[i].nodeValue)
                                ||mainMap[nodelist[i].nodeValue] !== undefined
                                ||title===nodelist[i].nodeValue)
                            ){
                                flag=false;
                                break;
                            }
                        }
                        /*如果存在title,且title没有定义在mainMap*/
                        /*那么添加到待翻译title信息*/
                        if (flag){
                            noTitleMap[title] = title.toLowerCase();
                        }
                    }
                    //复制value->title
                    // if (title != null && title.trim() !== value) {
                    //     node.setAttribute('title', title + ' ' + value);
                    // } else {
                    //     node.setAttribute('title', value);
                    // }
                    //设置没有翻译的map标记
                    noMap[value] = value.toLowerCase();
                }
            }
        }
    };
    /*立即执行*/
    copyToTitle();
    /**
     *统计不应该匹配,但可以匹配的k->v与正则,用以将局部map升级到主map
     * @type {{Object}}
     */
    otherLog = GM_getValue('otherLog') || {};
    console.log(otherLog);
    delotherLog = () => {
        GM_deleteValue('otherLog');
    };
    /**
     * 按降序显示otherLog数组
     */
    showotherLog=()=>{
        //复制一份
        let temp=JSON.parse(JSON.stringify(otherLog));
        let k = Object.getOwnPropertyNames(temp);
        let otherLogList=[];
        for (let i = 0, len = k.length; i < len; i++) {
            temp[k[i]].unshift(k[i]);
            otherLogList.push(temp[k[i]]);
        }
        /*排序*/
        otherLogList.sort(function (obj1, obj2) {
            return obj2[1] - obj1[1];
        });
        console.log(otherLogList);

        let sb='匹配项\t匹配数\t匹配时机\t匹配结果\n';
        for (let i=0,len=otherLogList.length;i<len;i++){
            sb+=otherLogList[i].join('\t')+'\n'
        }
        console.log(sb)
    };
    /*未生效规则匹配测试,用以筛选常用规则手动上移至主规则*/
    (() => {
        /*object转Map,将其他没有生效的map合起来*/
        let otherMap = {};
        let otherTitleMap={};
        let otherSpecialMap = new Map();
        otherPageRules.forEach((item) => {
            let pathname = window.location.pathname;
            if (item.regular !== undefined && item.regular instanceof RegExp && !item.regular.test(pathname)) {
                let k = Object.getOwnPropertyNames(item.specialMap);
                for (let i = 0, len = k.length; i < len; i++) {
                    try {
                        otherSpecialMap.set(new RegExp(k[i]), item.specialMap[k[i]]);
                    } catch (e) {
                        console.log('"' + k[i] + '"不是一个合法正则表达式');
                    }
                }
                Object.assign(otherMap, item.map);
                Object.assign(otherTitleMap, item.titleMap);
            }
        });
        /*立即执行*/
        console.time('初始其他规则,调试');
        递归(document.body, 未生效规则匹配测试);
        console.timeEnd('初始其他规则,调试');
        /*当body发生变化时执行*/
        dom修改事件(document.body, (records) => {
            console.time('其他规则,调试');
            for (let i = 0, len = records.length; i < len; i++) {
                递归(records[i].target, 未生效规则匹配测试);
            }
            console.timeEnd('其他规则,调试');
            /*若不相等则更新并输出*/
            if (JSON.stringify(otherLog) !== JSON.stringify(GM_getValue('otherLog') || {})) {
                GM_setValue('otherLog', otherLog);
                console.log(otherLog);
            }
        });

        /**
         * 统计不应该匹配,但可以匹配的k->v与正则,用以将局部map升级到主map
         * @param key
         * @param value
         */
        function otherLogAdd(key, value) {
            if (otherLog[key] === undefined) {
                otherLog[key] = [1, value[0], value[1]];
            } else {
                let item = otherLog[key];
                item[0]++;
                /*去重*/
                let a1 = item[1].split('$$');
                a1.push(value[0]);
                let mySet = new Set(a1);
                a1 = [...mySet];
                item[1] = a1.join('$$');

                a1 = item[2].split('$$');
                a1.push(value[1]);
                mySet = new Set(a1);
                a1 = [...mySet];
                item[2] = a1.join('$$');
            }
        }

        function 未生效规则匹配测试(node, value, attribute = 'Text') {
            if (value == null || value.trim().length === 0) return;
            value = value.trim();
            /*不被mainMap和specialMap匹配*/
            /*由于执行顺序的原因,该判断基本没有意义*/
            if (mainMap[value] !== undefined) {
                return;
            }
            /*因为正则涉及匹配可能太广,所以不排除*/
            // for (let key of specialMap.keys()) {
            //     if (key.test(value)) {
            //         return;
            //     }
            // }

            /*1<长度<300,不为中文、日文,不是纯数字,降低缩进*/
            let f = true;
            if (1 < value.length && value.length < 300
                && !/[\u4E00-\u9FA5ぁ-んァ-ヶ]+/.test(value)
                && !/^[\d]+$/.test(value)) {
                f = false;
            }
            if (f) return;
            /*title翻译*/
            /** titleMap翻译*/
            if (attribute==='title'){
                if(otherMap[value] === undefined
                    &&node.nodeType === 1&&node.title
                ){
                    /*如果为节点类型,value没有翻译,且存在title*/
                    let flag=true;
                    /*判断子节点文本,若文本为中文日文或匹配mainMap或与title相等,则执行后续操作*/
                    let nodelist=node.childNodes;
                    for (let i=0;i<nodelist.length;++i){
                        if (nodelist[i].nodeType===3&&
                            (/[\u4E00-\u9FA5ぁ-んァ-ヶ]+/.test(nodelist[i].nodeValue)
                                ||otherMap[nodelist[i].nodeValue] !== undefined
                                ||node.title===nodelist[i].nodeValue)
                        ){
                            flag=false;
                            break;
                        }
                    }
                    if (flag){/*加上翻译信息*/
                        let title=node.title;
                        if (otherTitleMap[title] !== undefined) {
                            node.title=otherTitleMap[title]+" \t\n"+title;
                            otherLogAdd(title, ['otherTitleMap匹配', otherTitleMap[title]]);
                        }else if (otherMap[node.title]!==undefined){
                            node.title=otherMap[title]+" \t\n"+title;
                            otherLogAdd(title, ['otherTitleMap->otherMap匹配', otherMap[title]]);
                        }
                    }
                }
                return;
            }


            if (otherMap[value] !== undefined) {
                if (attribute === 'Text') {
                    //若为文本节点则追加父节点title属性
                    let title = node.parentNode.getAttribute('title');
                    if (title != null && title.trim() !== value) {
                        node.parentNode.setAttribute('title', title + ' ' + value);
                    } else {
                        node.parentNode.setAttribute('title', value);
                    }
                    node.nodeValue = otherMap[value];
                    otherLogAdd(value, ['otherMap匹配,Text', otherMap[value]]);

                } else {
                    //若为通常节点则正常设置属性
                    node.setAttribute('title', value);
                    node.setAttribute(attribute, otherMap[value]);
                    otherLogAdd(value, ['otherMap匹配,节点', otherMap[value]]);
                }
            } else {
                //遍历specialMap,正则替换
                for (let key of otherSpecialMap.keys()) {
                    /*正则匹配,降低缩进*/
                    if (!key.test(value)) {continue;}
                    let info = 'otherSpecialMap匹配,正则:' + key + ',';
                    /*正则替换*/
                    let newValue = value.replace(key, otherSpecialMap.get(key));
                    /*若有循环替换符,则进行替换*/
                    let nvs = newValue.split('%%');
                    /*如果map的值没有中文,且带%%%%,则设置flag为true*/
                    let flag = false;
                    if (!/[\u4E00-\u9FA5]+/.test(otherSpecialMap.get(key))
                        && nvs.length !== 1 && nvs.length % 2 === 1) {
                        flag = true;
                    }
                    if (nvs.length !== 1 && nvs.length % 2 === 1) {
                        for (let i = 1; i < nvs.length; i += 2) {
                            /*转小写*/
                            let low = nvs[i].split('@@');
                            if (low.length === 3) {
                                nvs[i] = low[1].toLowerCase();
                            }
                            /*匹配otherMap*/
                            if (otherMap[nvs[i]] !== undefined) {
                                nvs[i] = otherMap[nvs[i]];
                                info += '在otherMap找到%%%%(额外匹配),';
                                /*若找到map,则重新置flag为false*/
                                flag = false;
                            }
                            /*匹配匹配mainMap*/
                            if (mainMap[nvs[i]] !== undefined) {
                                nvs[i] = mainMap[nvs[i]];
                                info += '在mainMap找到%%%%(额外匹配),';
                                /*若找到map,则重新置flag为false*/
                                flag = false;
                            }
                        }
                        newValue = nvs.join('')
                    }
                    /*如果替换式没有中文,且%%%%也没有匹配,则跳过*/
                    if (flag) {continue;}
                    if (attribute === 'Text') {
                        //若为文本节点则追加父节点title属性
                        let title = node.parentNode.getAttribute('title');
                        if (title != null && title.trim() !== value) {
                            node.parentNode.setAttribute('title', title + ' ' + value);
                        } else {
                            node.parentNode.setAttribute('title', value);
                        }
                        node.nodeValue = newValue;
                        info += 'Text';
                    } else {
                        //若为通常节点则正常设置属性
                        node.setAttribute('title', value);
                        node.setAttribute(attribute, newValue);
                        info += '节点';
                    }
                    otherLogAdd(value, [info, newValue]);
                    // console.log(value + '->' + newValue);
                    /*替换后结束遍历*/
                    break;
                }
            }
        }
    })();
}