/* jshint esversion: 8 */ // ==UserScript== // @name 字体渲染(自用脚本) // @namespace https://openuserjs.org/users/t3xtf0rm4tgmail.com // @version 2021.06.26.2 // @icon https://img.icons8.com/ios-filled/50/26e07f/font-style-formatting.png // @description 让每个页面的字体变得有质感,默认使用微软雅黑字体,亦可自定义设置多种中文字体,附加字体描边、字体重写、字体阴影、字体平滑、对特殊样式元素的过滤和许可等效果,脚本菜单中可使用设置界面进行参数设置,亦可对某域名下所有页面进行排除渲染。 // @supportURL https://github.com/F9y4ng/GreasyFork-Scripts/issues // @author F9y4ng // @include * // @grant GM_info // @grant GM_registerMenuCommand // @grant GM.registerMenuCommand // @grant GM_unregisterMenuCommand // @grant GM_getValue // @grant GM.getValue // @grant GM_setValue // @grant GM.setValue // @grant GM_deleteValue // @grant GM.deleteValue // @compatible Chrome 兼容TamperMonkey, ViolentMonkey // @compatible Firefox 兼容Greasemonkey, TamperMonkey, ViolentMonkey // @compatible Opera 兼容TamperMonkey, ViolentMonkey // @compatible Safari 兼容Tampermonkey • Safari // @license GPL-3.0-only // @create 2020-11-24 // @copyright 2020-2021, F9y4ng // @run-at document-start // @downloadURL none // ==/UserScript== !(function () { "use strict"; /* customize */ const isdebug = false; // set "true" to debug scripts, May cause script response slower. const refreshTime = 1e3; // Define data synchronous refresh time, unit is millisecond. /* Perfectly Compatible For Greasemonkey4.0+, TamperMonkey, ViolentMonkey * F9y4ng * 20210609 */ let GMsetValue, GMgetValue, GMdeleteValue, GMregisterMenuCommand, GMunregisterMenuCommand; const GMinfo = GM_info; const handlerInfo = GMinfo.scriptHandler; const isGM = Boolean(handlerInfo.toLowerCase() === "greasemonkey"); const debug = isdebug ? console.log.bind(console) : () => {}; const error = isdebug ? console.error.bind(console) : () => {}; const defCon = { scriptName: GMinfo.script.name, curVersion: GMinfo.script.version, supportURL: GMinfo.script.supportURL, guideUrl: "https://openuserjs.org/scripts/t3xtf0rm4tgmail.com/%E5%AD%97%E4%BD%93%E6%B8%B2%E6%9F%93%EF%BC%88%E8%87%AA%E7%94%A8%E8%84%9A%E6%9C%AC%EF%BC%89", randString: (n, v, r, s = "") => { // v: true for only letters. let a = "0123456789"; let b = "abcdefghijklmnopqrstuvwxyz"; let c = b.toUpperCase(); n = Number.isFinite(n) ? n : 10; v ? (r = b + c) : (r = a + b + a + c); for (; n > 0; --n) { s += r[Math.floor(Math.random() * r.length)]; } return s; }, }; defCon.rndClass = defCon.randString(10, true); defCon.rndId = defCon.randString(12, true); /* GM selector */ if (isGM) { GMsetValue = GM.setValue; GMgetValue = GM.getValue; GMdeleteValue = GM.deleteValue; GMregisterMenuCommand = GM.registerMenuCommand; GMunregisterMenuCommand = () => {}; } else { GMsetValue = GM_setValue; GMgetValue = GM_getValue; GMdeleteValue = GM_deleteValue; GMregisterMenuCommand = GM_registerMenuCommand; GMunregisterMenuCommand = GM_unregisterMenuCommand; } /* Passive event listeners */ let supportsPassive = false; try { let opts = Object.defineProperty({}, "passive", { get: function () { return (supportsPassive = true); }, }); window.addEventListener("testPassive", null, opts); window.removeEventListener("testPassive", null, opts); } catch (e) { error("//-> ", e); } /* Get browser core & system parameters */ const browser = { versions: (function () { let u = navigator.userAgent; return { edg: u.indexOf("edg") > -1 /* edge */, presto: u.indexOf("Presto") > -1 /* opera */, webKit: u.indexOf("AppleWebKit") > -1 /* chromium */, gecko: u.indexOf("Gecko") > -1 && u.indexOf("KHTML") === -1 /* firefox */, mobile: !!u.match(/AppleWebKit.*Mobile.*/) || !!u.match(/AppleWebKit/) /* mobile */, ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) /* ios */, android: u.indexOf("Android") > -1 || u.indexOf("Linux") > -1 /* android */, iPhone: u.indexOf("iPhone") > -1 || u.indexOf("Mac") > -1 /* iPhone */, iPad: u.indexOf("iPad") > -1 /* ipad */, webApp: u.indexOf("Safari") === -1 /* webApp */, }; })(), language: (navigator.browserLanguage || navigator.language).toLowerCase() /* language */, platform: navigator.platform /* platform */, cookies: navigator.cookieEnabled /* cookies */, }; /* Color Picker init */ const addClassName = (node, str) => { if ( node.className.split(" ").filter(s => { return s === str; }).length === 0 ) { node.className += ` ${str}`; } }; const removeClassName = (node, str) => { node.className = node.className .split(" ") .filter(s => { return s !== str; }) .join(" "); }; const numberBorder = (num, max, min) => { return Math.max(Math.min(num, max), min); }; const rgbToHsb = hex => { const hsb = { h: 0, s: 0, b: 0 }; if (hex.indexOf("#") === 0) { hex = hex.substring(1); } if (hex.length === 3) { hex = hex .split("") .map(s => { return s + s; }) .join(""); } if (hex.length !== 6) { return false; } hex = [hex.substr(0, 2), hex.substr(2, 2), hex.substr(4, 2)].map(s => { return parseInt(s, 16); }); const rgb = { r: hex[0], g: hex[1], b: hex[2], }; const MAX = Math.max(...hex); const MIN = Math.min(...hex); // H start if (MAX === MIN) { hsb.h = 0; } else if (MAX === rgb.r && rgb.g >= rgb.b) { hsb.h = (60 * (rgb.g - rgb.b)) / (MAX - MIN) + 0; } else if (MAX === rgb.r && rgb.g < rgb.b) { hsb.h = (60 * (rgb.g - rgb.b)) / (MAX - MIN) + 360; } else if (MAX === rgb.g) { hsb.h = (60 * (rgb.b - rgb.r)) / (MAX - MIN) + 120; } else if (MAX === rgb.b) { hsb.h = (60 * (rgb.r - rgb.g)) / (MAX - MIN) + 240; } // H end if (MAX === 0) { hsb.s = 0; } else { hsb.s = 1 - MIN / MAX; } hsb.b = MAX / 255; return hsb; }; const heightToRgb = heightPercent => { heightPercent = 1 - heightPercent; let rgb = { r: undefined, g: undefined, b: undefined }; const percentInEach = heightPercent * 6; return Object.entries(rgb).reduce((lastObj, nowArr, index) => { return Object.assign(lastObj, { [nowArr[0]]: Math.floor( (function () { const left = ((index + 1) % 3) * 2; const right = left + 2; const differenceL = percentInEach - left; const differenceR = right - percentInEach; if (differenceL >= 0 && differenceR >= 0) { return 0; } const distance = Math.min(Math.abs(differenceL), Math.abs(differenceR), Math.abs(6 - differenceL), Math.abs(6 - differenceR)); return Math.min(255, 255 * distance); })() ), }); }, {}); }; const heightAddLAndT_ToRGB = (height, left, top) => { const rgb = heightToRgb(height); for (const key in rgb) { rgb[key] = (255 - rgb[key]) * (1 - left) + rgb[key]; rgb[key] = rgb[key] * (1 - top); } return rgb; }; const rgbAToHex = (rgba, err) => { rgba = rgba.replace(/\s+/g, ""); let pattern = /^rgba?\((\d+),(\d+),(\d+),?(\d*(\.\d+)?)?\)$/; let result = pattern.exec(rgba); if (!result) { return err; } let colors = []; let alpha, r, g, b; if (/^rgba/.test(result[0])) { alpha = result[4]; r = Math.floor(alpha * parseInt(result[1]) + (1 - alpha) * 255); g = Math.floor(alpha * parseInt(result[2]) + (1 - alpha) * 255); b = Math.floor(alpha * parseInt(result[3]) + (1 - alpha) * 255); return String(("0" + r.toString(16)).slice(-2) + ("0" + g.toString(16)).slice(-2) + ("0" + b.toString(16)).slice(-2)); } else { for (let i = 1, len = 3; i <= len; ++i) { let str = Number(result[i]).toString(16); if (str.length === 1) { str = 0 + str; } colors.push(str); } rgba = colors.join(""); return rgba; } }; const rgbToHex = rgb => { const { r, g, b } = rgb; return Math.floor(r).toString(16).padStart(2, "0") + Math.floor(g).toString(16).padStart(2, "0") + Math.floor(b).toString(16).padStart(2, "0"); }; const hexToRgb = hex => { return { r: parseInt(hex.substr(0, 2), 16), g: parseInt(hex.substr(2, 2), 16), b: parseInt(hex.substr(4, 2), 16), }; }; const cE = str => { return document.createElement(str); }; class ColorPicker { constructor({ dom = cE("div"), value = "FFF", def = "FFF" } = {}) { this.dom = dom; this.def = def; const thisClass = this; Array.prototype.forEach.call(this.getDOM().children, node => { node.remove(); }); addClassName(dom, "fr-color-picker"); const rightBar = cE("div"); rightBar.className = "fr-color-picker-right-bar"; const rightBarPicker = cE("div"); rightBarPicker.className = "fr-color-picker-right-bar-picker"; rightBar.appendChild(rightBarPicker); const gradientColor = cE("div"); gradientColor.className = "fr-color-picker-gradients fr-color-picker-gradient-color"; const gradientBlack = cE("div"); gradientBlack.className = "fr-color-picker-gradients fr-color-picker-gradient-black"; gradientColor.style.background = "linear-gradient(to right,#FFFFFF,#FF0000)"; const gradientCircle = cE("div"); gradientCircle.className = "fr-color-picker-circle"; gradientBlack.appendChild(gradientCircle); this.getDOM().appendChild(rightBar); this.getDOM().appendChild(gradientColor); this.getDOM().appendChild(gradientBlack); document.querySelector(".cpicker-2 #color").addEventListener("change", () => { let color = document.querySelector(".cpicker-2 #color").value; this.setValue(color, true); this.onchange(); this.updatePicker(); }); this.textInput = document.querySelector(".cpicker-2 #color"); this._gradientBlack = gradientBlack; this._gradientColor = gradientColor; this._rightBar = rightBar; this._rightBarPicker = rightBarPicker; this._colorBlock = document.querySelector("#fr-color-picker-show"); this._gradientCircle = gradientCircle; this._height = 0; this._mouseX = 0; this._mouseY = 0; this.setValue(value, true); this._lastValue = this.value; this._def = this.def.substring(1); this.updatePicker(); const mouseMoveFun = e => { window.addEventListener("mouseup", function mouseUpFun() { thisClass.getDOM().style.userSelect = "text"; window.removeEventListener("mousemove", mouseMoveFun); window.removeEventListener("mouseup", mouseUpFun); }); const bbox = thisClass._gradientBlack.getBoundingClientRect(); this._mouseX = e.clientX - bbox.left; // * (p.width / bbox.width) this._mouseY = e.clientY - bbox.top; // * (p.height / bbox.height) this.mouseBorder(); this.setValue(heightAddLAndT_ToRGB(this.height, this.position.x, this.position.y)); this.updatePicker(); }; const mouseMoveFunBar = e => { window.addEventListener("mouseup", function mouseUpFunBar() { thisClass.getDOM().style.userSelect = "text"; window.removeEventListener("mousemove", mouseMoveFunBar); window.removeEventListener("mouseup", mouseUpFunBar); }); const bbox = thisClass._rightBar.getBoundingClientRect(); this._height = e.clientY - bbox.top; // * (p.height / bbox.height) this.mouseBorderBar(); this.setValue(heightAddLAndT_ToRGB(this.height, this.position.x, this.position.y)); this.updatePicker(); }; this._gradientBlack.addEventListener("mousedown", e => { this.getDOM().style.userSelect = "none"; mouseMoveFun(e); window.addEventListener("mousemove", mouseMoveFun); }); this._rightBar.addEventListener("mousedown", e => { this.getDOM().style.userSelect = "none"; mouseMoveFunBar(e); window.addEventListener("mousemove", mouseMoveFunBar); }); if ("ontouchstart" in window) { const touchFun = e => { e.preventDefault(); e = e.touches[0]; const bbox = thisClass._gradientBlack.getBoundingClientRect(); this._mouseX = e.clientX - bbox.left; // * (p.width / bbox.width) this._mouseY = e.clientY - bbox.top; // * (p.height / bbox.height) this.mouseBorder(); this.setValue(heightAddLAndT_ToRGB(this.height, this.position.x, this.position.y)); this.updatePicker(); }; const touchFunBar = e => { e.preventDefault(); e = e.touches[0]; const bbox = this._rightBar.getBoundingClientRect(); this._height = e.clientY - bbox.top; // * (p.height / bbox.height) this.mouseBorderBar(); this.setValue(heightAddLAndT_ToRGB(this.height, this.position.x, this.position.y)); this.updatePicker(); }; this._gradientBlack.addEventListener("touchmove", touchFun, supportsPassive ? { passive: true } : false); this._gradientBlack.addEventListener("touchstart", touchFun, supportsPassive ? { passive: true } : false); this._rightBar.addEventListener("touchmove", touchFunBar, supportsPassive ? { passive: true } : false); this._rightBar.addEventListener("touchstart", touchFunBar, supportsPassive ? { passive: true } : false); } this._changeFunctions = []; } onchange() { this._changeFunctions.forEach(fun => { return fun({ target: this, type: "change", timeStamp: performance.now(), }); }); } addEventListener(type, fun) { if (typeof fun !== "function") { return; } switch (type) { case "change": { this._changeFunctions.push(fun); break; } } } getValue(mode = "value") { switch (mode) { case "hex": { return this._value; } case "rgb": { return hexToRgb(this.getValue("hex")); } case "hsb": { return rgbToHsb(this.getValue("hex")); } case "value": default: { return "#" + this._value; } } } getBrightness() { const { r, g, b } = this.getValue("rgb"); return 0.299 * r + 0.587 * g + 0.114 * b; } setValue(value, resetPosition = false) { let hex = ""; const Hex6Reg = /^#([A-F0-9]{6}|[a-f0-9]{6})$/; const Hex3Reg = /^#([A-F0-9]{3}|[a-f0-9]{3})$/; const rgbaReg = /^rgba\(([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2([0-4][0-9]|5[0-5]))),\s*([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2([0-4][0-9]|5[0-5]))),\s*([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2([0-4][0-9]|5[0-5]))),\s*((?!1.[1-9])[0-1]?(\.[0-9]{1,3})?)\)$/; const rgbReg = /^rgb\(([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2([0-4][0-9]|5[0-5]))),\s*([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2([0-4][0-9]|5[0-5]))),\s*([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2([0-4][0-9]|5[0-5])))\)$/; switch (typeof value) { case "string": { if (Hex6Reg.test(value)) { value = value.substring(1); } else if (Hex3Reg.test(value)) { value = value .substring(1) .split("") .map(s => { return s + s; }) .join(""); } else if (rgbaReg.test(value)) { value = rgbAToHex(value, this._def); } else if (rgbReg.test(value)) { value = rgbAToHex(value, this._def); } else if (value === "currentcolor") { value = "FFFFFF"; } else { value = this._def; } hex = value; break; } case "object": { hex = rgbToHex(value); } } let rgb; try { rgb = hexToRgb(hex); } catch (error) { rgb = { r: 255, g: 255, b: 255, }; } const { r, g, b } = rgb; this._value = rgbToHex({ r, g, b }).toUpperCase(); this.textInput.value = this._value === "FFFFFF" ? "currentcolor" : "#" + this._value; this._colorBlock.style.backgroundColor = this.getValue(); if (resetPosition) { const { h, s, b } = rgbToHsb(hex); this._height = 1 - h / 360; if (h === 0) { this._height = 0; } this._mouseX = s; this._mouseY = 1 - b; } else { if (this._lastValue !== this.value) { this.onchange(); } } this._lastValue = this.value; } getDOM() { return this.dom; } mouseBorder() { this._mouseX = numberBorder(this._mouseX / (this._gradientBlack.getBoundingClientRect().width - 2), 1, 0); this._mouseY = numberBorder(this._mouseY / (this._gradientBlack.getBoundingClientRect().height - 2), 1, 0); } mouseBorderBar() { this._height = numberBorder(this._height / (this._rightBar.getBoundingClientRect().height - 2), 1, 0); } updatePicker() { const position = this.position; const target = this._gradientCircle; target.style.left = `${position.x * 100}%`; target.style.top = `${position.y * 100}%`; this._rightBarPicker.style.top = `${this.height * 100}%`; this._gradientColor.style.background = `linear-gradient(to right,#FFFFFF,#${rgbToHex(heightToRgb(this.height))})`; if (this.getBrightness() > 152) { addClassName(target, "fr-color-picker-circle-black"); removeClassName(target, "fr-color-picker-circle-white"); } else { removeClassName(target, "fr-color-picker-circle-black"); addClassName(target, "fr-color-picker-circle-white"); } } get position() { return { x: this._mouseX, y: this._mouseY, }; } get height() { return this._height; } get value() { return this.getValue(); } set value(value) { this.setValue(value, true); this.updatePicker(); } } /* new frDialogBox */ class frDialogBox { constructor({ titleText = "Error", messageText = "Something unexpected has gone wrong. If the problem persists, contact your administrator", trueButtonText = "OK", falseButtonText = null, neutralButtonText = null, } = {}) { this.titleText = titleText; this.messageText = messageText; this.trueButtonText = trueButtonText; this.falseButtonText = falseButtonText; this.neutralButtonText = neutralButtonText; this.hasFalse = falseButtonText !== null; this.hasNeutral = neutralButtonText !== null; this.frDialog = undefined; this.trueButton = undefined; this.falseButton = undefined; this.neutralButton = undefined; this.parent = document.body; this._createfrDialog(this); this._appendfrDialog(); } _createfrDialog(context) { this.frDialog = document.createElement("div"); this.frDialog.classList.add("frDialog-box"); this.frDialog.style.opacity = 0; const title = document.createElement("div"); title.textContent = this.titleText; title.classList.add("frDialog-box-title"); this.frDialog.appendChild(title); const question = document.createElement("div"); question.innerHTML = this.messageText; question.classList.add("frDialog-box-message"); this.frDialog.appendChild(question); const buttonContainer = document.createElement("div"); buttonContainer.classList.add("frDialog-box-button-container"); this.frDialog.appendChild(buttonContainer); this.trueButton = document.createElement("a"); this.trueButton.classList.add("frDialog-box-button", "frDialog-box-button--true"); this.trueButton.textContent = this.trueButtonText; this.trueButton.addEventListener("click", function () { context._destroy(); }); buttonContainer.appendChild(this.trueButton); if (this.hasFalse) { this.falseButton = document.createElement("a"); this.falseButton.classList.add("frDialog-box-button", "frDialog-box-button--false"); this.falseButton.textContent = this.falseButtonText; this.falseButton.addEventListener("click", function () { context._destroy(); }); buttonContainer.appendChild(this.falseButton); } if (this.hasNeutral) { this.neutralButton = document.createElement("a"); this.neutralButton.classList.add("frDialog-box-button", "frDialog-box-button--neutral"); this.neutralButton.textContent = this.neutralButtonText; this.neutralButton.addEventListener("click", function () { context._destroy(); }); buttonContainer.appendChild(this.neutralButton); } } _appendfrDialog() { const diag = this.frDialog; if (this.frDialog) { this.parent.appendChild(diag); setTimeout(function () { diag.style.opacity = 1; }, 0); } } _destroy() { if (this.frDialog) { this.parent.removeChild(this.frDialog); delete this; } } respond() { return new Promise((resolve, reject) => { const somethingWentWrongUponCreation = !this.frDialog || !this.trueButton; if (somethingWentWrongUponCreation) { reject(new Error("Something went wrong upon modal creation")); } this.trueButton.addEventListener("click", () => { resolve(true); }); if (this.hasFalse) { this.falseButton.addEventListener("click", () => { resolve(false); }); } }); } } /* Slider Movements init */ class frProgress { constructor(a, c) { let b = void 0 === c ? {} : c; c = void 0 === b.size ? 10 : b.size; let d = void 0 === b.val ? 0 : b.val; let g = void 0 === b.precision ? 0 : b.precision; let h = void 0 === b.range ? 1 : b.range; let k = void 0 === b.getVal ? function () {} : b.getVal; let l = void 0 === b.drag ? !0 : b.drag; let m = void 0 === b.direction ? "horizontal" : b.direction; b = void 0 === b.tip ? !1 : b.tip; if (!a) { error("//-> \u5fc5\u987b\u6307\u5b9a\u5b9e\u4f8b\u5bf9\u8c61\u7684\u5bb9\u5668\uff01"); } this.container = document.querySelector(a); this.size = c; this.val = d; this.precision = g; this.range = h; this.getVal = k; this.drag = l; this.direction = m; if (typeof b === "object") { this.tip = b || { trigger: "show", align: "top", }; } else if ("boolean" !== typeof b) { error("//-> tip\u914d\u7f6e\u9519\u8bef"); } this.initialize(); } initialize() { if ( 0 > this.size || 0 > this.val || 100 < this.val || 0 > this.precision || 4 < this.precision || ("horizontal" !== this.direction && "vertical" !== this.direction) || !this.container || ("boolean" !== typeof this.drag && "object" !== typeof this.drag) ) { return error("//-> \u53c2\u6570\u914d\u7f6e\u9519\u8bef\uff01"); } this.rander(); this.renderLine(); } rander() { this.bgBar = document.createElement("div"); this.bgLine = document.createElement("div"); this.btnTip = document.createElement("div"); let a = this.bgBar; let c = this.container; let b = this.bgLine; let d = this.btnTip; switch (this.direction) { case "horizontal": a.classList.add("frProgressBar"); a.style.height = this.size + "px"; a.style.width = "100%"; a.style.borderRadius = this.size / 2 + "px"; b.appendChild(d); break; case "vertical": a.classList.add("frProgressBar"); a.style.width = this.size + "px"; a.style.height = "100%"; a.style.borderRadius = this.size / 2 + "px"; d.classList.add("vertical"); b.appendChild(d); } d.classList.add("btnll"); d.style.width = this.size + "px"; d.style.height = this.size + "px"; b.classList.add("frProgressLine"); b.style.borderRadius = this.size / 2 + "px"; a.appendChild(b); c.appendChild(a); this.drag ? this.Dragdrop() : this.btnTip.classList.add("disable"); (this.tip || typeof this.tip === "object") && this.openTip(); this.onLoading(); } Dragdrop() { let a = this; let c = this.bgBar; let b = function (d) { a.getPos(d); }; c.addEventListener("mousedown", function (d) { document.addEventListener("mousemove", b); a.getPos(d); }); document.addEventListener("mouseup", function (d) { document.removeEventListener("mousemove", b); }); c.addEventListener( "touchstart", function (d) { document.addEventListener("touchmove", b); a.getPos(d); }, supportsPassive ? { passive: true } : false ); document.addEventListener( "touchend", function (d) { document.removeEventListener("touchmove", b); }, supportsPassive ? { passive: true } : false ); } getPos(a) { typeof a.touches === "undefined" && (a.preventDefault(), a.stopPropagation()); a.touches && (a = a.touches[0]); this.oldVal = this.val; let b, c; switch (this.direction) { case "horizontal": a = a.clientX + this.size / 2; c = this.bgBar.clientWidth; b = this.getElementLeft(this.bgBar); this.val = ((a - b - this.size) / (c - this.size)) * 100; break; case "vertical": a = a.clientY + this.size / 2; c = this.bgBar.clientHeight; b = this.getElementTop(this.bgBar); this.val = 100 - ((a - b - this.size) / (c - this.size)) * 100; } this.val = Math.max(0, this.val); this.val = Math.min(100, this.val); this.renderLine(); this.eventVal(); } getElementLeft(a) { let c = a.offsetLeft; for (a = a.offsetParent; null !== a; a) { c += a.offsetLeft; a = a.offsetParent; } return c; } getElementTop(a) { let c = a.offsetTop; for (a = a.offsetParent; null !== a; a) { c += a.offsetTop; a = a.offsetParent; } return c; } renderLine() { switch (this.direction) { case "horizontal": this.bgLine.style.width = ((this.bgBar.clientWidth - this.size) * this.val) / 100 + this.size + "px"; break; case "vertical": this.bgLine.style.height = ((this.bgBar.clientHeight - this.size) * this.val) / 100 + this.size + "px"; } } eventVal() { this.val = Number(this.val.toFixed(this.precision)); this.oldVal !== this.val && (this.getVal && this.getVal(this), this.tip || typeof this.tip === "object") && (this.tipBox.innerText = String(((this.val / 100) * this.range).toFixed(this.precision + 2))); } updateVal(a) { 0 > a || 100 < a || ((this.val = Number(a)), this.renderLine(), (this.val = Number(a.toFixed(this.precision))), !this.tip && "object" !== typeof this.tip) || (this.tipBox.innerText = String(((this.val / 100) * this.range).toFixed(this.precision + 2))); } openTip() { let a = this.btnTip; this.tipBox = document.createElement("span"); this.tipBox.classList.add("frProgressVal"); this.tipBox.innerText = String(((this.val / 100) * this.range).toFixed(this.precision + 2)); a.appendChild(this.tipBox); this.tip.trigger && this.tipConfig(); } tipConfig() { let a = this; switch (this.tip.trigger) { case "hover": this.tipBox.style.opacity = 0; this.bgBar.addEventListener("mouseenter", function () { return (a.tipBox.style.opacity = 1); }); this.bgBar.addEventListener("mouseleave", function () { return (a.tipBox.style.opacity = 0); }); this.bgBar.addEventListener( "touchstart", function () { return (a.tipBox.style.opacity = 1); }, supportsPassive ? { passive: true } : false ); this.bgBar.addEventListener( "touchend", function () { return (a.tipBox.style.opacity = 0); }, supportsPassive ? { passive: true } : false ); break; case "show": this.tipBox.style.opacity = 1; } switch (this.tip.align) { case "bottom": this.tipBox.classList.add("bottom"); break; case "left": this.tipBox.classList.add("left"); break; case "right": this.tipBox.classList.add("right"); } } onLoading() { let a = (this.btnLoading = document.createElement("span")); let c = this.btnTip; a.classList.add("loading"); c.appendChild(a); a.style.width = c.offsetWidth + "px"; a.style.height = c.offsetHeight + "px"; } onLoad(a, c) { c = void 0 === c ? function () {} : c; if ("boolean" !== typeof a) { error("//-> onload\u914d\u7f6e\u9519\u8bef"); } a && (this.btnLoading.style.display = "block"); c(this); } } function checkdraw(b, a, c) { b.value = Number((a.val / 100) * a.range) ? ((a.val / 100) * a.range).toFixed(a.precision + 2) : "OFF"; b.addEventListener("blur", function () { this.value <= a.range ? ((this.value = Number(this.value.match(c)).toFixed(a.precision + 2)), a.updateVal((100 * this.value) / a.range)) : (this.value = ((a.val / 100) * a.range).toFixed(a.precision + 2)); }); } /* Font filtering & discriminating list */ let fontSet = function (s) { return { that: Array.prototype.slice.call(document.querySelectorAll(s), 0), stopPropagation: function (e) { e = e || window.event; if (e.stopPropagation) { e.stopPropagation(); } else { e.cancelBubble = true; } }, hide: function () { fontSet(s).that.forEach(function (item) { item.style.cssText += "display:none"; }); }, show: function () { fontSet(s).that.forEach(function (item) { item.style.cssText += "display:block"; }); }, fdeleteList: function (fontData) { let ddRemove = function (dd) { let temp = dd.nextElementSibling; dd.remove(); if (temp !== null && temp.nodeName === "DD") { ddRemove(temp); } }; let selector = (function () { class selector { constructor(ch, en) { this.ch = ch; this.en = en; } } return selector; })(); let close = fontSet("#fontSelect .frclose"); close.that.forEach(function (item) { ddRemove(item.parentNode); let value = item.parentNode.children[1].value; let text = item.parentNode.children[0].innerHTML; fontData.push(new selector(text, value)); fontData.sort(); if (fontSet("#fontSelect .frclose").that.length === 0) { fontSet("#fontSelect .selector").that[0].parentNode.style.cssText += "display:none;"; } }); return Boolean(close.that.length); }, fsearchList: function (name) { let arr = []; fontSet("input[name=" + name + "]").that.forEach(item => { arr.push(item.value); }); return arr; }, fsearch: function (fontData) { let domId = fontSet(s).that[0]; let html = String( `
\ud83d\udd14温馨提示:

