全局滚动条美化 & 字体修改

全局字体美化,滚动条美化,支持自定义字体、自定义规则

目前为 2023-11-04 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name 全局滚动条美化 & 字体修改
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0.30
  5. // @author subframe7536
  6. // @description 全局字体美化,滚动条美化,支持自定义字体、自定义规则
  7. // @license MIT
  8. // @icon https://foruda.gitee.com/avatar/1677064980766394537/5705841_subframe7536_1652618638.png!avatar200
  9. // @supportURL https://github.com/subframe7536/userscript
  10. // @match *://*/*
  11. // @grant GM_deleteValue
  12. // @grant GM_getValue
  13. // @grant GM_registerMenuCommand
  14. // @grant GM_setValue
  15. // @run-at document-start
  16. // ==/UserScript==
  17.  
  18. (function () {
  19. 'use strict';
  20.  
  21. /**
  22. * @preserve
  23. * 基础配置
  24. * - SANS: 普通字体,默认 'sans-serif'
  25. * - MONO: 等宽字体,默认 'monospace'
  26. * - MONO_SETTING: 等宽字体 font-feature-settings 设置,默认 ['calt']
  27. * - SCROLLBAR: 是否修改滚动条,默认 true
  28. * - SCROLLBAR_WIDTH: 滚动条宽度,可以是任何 css 的宽度,默认 'max(0.85vw, 10px)'
  29. */
  30. const BASE_CONFIG = {
  31. SANS: "",
  32. MONO: "",
  33. MONO_SETTING: ["calt"],
  34. SCROLLBAR: void 0,
  35. SCROLLBAR_WIDTH: ""
  36. };
  37. /**
  38. * @preserve
  39. * 需要修改字体的域名的黑名单
  40. *
  41. * @example ['font']
  42. */
  43. const BLOCKLIST = [];
  44. /**
  45. * @preserve
  46. * 字体修改的规则
  47. * type: [pattern, callback]
  48. *
  49. * @example
  50. * ```
  51. * [
  52. * ['w3cschools.com', () => {
  53. * addCodeFont('.w3-code *')
  54. * }],
  55. * [['yuque.com'], () => {
  56. * //...
  57. * }],
  58. * ]
  59. * ```
  60. */
  61. const SITEMAP = [];
  62. var _GM_deleteValue = /* @__PURE__ */ (() => typeof GM_deleteValue != "undefined" ? GM_deleteValue : void 0)();
  63. var _GM_getValue = /* @__PURE__ */ (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)();
  64. var _GM_registerMenuCommand = /* @__PURE__ */ (() => typeof GM_registerMenuCommand != "undefined" ? GM_registerMenuCommand : void 0)();
  65. var _GM_setValue = /* @__PURE__ */ (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)();
  66. const moduleName = "script-mono";
  67. function getConfig(key, defaultValue) {
  68. let ret = _GM_getValue(key, void 0) ?? defaultValue;
  69. if (BASE_CONFIG[key]) {
  70. ret = BASE_CONFIG[key];
  71. _GM_setValue(key, ret);
  72. }
  73. return ret;
  74. }
  75. BASE_CONFIG.SANS = getConfig("SANS", "maple ui,sans-serif");
  76. BASE_CONFIG.MONO = getConfig("MONO", "maple mono sc nf,maple mono,monospace");
  77. BASE_CONFIG.MONO_SETTING = getConfig("MONO_SETTING", ["calt"]);
  78. BASE_CONFIG.SCROLLBAR = getConfig("SCROLLBAR", true);
  79. BASE_CONFIG.SCROLLBAR_WIDTH = getConfig("SCROLLBAR_WIDTH", "max(0.85vw,10px)");
  80. const monacoCharWidthCheckElement = 'body>div[style="position: absolute; top: -50000px; width: 50000px;"] *';
  81. const sansExcludeSelector = [
  82. monacoCharWidthCheckElement,
  83. "v-text",
  84. "[data-virgo-text=true]",
  85. // math
  86. "mjx-container *",
  87. // icons
  88. "[class*=material-symbols]",
  89. "[class*=codicon]",
  90. "[class*=icon]",
  91. "[class*=icon] *",
  92. "[class*=Icon]",
  93. "[class*=Icon] *",
  94. '[class*="terminal"] *',
  95. '[class^="fui-"]',
  96. '[class*="fui-"]',
  97. '[class*="fa"]',
  98. "[class*=heroButton]",
  99. ".pi, .pi *",
  100. // elements
  101. "em, i, svg *, kbd, kdb *, samp, samp *, var, var *, tt"
  102. ];
  103. const monospaceSelectors = [
  104. monacoCharWidthCheckElement,
  105. ".monaco-editor *",
  106. "html body pre",
  107. "pre *",
  108. "pre.CodeMirror-line *",
  109. "code",
  110. "code *",
  111. ".code",
  112. ".code *",
  113. ".mono",
  114. ".text-mono",
  115. ".text-mono *",
  116. "pre .token",
  117. "pre code *",
  118. "pre section *",
  119. "body pre code.hljs",
  120. ".prettyprint *",
  121. ".hljs",
  122. ".hljs *",
  123. "[class*=hljs]:not(.hljs-engine) *",
  124. 'code[class*="language-"] *',
  125. 'pre[class*="language-"] *',
  126. "body .prism .token",
  127. ".cm-editor *",
  128. ".font-mono",
  129. "[font-mono]",
  130. ".font-mono>*",
  131. "[font-mono]>*",
  132. ".monaco-mouse-cursor-text",
  133. "#vscode-editor *",
  134. ".enlighter *",
  135. ".syntaxhighlighter :is(code, .line)",
  136. "table.highlight *",
  137. "pre[data-lang] code",
  138. ".Typist",
  139. ".Typist *",
  140. ".ace_editor *",
  141. '[data-rnw-int-class*="codeblock"] *',
  142. ".codecolorer-container *",
  143. ".codeblock *",
  144. ".swagger-ui :is(.code, code)",
  145. ".dp-highlighter *",
  146. ".highlighted-code *",
  147. ".prism-code *",
  148. ".CodeMirror-code *",
  149. ".code-editor :is(.token-line, .token)",
  150. '[class*="monospace"]',
  151. '[class*="monospace"] *',
  152. '[class*="terminal"] *',
  153. ".whitespace-pre",
  154. "[class^=console]>*",
  155. "samp",
  156. "code-container *",
  157. "span:has(>.r-crgep1[data-highlighting]) *",
  158. "kbd",
  159. "tt",
  160. "[class^=code-block]",
  161. ".gitbook-root div[data-rnwi-handle=codeblock-toolbar] *"
  162. ];
  163. const blocklist = [
  164. "font",
  165. "ziti",
  166. "izihun",
  167. "foundertype",
  168. "hanyi",
  169. "adobe",
  170. "localhost",
  171. "mono",
  172. "latex",
  173. "typeof",
  174. "jetbrains",
  175. "unicode",
  176. "math",
  177. "twitter",
  178. "openvim"
  179. ];
  180. const isDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
  181. var _LEVEL = ["debug", "info", "warn", "error"];
  182. function createLogger(mode, onLog, onTimer) {
  183. let filter = (level, s) => (
  184. // #hack: e is unknown when level = 'error', else e is scope
  185. (msg, e, scope) => (mode === _LEVEL[3] && level > 2 || mode === _LEVEL[1] && level > 0 || mode === _LEVEL[0]) && onLog(msg, _LEVEL[level], ...level > 2 ? [s || scope, e] : [s || e])
  186. );
  187. let withScope = (scope) => ({
  188. debug: filter(0, scope),
  189. info: filter(1, scope),
  190. warn: filter(2, scope),
  191. error: filter(3, scope),
  192. timer: onTimer,
  193. setLogMode: (m) => mode = m
  194. });
  195. return {
  196. ...withScope(),
  197. withScope
  198. };
  199. }
  200. var scopeColors = ["#3f6894", "#feecd8"];
  201. var levelColors = {
  202. debug: "#66a2cc",
  203. info: "#7cbd75",
  204. warn: "#dbaf57",
  205. error: "#e08585"
  206. };
  207. var r = ".3rem";
  208. function renderBadge(bg, fg, radius = r) {
  209. return `font-size:.8rem;padding:.1rem .3rem;border-radius:${radius};background-color:${bg};color:${fg}`;
  210. }
  211. function onBrowserLog(msg, level, scope, e) {
  212. let _msg = `%c${level.toUpperCase()}`;
  213. const args = [];
  214. if (scope) {
  215. _msg += `%c${scope}`;
  216. args.push(
  217. renderBadge(levelColors[level], "#fff", `${r} 0 0 ${r}`),
  218. renderBadge(scopeColors[0], scopeColors[1], `0 ${r} ${r} 0`)
  219. );
  220. } else {
  221. args.push(renderBadge(levelColors[level], "#fff"));
  222. }
  223. _msg += "%c ";
  224. args.push("");
  225. if (typeof msg !== "object") {
  226. _msg += msg;
  227. } else {
  228. _msg += "%o";
  229. args.push(msg);
  230. }
  231. console.log(_msg, ...args);
  232. e && console.error(e);
  233. }
  234. function onBrowserTimer(label) {
  235. const start = Date.now();
  236. return () => console.log(
  237. `%c${label}%c ${(Date.now() - start).toFixed(2)}ms`,
  238. renderBadge(scopeColors[0], scopeColors[1]),
  239. ""
  240. );
  241. }
  242. function createBrowserLogger(logMode = "info") {
  243. return createLogger(logMode, onBrowserLog, onBrowserTimer);
  244. }
  245. let styleArray = [];
  246. const logger = createBrowserLogger(getDebug() ? "debug" : "disable").withScope("scripts-mono");
  247. function loadStyles(style) {
  248. if (styleArray.length || style) {
  249. document.documentElement.insertAdjacentHTML(
  250. "beforeend",
  251. `<style class="${moduleName}">${style || [...new Set(styleArray)].join("")}</style>`
  252. );
  253. if (!style) {
  254. styleArray = [];
  255. }
  256. }
  257. }
  258. function addRootCSS(property, value) {
  259. styleArray.push(`:root{${property}:${value}}`);
  260. }
  261. function addCSS(selectors, styles) {
  262. selectors = Array.isArray(selectors) ? selectors : [selectors];
  263. styles = Array.isArray(styles) ? styles : [styles];
  264. styleArray.push(`${selectors.join(",")}{${styles.join(";")}}`);
  265. }
  266. function addCodeFont(...selectors) {
  267. addCSS(
  268. selectors,
  269. [
  270. `font-family: ${BASE_CONFIG.MONO}, ${BASE_CONFIG.SANS} !important`,
  271. `font-feature-settings: ${BASE_CONFIG.MONO_SETTING.map((s) => `"${s}"`).join(",")} !important`,
  272. "letter-spacing: 0px !important"
  273. ]
  274. );
  275. }
  276. function addSansFontDefault() {
  277. addCSS(
  278. `body :not(${sansExcludeSelector.join(",")})`,
  279. [
  280. `font-family: ${BASE_CONFIG.SANS}`,
  281. "letter-spacing: 0px!important"
  282. ]
  283. );
  284. }
  285. function addSansFont(...selectors) {
  286. addCSS(
  287. selectors,
  288. [
  289. `font-family:${BASE_CONFIG.SANS}!important`,
  290. "letter-spacing:0px!important"
  291. ]
  292. );
  293. }
  294. function isInBlockList(current2, blocklist2) {
  295. return current2 && blocklist2.some((pattern) => current2.includes(pattern));
  296. }
  297. function getDebug() {
  298. return _GM_getValue("debug", false);
  299. }
  300. function toggleDebug() {
  301. const debug = !getDebug();
  302. logger.setLogMode(debug ? "debug" : "disable");
  303. _GM_setValue("debug", debug);
  304. }
  305. const __vite_glob_0_0 = ["www.51cto.com", () => {
  306. addCodeFont(
  307. "#result [class*=language-]",
  308. ".prettyprint *",
  309. "code[class*=language-] *",
  310. "div[class*=language-] *",
  311. "pre[class*=language-] *"
  312. );
  313. }];
  314. const __vite_glob_0_1 = ["app.affine.pro", () => {
  315. addCSS("body", "--affine-font-code-family:monospace,sans-serif!important");
  316. addCSS("body", "--affine-font-family:sans-serif!important");
  317. }];
  318. const __vite_glob_0_2 = ["www.baidu.com", () => {
  319. addSansFont("input");
  320. }];
  321. const __vite_glob_0_3 = [["www.bilibili.com", "t.bilibili.com", "space.bilibili.com"], () => {
  322. addSansFont(
  323. ".bili-comment.browser-pc *",
  324. ".video-page-card-small .card-box .info .title"
  325. );
  326. }];
  327. const __vite_glob_0_4 = ["www.cnblogs.com", () => {
  328. addCodeFont(".cnblogs-markdown code", " .cnblogs_code", " .cnblogs_code *");
  329. }];
  330. const __vite_glob_0_5 = ["blog.csdn.net", () => {
  331. addSansFont(
  332. "#csdn-toolbar *",
  333. " #csdn_tool_otherPlace *",
  334. "body #content_views > pre > code > div.hljs-button"
  335. );
  336. addCodeFont("body .markdown_views pre code.prism .token.comment");
  337. }];
  338. const __vite_glob_0_6 = ["discord.com", () => {
  339. addCodeFont("[class^=codeBlockSyntax]", "[class^=codeLine] *", "[class*=inlineCode]>span");
  340. addRootCSS("--font-code", `${BASE_CONFIG.MONO},${BASE_CONFIG.SANS}!important`);
  341. addRootCSS("--font-display", `${BASE_CONFIG.SANS}!important`);
  342. addRootCSS("--font-primary", `${BASE_CONFIG.SANS}!important`);
  343. addRootCSS("--font-headline", `${BASE_CONFIG.SANS}!important`);
  344. }];
  345. const __vite_glob_0_7 = ["gitee.com", () => {
  346. addCodeFont(".commit-id", "input", "textarea");
  347. addSansFont("button", ".ui:not(.iconfont)");
  348. addCSS("#git-header-nav #navbar-search-form", "border-radius:4px");
  349. }];
  350. const __vite_glob_0_8 = ["github.com", () => {
  351. addCodeFont(
  352. 'table:not(.d-block):not([aria-labelledby="folders-and-files"]) *',
  353. "textarea",
  354. "#read-only-cursor-text-area",
  355. ".react-code-lines *",
  356. ".react-line-number",
  357. ".blob-code-inner span",
  358. ".commit .sha-block",
  359. ".commit .sha",
  360. ".branch-name",
  361. ".blame-container *"
  362. );
  363. addCSS(".code-navigation-cursor", "display:none");
  364. addCSS("#read-only-cursor-text-area", "caret-color:var(--color-fg-default)");
  365. }];
  366. const __vite_glob_0_9 = ["gf.qytechs.cn", () => {
  367. addCSS("body", "color:#000");
  368. }];
  369. const __vite_glob_0_10 = ["www.jb51.net", () => {
  370. addCodeFont("body div .syntaxhighlighter *");
  371. }];
  372. const __vite_glob_0_11 = ["www.jianshu.com", () => {
  373. addSansFont("a.title");
  374. }];
  375. const __vite_glob_0_12 = ["juejin.cn", () => {
  376. addCSS(".markdown-body pre>code.copyable.hljs[lang]:before", "right:90px");
  377. addCSS("copy-code-btn", "top:8px");
  378. }];
  379. const __vite_glob_0_13 = ["developer.mozilla.org", () => {
  380. addCSS(":root", `--font-body:${BASE_CONFIG.SANS}!important;`);
  381. }];
  382. const __vite_glob_0_14 = ["ray.so", () => {
  383. addCodeFont('textarea[class^="Editor_textarea"]');
  384. }];
  385. const __vite_glob_0_15 = ["regex101.com", () => {
  386. addRootCSS("--code-font", "monospace,sans-serif!important");
  387. addRootCSS("--app-font", "sans-serif!important");
  388. }];
  389. const __vite_glob_0_16 = ["stackoverflow.com", () => {
  390. addCSS("body", ["--ff-sans:", "--ff-mono:monospace,"].map((s) => `${s}sans-serif!important`));
  391. }];
  392. const __vite_glob_0_17 = [["twitter.com", "x.com"], () => {
  393. addCSS("div:is([lang=ja],[lang=en],[lang=ko])", `font-family:${BASE_CONFIG.SANS}!important;`);
  394. }];
  395. const __vite_glob_0_18 = ["www.w3cschool.com.cn", () => {
  396. addSansFont("strong,h1,h2,h3,h4,h5,h6");
  397. }];
  398. const __vite_glob_0_19 = ["www.yuque.com", () => {
  399. addCodeFont(".ne-code");
  400. addSansFont("[class^=catalogTreeItem-module_title]");
  401. }];
  402. function loadSites(current2, customs) {
  403. var _a;
  404. const map = /* @__PURE__ */ new Map();
  405. const configs = /* @__PURE__ */ Object.assign({ "./51cto.ts": __vite_glob_0_0, "./affine.ts": __vite_glob_0_1, "./baidu.ts": __vite_glob_0_2, "./bilibili.ts": __vite_glob_0_3, "./cnblog.ts": __vite_glob_0_4, "./csdn.ts": __vite_glob_0_5, "./discord.ts": __vite_glob_0_6, "./gitee.ts": __vite_glob_0_7, "./github.ts": __vite_glob_0_8, "./greasyfork.ts": __vite_glob_0_9, "./jb51.ts": __vite_glob_0_10, "./jianshu.ts": __vite_glob_0_11, "./juejin.ts": __vite_glob_0_12, "./mdn.ts": __vite_glob_0_13, "./raycast-website.ts": __vite_glob_0_14, "./regex101.ts": __vite_glob_0_15, "./stackoverflow.ts": __vite_glob_0_16, "./twitter.ts": __vite_glob_0_17, "./w3cschools.ts": __vite_glob_0_18, "./yuque.ts": __vite_glob_0_19 });
  406. Object.values(configs).forEach(([site, callback]) => {
  407. let patterns = site;
  408. if (!Array.isArray(site)) {
  409. patterns = [site];
  410. }
  411. patterns.forEach((pattern) => map.set(pattern, callback));
  412. });
  413. customs.forEach(([pattern, callback]) => {
  414. map.set(pattern, callback);
  415. });
  416. if (map.has(current2)) {
  417. logger.info(`[${current2}] match current!`);
  418. (_a = map.get(current2)) == null ? void 0 : _a();
  419. }
  420. loadStyles();
  421. }
  422. const base = "*{-webkit-font-smoothing:antialiased!important;font-optical-sizing:auto;font-kerning:auto;text-rendering:optimizeLegibility;-webkit-text-stroke:.05px!important}::selection{background-color:#aad0ffd9;color:#111}::highlight{background-color:#f6be49}\n";
  423. const scrollbar = ":root{--scrollbar-width: max(.85vw, 10px)}@media (prefers-color-scheme: light){:root{--scrollbar-color-rgb: 0, 0, 0}}@media (prefers-color-scheme: dark){:root{--scrollbar-color-rgb: 255, 255, 255}}*::-webkit-scrollbar{width:var(--scrollbar-width)!important;height:var(--scrollbar-width)!important}*::-webkit-scrollbar-track{background-color:transparent!important;border-radius:var(--scrollbar-width)!important;box-shadow:none!important}*::-webkit-scrollbar-thumb{box-shadow:inset 0 0 0 var(--scrollbar-width)!important;border-radius:var(--scrollbar-width)!important;border:calc(var(--scrollbar-width) * 2 / 9) solid transparent!important;background-clip:content-box;background-color:transparent!important;color:rgba(var(--scrollbar-color-rgb),30%)!important}*::-webkit-scrollbar-thumb:hover{color:rgba(var(--scrollbar-color-rgb),45%)!important}*::-webkit-scrollbar-thumb:active{color:rgba(var(--scrollbar-color-rgb),60%)!important}\n";
  424. const current = window.location.hostname;
  425. logger.info(current);
  426. function init() {
  427. if (BASE_CONFIG.SCROLLBAR) {
  428. loadStyles(scrollbar);
  429. document.documentElement.style.setProperty("--scrollbar-width", BASE_CONFIG.SCROLLBAR_WIDTH);
  430. }
  431. loadSites(current, SITEMAP);
  432. if (isInBlockList(current, [...blocklist, ...BLOCKLIST])) {
  433. return;
  434. }
  435. if (isInBlockList(current, _GM_getValue("blocklist", []))) {
  436. logger.warn("排除当前域名");
  437. _GM_registerMenuCommand("恢复当前域名并刷新", () => {
  438. const stored = _GM_getValue("blocklist", []);
  439. const index = stored.indexOf(current);
  440. if (index !== -1) {
  441. stored.splice(index, 1);
  442. }
  443. _GM_setValue("blocklist", stored);
  444. location.reload();
  445. });
  446. return;
  447. }
  448. addSansFontDefault();
  449. addCodeFont(...monospaceSelectors);
  450. addRootCSS("--d-border-radius", "0.25rem");
  451. addRootCSS("--font-mono", "monospace");
  452. addRootCSS("--font-monospace", "monospace");
  453. addRootCSS("--code-font", "monospace");
  454. loadStyles();
  455. _GM_registerMenuCommand("排除当前域名并刷新", () => {
  456. const stored = _GM_getValue("blocklist", []);
  457. stored.push(current);
  458. _GM_setValue("blocklist", stored);
  459. location.reload();
  460. });
  461. loadStyles(base);
  462. }
  463. _GM_registerMenuCommand(`${BASE_CONFIG.SCROLLBAR ? "关闭" : "开启"}滚动条美化并刷新`, () => {
  464. _GM_setValue("SCROLLBAR", !BASE_CONFIG.SCROLLBAR);
  465. logger.info(!BASE_CONFIG.SCROLLBAR);
  466. location.reload();
  467. });
  468. _GM_registerMenuCommand("重置设置", () => {
  469. _GM_deleteValue("SANS");
  470. _GM_deleteValue("MONO");
  471. _GM_deleteValue("MONO_SETTING");
  472. _GM_deleteValue("SCROLLBAR");
  473. _GM_deleteValue("SCROLLBAR_WIDTH");
  474. });
  475. _GM_registerMenuCommand(`${getDebug() ? "关闭" : "开启"} Debug 模式并刷新`, () => {
  476. toggleDebug();
  477. location.reload();
  478. });
  479. init();
  480. isDark && addRootCSS("color-scheme", "dark");
  481. window.onload = () => {
  482. setTimeout(() => {
  483. const list = document.documentElement.classList;
  484. if (list.contains("theme-dark") || list.contains("dark")) {
  485. addRootCSS("color-scheme", "dark");
  486. }
  487. loadStyles();
  488. if (!document.querySelector(`.${moduleName}`)) {
  489. logger.warn("未找到 userscript-mono 标签,重新加载");
  490. init();
  491. }
  492. }, 100);
  493. };
  494.  
  495. })();

QingJ © 2025

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