您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
自动替你在网页中所有的中文字和半形的英文、数字、符号之间插入空白,让文字变得美观好看。(pangu, 盤古之白)
当前为
// ==UserScript== // @name 中英文之间加空白 // @name:zh-TW 中英文之間加空白 // @version 0.6.12 // @author CY Fung // @namespace UserScript // @license MIT // @require https://cdn.jsdelivr.net/gh/cyfung1031/pangu.js@c2b48999d1c30ccdf6f609571f38d73af87eb33a/dist/web/pangu.js // @match http://*/* // @match https://*/* // @exclude /^https?://\S+\.(txt|png|jpg|jpeg|gif|xml|svg|manifest|log|ini)[^\/]*$/ // @icon https://github.com/cyfung1031/userscript-supports/raw/main/icons/blank-letter.png // @grant GM_setValue // @grant unsafeWindow // @run-at document-start // @allFrames true // @inject-into content // @description 自动替你在网页中所有的中文字和半形的英文、数字、符号之间插入空白,让文字变得美观好看。(pangu, 盤古之白) // @description:zh-TW 自動替你在網頁中所有的中文字和半形的英文、數字、符號之間插入空白,讓文字變得美觀好看。(pangu, 盤古之白) // ==/UserScript== ((__CONTEXT__) => { const { pangu } = __CONTEXT__; const win = typeof unsafeWindow !== 'undefined' ? unsafeWindow: (this instanceof Window ? this : window); // Create a unique key for the script and check if it is already running const hkey_script = 'depcyxozwnig'; if (win[hkey_script]) throw new Error('Duplicated Userscript Calling'); // avoid duplicated scripting win[hkey_script] = true; function isBrave() { const ua = window.navigator.userAgent.toLowerCase(); const isChrome = /chrome|crios/.test(ua) && ! /edge|opr\//.test(ua) const isBrave = isChrome && !window.google && (typeof IdleDetector === 'undefined' || typeof navigator.brave !== 'undefined'); return isBrave } /** @type {globalThis.PromiseConstructor} */ const Promise = (async () => { })().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve. const cleanContext = async (win) => { const waitFn = requestAnimationFrame; // shall have been binded to window try { let mx = 16; // MAX TRIAL const frameId = 'vanillajs-iframe-v1' let frame = document.getElementById(frameId); let removeIframeFn = null; if (!frame) { frame = document.createElement('iframe'); frame.id = frameId; const blobURL = typeof webkitCancelAnimationFrame === 'function' ? (frame.src = URL.createObjectURL(new Blob([], { type: 'text/html' }))) : null; // avoid Brave Crash frame.sandbox = 'allow-same-origin'; // script cannot be run inside iframe but API can be obtained from iframe let n = document.createElement('noscript'); // wrap into NOSCRPIT to avoid reflow (layouting) n.appendChild(frame); while (!document.documentElement && mx-- > 0) await new Promise(waitFn); // requestAnimationFrame here could get modified by YouTube engine const root = document.documentElement; root.appendChild(n); // throw error if root is null due to exceeding MAX TRIAL if (blobURL) Promise.resolve().then(() => URL.revokeObjectURL(blobURL)); removeIframeFn = (setTimeout) => { const removeIframeOnDocumentReady = (e) => { e && win.removeEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false); win = null; const m = n; n = null; setTimeout(() => m.remove(), 200); } if (document.readyState !== 'loading') { removeIframeOnDocumentReady(); } else { win.addEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false); } } } while (!frame.contentWindow && mx-- > 0) await new Promise(waitFn); const fc = frame.contentWindow; if (!fc) throw "window is not found."; // throw error if root is null due to exceeding MAX TRIAL const { requestAnimationFrame, setTimeout, clearTimeout } = fc; const res = { requestAnimationFrame, setTimeout, clearTimeout }; for (let k in res) res[k] = res[k].bind(win); // necessary if (removeIframeFn) Promise.resolve(res.setTimeout).then(removeIframeFn); return res; } catch (e) { console.warn(e); return null; } }; cleanContext(win).then(__CONTEXT__ => { if (!__CONTEXT__) return null; const { requestAnimationFrame } = __CONTEXT__; let rafPromise = null; const getRafPromise = () => rafPromise || (rafPromise = new Promise(resolve => { requestAnimationFrame(hRes => { rafPromise = null; resolve(hRes); }); })); class Mutex { constructor() { this.p = Promise.resolve() } lockWith(f) { this.p = this.p.then(() => new Promise(f).catch(console.warn)) } } let busy = false; const mutex = new Mutex(); function executor(f) { mutex.lockWith(unlock => { if (busy) { unlock(); return; } busy = true; Promise.resolve().then(() => { f(); }).then(() => { busy = false; }).then(unlock); }); } let mzk = null; document.addEventListener('DOMNodeInserted', function (e) { if (!busy) { if (mzk === null) mzk = e.target; else mzk = true; } }, { capture: false, passive: true }); function f77() { executor(() => { if (mzk) { let t = mzk; mzk = null; pangu.spacingPageTitle(); const node = t === true ? document.body : t; if ((node instanceof Node) && node.isConnected) { pangu.spacingNode(node); } } }); } const delayForSiteContentReady = location.hostname.endsWith('nga.cn') ? getRafPromise : () => 0; async function onReady() { window.removeEventListener("DOMContentLoaded", onReady, false); let bodyDOM = document.body; let maxLoopCount = 16; while (!bodyDOM && --maxLoopCount >= 0) { await getRafPromise(); bodyDOM = document.body; } if (!bodyDOM) return; if (await delayForSiteContentReady() !== 0) await new Promise(r => setTimeout(r, 99)); executor(() => { pangu.spacingPageTitle(); pangu.spacingPageBody(); }); let m33 = 0; const config = { childList: true, subtree: true }; const callback = async () => { if (m33++ > 1e9) m33 = 9; let tid = m33; await getRafPromise(); if (tid !== m33) return; f77(); await Promise.resolve(); let tmp = document.body; if (tmp != bodyDOM) { bodyDOM = tmp; observer.takeRecords(); observer.disconnect(); if (bodyDOM) { observer.observe(bodyDOM, config); callback(); } } }; const observer = new MutationObserver(callback); observer.observe(bodyDOM, config); callback(); } Promise.resolve().then(() => { if (document.readyState !== 'loading') { onReady(); } else { window.addEventListener("DOMContentLoaded", onReady, false); } }); }); })({ pangu });