脚本预载了多种常用的、好看的中文字体,下拉菜单中所罗列的字体是您系统中已安装过的字体,没有安装过则不会显示。

(注一)如果没有重新选择字体,则使用上一次保存的字体。首次使用默认为微软雅黑字体。

(注二)输入框可输入关键字进行搜索,支持中文和英文字体名。

(注三)字体是按您选择的先后顺序进行优先渲染的,所以多选不如之选一个您最想要的。

` ); domId.innerHTML = html; fontSet("#fontSelect .selector").that[0].parentNode.style.cssText += "display:none;"; function clickEvent() { fontSet("#fontSelect .selectFontId dl dd").that.forEach(function (item) { item.onclick = function (e) { let value = this.attributes.value.value.toString(); if (value) { fontSet("#fontSelect .selector").that[0].innerHTML += String( `${this.innerHTML}×` ); fontSet(".selector").that[0].parentNode.style.cssText += "display:block;"; document.querySelector("#stcleaner").addEventListener("click", () => { fontSet().fdeleteList(fontData); }); for (let i = 0; i < fontData.length; i++) { if (fontData[i].en === value) { fontData.splice(i, 1); i = fontData.length; } } removeFontSelector(); } fontSet(".selectFontId dl").hide(); fontSet("#fontSelect .selectFontId input").that[0].value = ""; e.stopPropagation(); }; }); } let ddRemove = function (dd) { let temp = dd.nextElementSibling; dd.remove(); if (temp !== null && temp.nodeName === "DD") { ddRemove(temp); } }; fontSet("#fontSelect .selectFontId input").that[0].oninput = function () { let val = this.value; let dd = fontSet("#fontSelect .selectFontId dl dd").that[0]; if (dd === "DD") { ddRemove(dd); } fontSet("#fontSelect .selectFontId dl").hide(); if (fontData.length > 0) { fontSet("#fontSelect .selectFontId dl").show(); let sear_1 = new RegExp(val, "i"); let judge_1 = false; fontSet("#fontSelect .selectFontId dl").that[0].innerHTML = ""; fontData.forEach(function (item) { if (sear_1.test(item.ch) || sear_1.test(item.en)) { judge_1 = true; fontSet("#fontSelect .selectFontId dl").that[0].innerHTML += String( `
${item.ch}
` ); } }); if (!judge_1) { fontSet("#fontSelect .selectFontId dl").that[0].innerHTML = "
\u6682\u65e0\u60a8\u9700\u8981\u7684\u5b57\u4f53
"; } clickEvent(); } }; fontSet("#fontSelect .selectFontId input").that[0].onclick = function (e) { let dd = fontSet("#fontSelect .selectFontId dl dd").that[0]; if (dd === "DD") { ddRemove(dd); } if (fontData.length === 0) { this.innerHTML = "\u6682\u65e0\u6570\u636e"; } else { fontSet("#fontSelect .selectFontId dl").show(); } fontSet("#fontSelect .selectFontId dl").that[0].innerHTML = ""; fontData.sort(function (a, b) { return a.en - b.en; }); fontData.forEach(function (item) { fontSet("#fontSelect .selectFontId dl").that[0].innerHTML += String( `
${item.ch}
` ); }); clickEvent(); e.stopPropagation(); }; let selector = (function () { class selector { constructor(ch, en) { this.ch = ch; this.en = en; } } return selector; })(); function removeFontSelector() { fontSet("#fontSelect .frclose").that.forEach(function (item) { item.onclick = function () { ddRemove(this.parentNode); let value = this.parentNode.children[1].value; let text = this.parentNode.children[0].innerHTML; fontData.push(new selector(text, value)); if (fontSet("#fontSelect .frclose").that.length === 0) { fontSet("#fontSelect .selector").that[0].parentNode.style.cssText += "display:none;"; } }; }); } document.onclick = function (e) { fontSet("#fontSelect .selectFontId dl").hide(); fontSet("#fontSelect .selectFontId input").that[0].value = ""; }; }, }; }; const fontCheck = new Set( [ { ch: "微软雅黑", en: "Microsoft YaHei" }, { ch: "微软正黑体", en: "Microsoft JhengHei" }, { ch: "苹方-简", en: "PingFang SC" }, { ch: "更纱黑体 SC", en: "Sarasa Gothic SC" }, { ch: "冬青黑体简", en: "Hiragino Sans GB" }, { ch: "兰亭黑-简", en: "Lantinghei SC" }, { ch: "丽黑 Pro", en: "LiHei Pro Medium" }, { ch: "翩翩体-简", en: "Hanzipen SC" }, { ch: "手札体-简", en: "Hannotate SC" }, { ch: "娃娃体-简", en: "Wawati SC" }, { ch: "魏碑-简", en: "Weibei SC" }, { ch: "行楷-简", en: "Xingkai SC" }, { ch: "雅痞-简", en: "Yapi SC" }, { ch: "圆体-简", en: "Yuanti SC" }, { ch: "方正兰亭黑", en: "lanLantinghei SC" }, { ch: "方正兰亭刊宋", en: "FZLanTingKanSongS" }, { ch: "思源黑体", en: "Source Han Sans SC" }, { ch: "思源宋体", en: "Source Han Serif SC" }, { ch: "文泉驿微米黑", en: "WenQuanYi Micro Hei" }, { ch: "文泉驿正黑", en: "WenQuanYi Zen Hei" }, { ch: "汉仪旗黑55S", en: "HYQihei 55S" }, { ch: "新细明体", en: "PMingLiU" }, { ch: "华文黑体", en: "STHeiti" }, { ch: "华文仿宋", en: "STFangsong" }, { ch: "华文楷体", en: "STKaiti" }, { ch: "华文细黑", en: "STXihei" }, { ch: "华文彩云", en: "STCaiyun" }, { ch: "华文琥珀", en: "STHupo" }, { ch: "华文新魏", en: "STXinwei" }, { ch: "华文隶书", en: "STLiti" }, { ch: "华文行楷", en: "STXingkai" }, { ch: "方正舒体", en: "FZShuTi" }, { ch: "方正姚体", en: "FZYaoti" }, { ch: "幼圆", en: "YouYuan" }, ].sort() ); class isSupportFontFamily { constructor() { let baseFonts = ["monospace", "sans-serif", "serif"]; let testString = "mmmmmmmmmmmmmlli.这是测试,這是測試"; let testSize = "72px"; let h = document.getElementsByTagName("body")[0]; let s = document.createElement("span"); s.style.fontSize = testSize; s.innerHTML = testString; let defaultWidth = {}; let defaultHeight = {}; for (let index in baseFonts) { s.style.fontFamily = baseFonts[index]; h.appendChild(s); defaultWidth[baseFonts[index]] = s.offsetWidth; defaultHeight[baseFonts[index]] = s.offsetHeight; h.removeChild(s); } function detect(font) { let detected = false; for (let index in baseFonts) { s.style.fontFamily = "'" + font + "'," + baseFonts[index]; h.appendChild(s); let matched = s.offsetWidth !== defaultWidth[baseFonts[index]] || s.offsetHeight !== defaultHeight[baseFonts[index]]; h.removeChild(s); detected = detected || matched; } return detected; } this.detect = detect; } } /* define default value */ const defValue = { fontSelect: `"Microsoft YaHei",Arial,sans-serif,iconfont,icomoon,FontAwesome,"Material Icons","Material Icons Extended"`, fontFace: true, fontStroke: browser.versions.gecko ? 0.04 : 0.015, fontShadow: browser.versions.webKit ? 2.0 : 1.5, shadowColor: "#7B7B7B", fontSmooth: true, fontCSS: `:not(i):not(em):not([class*="fa"]):not([class*="icon"]):not([class*="logo"]):not([class*="code"])`, fontEx: `* pre,* pre *,* code,* code *,* input,* button,* textarea,* kbd,* i,* em`, }; const feedback = defCon.supportURL ? defCon.supportURL : "https://greasyfork.org/scripts/416688/feedback"; const CONST = {}; /* Determine whether the DOM is loaded */ function addLoadEvent(fn) { document.addEventListener("readystatechange", event => { if (event.target.readyState === "interactive") { fn(); } else if (event.target.readyState === "complete") { let sw = document.querySelector("#frsiteWelcome"); sw.classList.remove("isactived"); debug("//-> DOMs loaded complete!"); } }); } /* Start specific operation */ !(async function () { // Rebuild data for update const rebuild = (await GMgetValue("_rebuild_")) || 0; !Number(rebuild) ? (GMdeleteValue("_fonts_set_"), GMdeleteValue("_Exclude_site_"), GMsetValue("_rebuild_", 1)) : debug("Data is rebuild!"); // Get Promise Value let temp = await GMgetValue("_fonts_set_"); let exSite = await GMgetValue("_Exclude_site_"); /* Real-time update data */ if (!temp && !exSite) { sessionStorage.setItem("_temp_", 1); sessionStorage.setItem("_exSite_", 1); } else { setInterval(async () => { exSite = await GMgetValue("_Exclude_site_"); }, refreshTime); } /* DialogBox for the first visit after upgrading */ addLoadEvent(async () => { if (Number(sessionStorage.getItem("_temp_")) && Number(sessionStorage.getItem("_exSite_"))) { let frDialog = new frDialogBox({ trueButtonText: "好,去看看", falseButtonText: "不,算了吧", messageText: `

您好,这是您首次使用${defCon.scriptName}的新版本 V${defCon.curVersion},新版脚本新增了字体搜索功能、修正了字体阴影渲染造成的模糊问题、重建新的拾色器、优化自由度更高的排除规则等等,具体功能敬请试用。

稍后,将为您打开新版脚本的新功能帮助文件页面,您需要去看一下吗?

`, titleText: "温馨提示", }); sessionStorage.clear(); if (await frDialog.respond()) { window.open(`${defCon.guideUrl}`, "Guide"); } frDialog = null; } }); /* Exclude site */ let siteIndex; let obj = ["workstation-xi"].sort(); if (!exSite) { GMsetValue("_Exclude_site_", obj); exSite = obj; } else { for (let i = 0; i < exSite.length; i++) { if (exSite[i] === location.hostname) { siteIndex = i; break; } } } /* Set Default Value & initialize */ if (!temp) { saveDate("_fonts_set_", { fontSelect: defValue.fontSelect, fontFace: defValue.fontFace, fontStroke: defValue.fontStroke, fontShadow: defValue.fontShadow, shadowColor: defValue.shadowColor, fontSmooth: defValue.fontSmooth, fontCSS: defValue.fontCSS, fontEx: defValue.fontEx, }); CONST.fontSelect = defValue.fontSelect; CONST.fontFace = defValue.fontFace; CONST.fontStroke = defValue.fontStroke; CONST.fontShadow = defValue.fontShadow; CONST.shadowColor = defValue.shadowColor; CONST.fontSmooth = defValue.fontSmooth; CONST.fontCSS = defValue.fontCSS; CONST.fontEx = defValue.fontEx; } else { const fontValue = JSON.parse(temp); CONST.fontSelect = fontValue.fontSelect; CONST.fontFace = fontValue.fontFace; CONST.fontStroke = fontValue.fontStroke; CONST.fontShadow = fontValue.fontShadow; CONST.shadowColor = fontValue.shadowColor; CONST.fontSmooth = fontValue.fontSmooth; CONST.fontCSS = fontValue.fontCSS; CONST.fontEx = fontValue.fontEx; } /* Operation of CSS value */ let shadow = ""; const shadow_r = parseFloat(CONST.fontShadow); const shadow_c = CONST.shadowColor; if (!isNaN(shadow_r) && shadow_r > 0 && shadow_r <= 8) { shadow = `text-shadow:0 0 ${shadow_r}px ${shadow_c};`; } let stroke = ""; const stroke_r = parseFloat(CONST.fontStroke); if (!isNaN(stroke_r) && stroke_r > 0 && stroke_r <= 1.0) { stroke = `text-stroke:${stroke_r}px currentcolor;-webkit-text-stroke:${stroke_r}px currentcolor;`; } let smoothing = ""; const smooth_i = Boolean(CONST.fontSmooth); if (smooth_i) { smoothing = `-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility;`; } const fontfamily = `font-family:${CONST.fontSelect.toString()};`; let refont = CONST.fontSelect.toString().split(",")[0]; refont = refont ? refont.replace(/"|'/g, "") : ""; let fontface = ""; if (CONST.fontFace) { fontface = refont ? `@font-face{font-family:"宋体";src:local("${refont}")}@font-face{font-family:"黑体";src:local("${refont}")}@font-face{font-family:SimHei;src:local("${refont}")}@font-face{font-family:SimSun;src:local("${refont}")}@font-face{font-family:"serif";src:local("${refont}")}@font-face{font-family:"Microsoft YaHei UI";src:local("${refont}")}@font-face{font-family:"Segoe UI";src:local("${refont}")}@font-face{font-family:"sans-serif";src:local("${refont}")}@font-face{font-family:Tahoma;src:local("${refont}")}@font-face{font-family:Arial;src:local("${refont}")}@font-face{font-family:Helvetica;src:local("${refont}")}` : ``; } let exclude = ""; const cssexlude = CONST.fontEx; if (cssexlude) { exclude = `${cssexlude}{font-family:iconfont,icomoon,FontAwesome,"Material Icons","Material Icons Extended",arial,sans-serif;text-stroke:initial!important;-webkit-text-stroke:initial!important;text-shadow:initial!important}`; } const cssfun = CONST.fontCSS; let tshadow = ""; if (siteIndex === undefined) { tshadow = `${cssfun}{${shadow}${stroke}${smoothing}${fontfamily}}${fontface}${exclude}`; } const fontStyle = `.frDialog-box{max-width:400px;color:#444;z-index:9999999;border:2px solid #efefef;-moz-border-radius:24px;border-radius:24px}.frDialog-box .frDialog-box-title,.frDialog-box-button,.frDialog-box-button:hover{text-shadow:initial!important;-webkit-text-stroke:initial!important;text-stroke:initial!important}.frDialog-box-button--false,.frDialog-box-button--false:hover{background:#d93223;color:#fff;border:1px solid #d93223;-moz-border-radius:6px;border-radius:6px;font-size:14px!important}.frDialog-box-button--true,.frDialog-box-button--true:hover{background:#038c5a;color:#fff;border:1px solid #038c5a;-moz-border-radius:6px;border-radius:6px;font-size:14px!important}.frDialog-box-button--neutral,.frDialog-box-button--neutral:hover{background:#777;color:#fff;border:1px solid #777;-moz-border-radius:6px;border-radius:6px;font-size:14px!important}.frDialog-box{display:block;overflow:hidden;position:fixed;top:500px;right:-180px;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;width:100%;background:#fff;-webkit-box-shadow:0 0 10px 0 rgba(0,0,0,.3);-moz-box-shadow:0 0 10px 0 rgba(0,0,0,.3);box-shadow:0 0 10px 0 rgba(0,0,0,.3);transition:opacity .3s;transform:translate(-50%,-50%)}.frDialog-box-message{color:#444;padding:10px;margin:10px;font-size:16px;font-weight:300;text-align:left}.frDialog-box-message p{line-height:160%;margin:5px 0}.frDialog-box-title{background:#efefef;margin-top:0;padding:12px;font-size:20px;font-weight:700;text-align:left;width:100%}.frDialog-box-button{display:inline-block;margin:0 1%;-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;padding:10px;min-width:20%;font-weight:400;text-align:center;letter-spacing:0;transition:opacity .5s;cursor:pointer}.frDialog-box-button:hover{color:#fff;opacity:.8;text-decoration:underline!important}.frDialog-box-button-container{text-align:right;padding:2.5%;background:#efefef;color:#fff}body #fr-container{position:fixed;top:10px;right:20px;-moz-border-radius:6px;border-radius:6px;background:#f0f6ff;-webkit-box-sizing:content-box;box-sizing:content-box}#fr-container *{font-size:16px;font-weight:700;font-family:"Microsoft YaHei",sans-serif;text-shadow:initial!important;-webkit-text-stroke:initial!important;text-stroke:initial!important}#fr-container{width:340px;min-height:70%;z-index:999999;padding:3px 8px;text-align:left;background-color:#fff;color:#333;font-size:16px;font-weight:900;-webkit-transition:all .1s ease-in;transition:all .1s ease-in}#fr-container strong{display:block;margin-bottom:10px}#fr-container ul li{list-style:none;margin:3px 0;-webkit-box-sizing:content-box;box-sizing:content-box;border:none;float:none;cursor:default}#fr-container fieldset{border:2px groove #67a5df;-moz-border-radius:10px;border-radius:10px;padding:4px 9px 6px;margin:2px;display:block;width:auto;height:auto;min-height:500px}#fr-container legend{line-height:20px;padding:0 8px;margin-bottom:0;font-size:16px;font-weight:700;font-family:"Microsoft YaHei",sans-serif;-webkit-box-sizing:content-box;box-sizing:content-box;width:auto!important;min-width:185px!important}#fr-container fieldset>ul{padding:0;margin:0}#fr-container .setting-title{color:#8b0000}@keyframes rotation{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(360deg)}}.setting-title .Rotation{width:24px;height:24px;top:auto;right:auto;bottom:auto;left:auto;-webkit-transform:rotate(360deg);-moz-animation:rotation 5s linear infinite;-webkit-animation:rotation 5s linear infinite;-o-animation:rotation 5s linear infinite;animation:rotation 5s linear infinite}#fontSelect{padding:2px 10px;min-height:80px}#fontFace,#fontSmooth{padding:2px 10px;height:40px;width:calc(100% - 22px);min-width:calc(100% - 22px)}#shadowColor{padding:2px 10px;min-height:45px;margin:4px;width:calc(100% - 10px)}#shadowColor *{-webkit-box-sizing:content-box;box-sizing:content-box}#fr-color-picker-show{float:left;display:block;margin:0}#shadowColor .cpicker{width:32px;height:30px;cursor:pointer;position:relative;border:2px solid #181a25;-moz-border-radius:4px;border-radius:4px;float:left;display:inline-block}#shadowColor .cpicker-2{display:inline-block;width:135px;margin:0 0 0 10px}#shadowColor .cpicker-2 #color{width:135px;height:32px;text-indent:0;font-size:18px;font-weight:400;background:#fafafa;-webkit-box-sizing:content-box;box-sizing:content-box;font-family:Impact,"Courier New",sans-serif!important;font-weight:400;color:#333;border:#67a5df 2px solid;-moz-border-radius:4px;border-radius:4px;display:inline-block;padding:0;margin:0;text-align:center}#fr-color-picker-main{width:220px;height:200px;z-index:999;position:fixed;display:none;margin:10px 0 0 20px;-webkit-box-sizing:content-box;box-sizing:content-box;background-color:#d1f2fb;padding:10px;box-shadow:0 0 10px #000;border-radius:6px}.fr-color-picker,.fr-color-picker *,.fr-color-picker ::after,.fr-color-picker ::before{border:0;margin:0;padding:0;display:block;box-sizing:border-box}.fr-color-picker{background-color:#fff;display:block;min-width:128px;min-height:128px;position:relative}.fr-color-picker>.fr-color-picker-right-bar{border:solid #000 1px;background:linear-gradient(red,#f0f,#00f,#0ff,#0f0,#ff0,red);width:16px;height:calc(100% - 26px);position:absolute;right:12px;top:12px}.fr-color-picker .fr-color-picker-right-bar-picker{position:absolute;width:100%;height:1px}.fr-color-picker .fr-color-picker-right-bar-picker::after,.fr-color-picker .fr-color-picker-right-bar-picker::before{content:"";width:10px;height:7px;position:absolute;background:0 0;border:solid transparent 5px;border-width:3.5px 5px;top:-3px}.fr-color-picker .fr-color-picker-right-bar-picker::before{border-left:solid #404040 5px;left:-6px}.fr-color-picker .fr-color-picker-right-bar-picker::after{border-right:solid #404040 5px;right:-6px}.fr-color-picker>.fr-color-picker-gradients{position:absolute;width:calc(100% - 50px);height:calc(100% - 26px);border:solid #000 1px;left:12px;top:12px}.fr-color-picker>.fr-color-picker-gradients,.fr-color-picker>.fr-color-picker-gradients *{cursor:url(color-picker.cur),crosshair;-webkit-box-sizing:content-box;box-sizing:content-box}.fr-color-picker>.fr-color-picker-gradient-black{background:linear-gradient(rgba(0,0,0,0),#000)}.fr-color-picker>.fr-color-picker-color-block{position:absolute;border:solid #000 1px;background:#fff;width:calc(100% - 104px);max-width:72px;height:18px;left:12px;bottom:8px}.fr-color-picker .fr-color-picker-circle{background-color:transparent;position:absolute}.fr-color-picker .fr-color-picker-circle::before{border-radius:50%;width:11px;height:11px;border:solid #000 1px;background-color:transparent;position:relative;left:-6px;top:-6px;display:block;content:""}.fr-color-picker .fr-color-picker-circle.fr-color-picker-circle-black::before{border-color:#000}.fr-color-picker .fr-color-picker-circle.fr-color-picker-circle-white::before{border-color:#fff}#fontShadow{padding:2px 10px;height:70px}#fontStroke{padding:2px 10px;height:70px}#submitData{padding:2px 10px;height:40px}#submitData button{background-image:initial;background-color:#67a5df;color:#fff;padding:5px;font-size:14px;font-weight:400;border:2px solid #6ba7e0;-moz-border-radius:6px;border-radius:6px;width:50px}#submitData .fr-cancel,#submitData .fr-reset{float:left;margin-right:10px}#submitData .fr-submit{float:right}#fontCSS,#fontEx{padding:2px 10px;min-height:110px}#fontEx textarea{background:#fafafa}#fontCSS textarea,#fontEx textarea{width:100%;max-width:calc(100% - 15px)!important;height:60px;line-height:140%;resize:none;border:2px solid #67a5df;-moz-border-radius:6px;border-radius:6px;-webkit-box-sizing:content-box;box-sizing:content-box;padding:5px;font-family:"Fira Code",Monaco,consolas,sans-serif;font-size:14px;font-weight:500;color:#0b5b9c;scrollbar-color:rgba(0,0,0,.6) rgba(0,0,0,.25);scrollbar-width:thin;scrollbar-arrow-color:#fff;scrollbar-face-color:#4c4c4c;scrollbar-highlight-color:#4c4c4c;scrollbar-shadow-color:#4c4c4c;scrollbar-track-color:#bfbfbf;scrollbar-3dlight-color:#4c4c4c;scrollbar-darkshadow-color:#4c4c4c;scrollbar-base-color:#4c4c4c}#fontCSS textarea::-webkit-scrollbar,#fontEx textarea::-webkit-scrollbar{width:5px;height:5px}#fontCSS textarea::-webkit-scrollbar-track,#fontEx textarea::-webkit-scrollbar-track{border-radius:5px;background-color:rgba(0,0,0,.25)}#fontCSS textarea::-webkit-scrollbar-thumb,#fontEx textarea::-webkit-scrollbar-thumb{border-radius:5px;background-color:rgba(0,0,0,.6)}.fr_tooltip{position:relative;cursor:help}.fr_tooltip .fr_tooltiptext{display:none;visibility:hidden;position:absolute;z-index:999999;-webkit-box-sizing:content-box;box-sizing:content-box;border:2px solid #b8c4ce;-moz-border-radius:6px;border-radius:6px;padding:10px;width:220px;max-width:220px;font-weight:400;color:#fff;background-color:#54a2ec;-moz-opacity:.9;opacity:.9}.fr_tooltip .fr_tooltiptext p{display:block;margin:0 0 10px;line-height:140%}.fr_tooltip .fr_tooltiptext *{font-size:14px!important}.fr_tooltip:hover .fr_tooltiptext{visibility:visible;display:block}.ps1{top:-32px;left:250px}.ps2{top:5px;left:-250px}.ps4{top:25px}#fontSelect .selector a{font-weight:400;color:#111;text-decoration:none}#fontSelect .label{display:block;float:left;margin:2px 5px 2px 0;-webkit-box-sizing:content-box;box-sizing:content-box;border:initial;-moz-border-radius:2px;border-radius:2px;padding:2px 0;height:24px;font-weight:400;line-height:20px;color:#fff;background:#67a5df}#fontSelect .label span{color:#fff;font-size:16px;font-weight:normal;padding:5px;background:#67a5df}#fontSelect .frclose{padding:5px!important;color:#fff;background:#67a5df;-webkit-box-sizing:content-box;box-sizing:content-box}#fontSelect .frclose:hover{-moz-border-radius:2px;border-radius:2px;color:tomato;background-color:#366694}#fontSelect .selectFontId{width:calc(100% - 42px)}#fontSelect .selectFontId label{display:block;margin:5px 0;color:#333;cursor:initial}#fontSelect .selectFontId input{-webkit-box-sizing:content-box;box-sizing:content-box;border:2px solid #67a5df;-moz-border-radius:6px;border-radius:6px;padding:1px 23px!important;width:100%;max-width:calc(100% - 10px);height:36px!important;font-size:16px;font-weight:700;text-indent:0;background:#fafafa;outline-color:#67a5df}#fontSelect .selectFontId dl{overflow-x:hidden;position:fixed;z-index:1000;margin:8px 0 0;-webkit-box-sizing:content-box;box-sizing:content-box;border:2px solid #67a5df;-moz-border-radius:4px;border-radius:4px;padding:4px 25px;width:100%;max-width:180px;max-height:200px;font-size:18px;white-space:nowrap;background-color:#fff}#fontSelect .selectFontId dl dd{margin:0;padding:5px;font-weight:400;font-size:21px}#fontSelect .selectFontId dl dd:hover{background-color:#67a5df;color:#fff}#selector{width:100%;max-width:100%}#selector label{display:block;cursor:initial;margin:0 0 4px}#selector #stcleaner{margin-left:5px;cursor:pointer}#selector #stcleaner:hover{color:red}#fontSelect .selector{overflow-y:auto;-webkit-box-sizing:content-box;box-sizing:content-box;border:2px solid #67a5df;-moz-border-radius:6px;border-radius:6px;padding:6px;width:100%;max-width:calc(100% - 15px);max-height:60px}.checkbox{display:none!important}.checkbox+label{padding:11px 9px;border-radius:7px;display:inline-block;position:relative;background:#f7836d;width:58px;height:10px;box-shadow:inset 0 0 20px rgba(0,0,0,.1),0 0 10px rgba(245,146,146,.4);-webkit-box-sizing:content-box;box-sizing:content-box;word-wrap:normal!important}.checkbox+label::before{position:absolute;top:0;left:0;z-index:99;-moz-border-radius:7px;border-radius:7px;width:24px;height:32px;color:#fff;background:#fff;box-shadow:0 0 1px rgba(0,0,0,.6);content:" "}.checkbox+label::after{position:absolute;top:0;left:28px;-webkit-box-sizing:content-box;box-sizing:content-box;-moz-border-radius:100px;border-radius:100px;padding:5px;font-size:1em;font-weight:700;color:#fff;content:"OFF"}.checkbox:checked+label{-webkit-box-sizing:content-box;box-sizing:content-box;background:#67a5df!important;box-shadow:inset 0 0 20px rgba(0,0,0,.1),0 0 10px rgba(146,196,245,.4)}.checkbox:checked+label::after{content:"ON";left:10px;-webkit-box-sizing:content-box;box-sizing:content-box}.checkbox:checked+label::before{content:" ";position:absolute;z-index:99;left:52px;-webkit-box-sizing:content-box;box-sizing:content-box}#f-face label,#f-face+label::after,#f-face+label::before,#smooth label,#smooth+label::after,#smooth+label::before{-webkit-transition:all .1s ease-in;transition:all .1s ease-in;-webkit-box-sizing:content-box;box-sizing:content-box}#fontShadow #shadowSize,#fontStroke #strokeSize{color:#111;width:56px;text-indent:0;margin-bottom:2px;float:right;height:32px;font-size:17px;font-weight:400;font-family:Impact,"Courier New",sans-serif!important;border:#67a5df 2px solid;-moz-border-radius:4px;border-radius:4px;margin-right:2px;text-align:center;-webkit-box-sizing:content-box;box-sizing:content-box;padding:0;background:#fafafa}.frProgress{margin:2px;width:calc(100% - 10px)}.frProgressBar{background:#f0f0f0;margin:2px;width:250px;box-sizing:border-box;display:flex;align-items:flex-end;box-shadow:0 0 1px 1px rgba(0,0,0,.1) inset}.frProgressLine{width:100%;height:100%;position:relative;border-radius:15px;background:#67a5df}.frProgressLine .btnll{position:absolute;height:100%;right:0;border-radius:50%;font-size:8px;background:#67a5df;border:6px solid #fff;top:50%;transform:translate(6px,-50%);box-sizing:content-box!important;box-shadow:0 0 0 1px rgba(0,0,0,.2);display:flex;justify-content:center;align-items:center}.frProgressLine .btnll .disable{background:#ddd;border-color:#fafafa}.frProgressLine .btnll .loading{display:none;position:absolute;content:"";top:50%;left:50%;border-radius:50%;overflow:hidden;transform:translate(-50%,-50%);background:url(loading1.gif);background-position:center center;background-size:130%;opacity:.5}@keyframes rate{0%{transform:translate(-50%,-50%) rotate(0)}100%{transform:translate(-50%,-50%) rotate(360deg)}}.vertical{top:0!important;left:50%!important;transform:translate(-50%,-6px)!important}.frProgressBar .frProgressVal{position:absolute;right:0;background:rgba(0,0,0,.4);text-align:center;width:54px;box-sizing:border-box;padding:0 4px;font-size:10px;color:#fff;height:24px;line-height:24px;border-radius:4px;top:-35px;left:50%;transform:translateX(-50%);transition:.5s linear}.frProgressBar .frProgressVal.bottom{top:auto;bottom:-35px}.frProgressBar .frProgressVal::after{position:absolute;content:"";border-width:5px 5px 0;border-style:solid;border-color:rgba(0,0,0,.4) transparent transparent;bottom:-5px;left:50%;transform:translateX(-50%)}.frProgressBar .frProgressVal.bottom::after{bottom:auto;top:-5px;border-width:0 5px 5px;border-style:solid;border-color:transparent transparent rgba(0,0,0,.4)}.frProgressBar .frProgressVal.left{top:auto;left:-40px}.frProgressBar .frProgressVal.left::after{top:50%;transform:translateY(-50%);left:auto;right:-5px;bottom:auto;border-width:5px 0 5px 5px;border-style:solid;border-color:transparent transparent transparent rgba(0,0,0,.4)}.frProgressBar .frProgressVal.right{top:auto;right:-94px;left:auto}.frProgressBar .frProgressVal.right::after{top:50%;transform:translateY(-50%);right:auto;left:-5px;bottom:auto;border-width:5px 5px 5px 0;border-style:solid;border-color:transparent rgba(0,0,0,.4) transparent transparent}.cssreadonly{background:linear-gradient(45deg,#ffe9e9 0,#ffe9e9 25%,transparent 25%,transparent 50%,#ffe9e9 50%,#ffe9e9 75%,transparent 75%,transparent);background-size:50px 50px;background-color:#fff7f7}.cssnotreadonly{background:linear-gradient(45deg,#e9ffe9 0,#e9ffe9 25%,transparent 25%,transparent 50%,#e9ffe9 50%,#e9ffe9 75%,transparent 75%,transparent);background-size:50px 50px;background-color:#f7fff7}.loadings{width:160px;height:160px;position:relative}.loadings::after,.loadings::before{content:"";position:absolute;width:0;height:0;background:#000;border-radius:50%;top:0;left:0;right:0;bottom:0;margin:auto;animation:toBig 1s linear infinite}.loadings::after{animation-delay:.5s}@keyframes toBig{0%{width:0;height:0;opacity:1}100%{width:150px;height:150px;opacity:0}}.frsite-welcome{display:none;justify-content:center;align-items:center;position:fixed;top:10px;right:20px;width:inherit;height:inherit;min-height:75%;padding:3px 8px;border-radius:4px;-webkit-box-sizing:content-box;box-sizing:content-box;z-index:1000;opacity:.65}.frsite-welcome.isactived{display:flex;background:linear-gradient(45deg,#ccc 0,#ccc 25%,transparent 25%,transparent 50%,#ccc 50%,#ccc 75%,transparent 75%,transparent);background-size:50px 50px;background-color:#eee}`; const tHTML = String(`
\u9875\u9762\u7b49\u5f85\u6570\u636e\u52a0\u8f7d\u4e2d\u2026
${defCon.scriptName}
`); const tCSS = `@charset "UTF-8";` + tshadow + fontStyle; /* Insert HTML and CSS */ function insertHTML() { if (document.body !== null && document.querySelector(`#${defCon.rndId}`) === null) { let div = document.createElement("div"); div.id = defCon.rndId; div.style = "visibility:hidden;"; div.innerHTML = tHTML; try { document.getElementsByTagName("body")[0].appendChild(div); return true; } catch (e) { error(`//-> ${e.name}`); return false; } } } function RAF() { RAFInterval( () => { if (!document.querySelector(`.${defCon.rndClass}`)) { addStyle(tCSS, `${defCon.rndClass}`, "head"); } if (!document.querySelector(`#${defCon.rndId}`)) { insertHTML(); } }, 200, true ); } try { const callback = mutations => { mutations.forEach(mutation => { if (document.querySelector(`#${defCon.rndId}`) && document.querySelector(`.${defCon.rndClass}`)) { debug(`//-> Already Insert Button & CSS.`); } else { RAF(); } }); }; const opts = { childList: true, subtree: true }; let observer = new MutationObserver(callback); observer.observe(document, opts); /* Menus Insert */ let Font_Set, Exclude_site, Feed_Back; Font_Set ? GMunregisterMenuCommand(Font_Set) : debug("No Font_Set"); Exclude_site ? GMunregisterMenuCommand(Exclude_site) : debug("No Exclude_site"); Feed_Back ? GMunregisterMenuCommand(Feed_Back) : debug("No Feed_Back"); if (window.self === window.top) { if (siteIndex === undefined) { Font_Set = GMregisterMenuCommand("\ufff0\ud83c\udf13 字体渲染设置", () => { document.querySelector(`#${defCon.rndId}`).style = "visibility: visible;"; }); Exclude_site = GMregisterMenuCommand(`\ufff1\ud83d\udeab 排除渲染 ${location.hostname}`, async () => { exSite.push(location.hostname); GMsetValue("_Exclude_site_", exSite); let frDialog = new frDialogBox({ trueButtonText: "确 定", messageText: "

" + location.hostname + " 已禁止字体渲染!

确定后页面将自动刷新!

", titleText: "禁止字体渲染", }); if (await frDialog.respond()) { frDialog = null; location.reload(); } }); } else { Exclude_site = GMregisterMenuCommand(`\ufff1\ud83c\udf40 重新渲染 ${location.hostname}`, async () => { exSite.splice(siteIndex, 1); GMsetValue("_Exclude_site_", exSite); let frDialog = new frDialogBox({ trueButtonText: "确 定", messageText: "

" + location.hostname + " 重新开启字体渲染!

确定后页面将自动刷新!

", titleText: "恢复字体渲染", }); if (await frDialog.respond()) { frDialog = null; location.reload(); } }); } Feed_Back = GMregisterMenuCommand("\ufff9\ud83e\udde1 建议反馈", () => { window.open(feedback, "feedback"); }); } /* Fonts selection */ const fontReady = await document.fonts.ready; const checkFont = new isSupportFontFamily(); const fontAvailable = new Set(); if (fontReady) { for (const font of fontCheck.values()) { if (checkFont.detect(font.en) || checkFont.detect(font.ch)) { fontAvailable.add(font); } } } const fontData = [...fontAvailable.values()]; if (document.querySelector(`#${defCon.rndId}`)) { fontSet("#fontSelect .font-list").fsearch(fontData); } /* Fonts stroke */ const strock = document.getElementById("strokeSize"); const drawStrock = new frProgress("#stroke", { val: CONST.fontStroke * 100, size: 10, precision: 1, range: 1, drag: true, direction: "horizontal", tip: { trigger: "hover", align: "right", }, getVal: function (e) { strock.value = Number((e.val / 100) * e.range) ? ((e.val / 100) * e.range).toFixed(e.precision + 2) : "OFF"; }, }); drawStrock.onLoad(true, checkdraw(strock, drawStrock, /OFF|\d+(?:\.\d{1,3})?/)); /* Fonts shadow */ const shadows = document.getElementById("shadowSize"); let drawShadow = new frProgress("#shadow", { val: (CONST.fontShadow * 100) / 8, size: 10, precision: 0, range: 8, drag: true, direction: "horizontal", tip: { trigger: "hover", align: "right", }, getVal: function (s) { shadows.value = Number((s.val / 100) * s.range) ? ((s.val / 100) * s.range).toFixed(s.precision + 2) : "OFF"; }, }); drawShadow.onLoad(false, checkdraw(shadows, drawShadow, /OFF|\d+(?:\.\d{1,2})?/)); /* Fonts shadow color selection */ const cpshow = document.querySelector("#fr-color-picker-show"); const cp = document.querySelector("#fr-color-picker-main"); const body = document.querySelector("body"); const colorshow = document.querySelector("#color"); const colorReg = /^currentcolor$|^#([A-F0-9]{6}|[a-f0-9]{6}|[A-F0-9]{3}|[a-f0-9]{3})$|^rgba\(([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2([0-4][0-9]|5[0-5]))),\s*([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2([0-4][0-9]|5[0-5]))),\s*([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2([0-4][0-9]|5[0-5]))),\s*((?!1.[1-9])[0-1]?(\.[0-9]{1,3})?)\)$|^rgb\(([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2([0-4][0-9]|5[0-5]))),\s*([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2([0-4][0-9]|5[0-5]))),\s*([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2([0-4][0-9]|5[0-5])))\)$/; const picker = new ColorPicker({ dom: cp, value: CONST.shadowColor, def: CONST.shadowColor, }); cpshow.addEventListener("click", function (e) { e.stopPropagation(); cp.style = "display:block"; }); cp.addEventListener( "click", function (e) { e.stopPropagation(); }, false ); body.addEventListener("click", function () { cp.style = "display:none"; }); /* Buttons control */ document.querySelector("#submitData .fr-reset").addEventListener("click", async () => { let frDialog = new frDialogBox({ trueButtonText: "确 定", falseButtonText: "取 消", messageText: `

『重置』将初始化您所有的操作,脚本的所有参数将被还原为初始状态,一般是在您配置错误造成页面混乱后才会进行重置。

注意,重置后记得保存数据!

请确认您是否要进行重置操作?

`, titleText: "参数重置确认", }); if (await frDialog.respond()) { fontSet().fdeleteList(fontData); strock.value = Number(defValue.fontStroke) ? defValue.fontStroke.toFixed(3) : "OFF"; drawStrock.updateVal((Number(defValue.fontStroke) * 100) / drawStrock.range); shadows.value = Number(defValue.fontShadow) ? defValue.fontShadow.toFixed(2) : "OFF"; drawShadow.updateVal((Number(defValue.fontShadow) * 1e5) / drawShadow.range / 1e3); picker.value = defValue.shadowColor; document.querySelector("#smooth").checked = defValue.fontSmooth; document.querySelector("#f-face").checked = defValue.fontFace; document.querySelector("#cssfun").value = defValue.fontCSS; document.querySelector("#exclude").value = defValue.fontEx; } frDialog = null; }); document.querySelector("#submitData .fr-submit").addEventListener("click", async () => { const fstrock = /[0-9]+(?:\.[0-9]{1,3})?/.test(strock.value) ? strock.value : strock.value === "OFF" ? "0.000" : defValue.fontStroke; const fshadow = /[0-9]+(?:\.[0-9]{1,3})?/.test(shadows.value) ? shadows.value : shadows.value === "OFF" ? "0.00" : defValue.fontShadow; const pickedcolor = colorshow.value; const fscolor = colorReg.test(pickedcolor) ? pickedcolor : defValue.shadowColor; const fontlists = fontSet().fsearchList("font-name"); const fontselect = fontlists.length > 0 ? fontlists.indexOf("Microsoft YaHei") === 0 ? defValue.fontSelect : String(QuotedStr(fontlists.toString()) + defValue.fontSelect) : CONST.fontSelect.indexOf("Microsoft YaHei") === 0 ? defValue.fontSelect : CONST.fontSelect.split(",")[0] + "," + defValue.fontSelect; const smooth = document.querySelector("#smooth").checked; const fontface = document.querySelector("#f-face").checked; const fcss = document.querySelector("#cssfun").value; const cssfun = fcss ? fcss.toString() : defValue.fontCSS; const fex = document.querySelector("#exclude").value; const fontex = fex.toString(); if ( saveDate("_fonts_set_", { fontSelect: fontselect, fontFace: fontface, fontStroke: fstrock, fontShadow: fshadow, shadowColor: fscolor, fontSmooth: smooth, fontCSS: cssfun, fontEx: fontex, }) ) { let frDialog = new frDialogBox({ trueButtonText: "感谢使用", messageText: "

您的设置参数已保存!页面将会自动刷新!

", titleText: "操作完毕", }); if (await frDialog.respond()) { document.querySelector(`#${defCon.rndId}`).style = "visibility:hidden;"; frDialog = null; location.reload(); } } else { let frDialog = new frDialogBox({ trueButtonText: "反馈问题", messageText: "

保存过程中发生了错误!

请收集浏览器信息、脚本插件信息、以及脚本版本后,与作者联系反馈!

", titleText: "错误报告", }); if (await frDialog.respond()) { document.querySelector(`#${defCon.rndId}`).style = "visibility:hidden;"; window.open(feedback, "feedback"); } frDialog = null; } }); document.querySelector("#submitData .fr-cancel").addEventListener("click", () => { document.querySelector(`#${defCon.rndId}`).style = "display:none"; }); } catch (e) { error("%c[Error]%c\n%s", "font-weight:bold;color:red", "font-weight:bold;color:darkred", e); } /* SYSTEM INFO */ if (siteIndex === undefined) { let reFontFace = "SYSTEM-UI"; fontCheck.forEach(item => { if (item.en.toLowerCase() === refont.toLowerCase()) { reFontFace = item.ch + " " + item.en; } }); console.info( `%c${defCon.scriptName}\n%c▞ 跨页面数据实时同步时长:%sms\n▞ 渲染字体:%s\n▞ 字体平滑:%s ▚ 字体重写:%s\n▞ 字体描边:%s ▚ 字体阴影:%s`, "line-height:160%;font-weight:bold;font-size:14px;color:red", "line-height:180%;font-size:12px;color:teal", refreshTime, reFontFace, CONST.fontSmooth ? "ON " : "OFF", CONST.fontFace ? "ON " : "OFF", Number(CONST.fontStroke) ? "ON " : "OFF", Number(CONST.fontShadow) ? "ON " : "OFF" ); } else { console.info( `%c${defCon.scriptName}\n%c${location.hostname.toUpperCase()} 已在排除渲染列表内,若要重新渲染,请在脚本菜单中打开重新渲染。`, "line-height:160%;font-weight:bold;font-size:14px;color:red", "line-height:180%;font-size:12px;color:darkred" ); } /* important Functions */ function addStyle(css, className, addToTarget, isReload, initType) { RAFInterval( () => { let addTo = document.querySelector(addToTarget); if (typeof addToTarget === "undefined") { addTo = document.head || document.body || document.documentElement || document; } isReload = isReload || false; initType = initType || "text/css"; if (typeof addToTarget === "undefined" || (typeof addToTarget !== "undefined" && document.querySelector(addToTarget) !== null)) { if (isReload === true) { safeRemove(`.${className}`); } else if (isReload === false && document.querySelector(`.${className}`) !== null) { return true; } const cssNode = document.createElement("style"); if (className !== null) { cssNode.className = className; } cssNode.setAttribute("type", initType); cssNode.innerHTML = css; try { addTo.appendChild(cssNode); } catch (e) { error(`//-> ${e.name}`); } return true; } return false; }, 200, true ); } function safeRemove(Css) { safeFunction(() => { const removeNodes = document.querySelectorAll(Css); for (let i = 0; i < removeNodes.length; i++) { removeNodes[i].remove(); } }); } function safeFunction(func) { try { func(); return true; } catch (e) { error(`//-> ${e.name}`); return false; } } function RAFInterval(callback, period, runNow) { const needCount = (period / 1000) * 60; let times = 0; if (runNow === true) { const shouldFinish = callback(); if (shouldFinish) { return; } } function step() { if (times < needCount) { times++; requestAnimationFrame(step); } else { const shouldFinish = callback() || false; if (!shouldFinish) { times = 0; requestAnimationFrame(step); } else { return; } } } requestAnimationFrame(step); } function QuotedStr(str) { let returnStr = ""; let strs = str.split(","); for (let s in strs) { if (strs[s] !== "Microsoft YaHei") { returnStr += `"${strs[s]}",`; } } return returnStr; } function saveDate(key, { ...Options }) { let obj = { ...Options }; try { GMsetValue(key, JSON.stringify(obj)); return true; } catch (e) { error(`//-> ${e.name}`); return false; } } })(); })();