Enhanced Features: Press F8 to show/hide buttons. Provides Eye-care Mode, Dark Mode, Chinese Conversion, TOC navigation, Font Switching and more.
// ==UserScript==
// @name 网页阅读助手
// @name:zh-CN 网页阅读助手
// @name:en Web Reading Tools
// @description 增强功能:按 F8 显示/隐藏按钮,提供护眼模式、黑夜模式、繁简转换、目录导航、字体转换等功能。
// @description:zh-CN 增强功能:按 F8 显示/隐藏按钮,提供护眼模式、黑夜模式、繁简转换、目录导航、字体转换等功能
// @description:en Enhanced Features: Press F8 to show/hide buttons. Provides Eye-care Mode, Dark Mode, Chinese Conversion, TOC navigation, Font Switching and more.
// @namespace https://www.runningcheese.com/bookmarklets
// @author RunningCheese
// @version 1.0
// @icon data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1NzYiIGhlaWdodD0iNTEyIiB2aWV3Qm94PSIwIDAgNTc2IDUxMiI+Cgk8cGF0aCBmaWxsPSIjMDA3RkU5IiBkPSJNNTQyLjIyIDMyLjA1Yy01NC44IDMuMTEtMTYzLjcyIDE0LjQzLTIzMC45NiA1NS41OWMtNC42NCAyLjg0LTcuMjcgNy44OS03LjI3IDEzLjE3djM2My44N2MwIDExLjU1IDEyLjYzIDE4Ljg1IDIzLjI4IDEzLjQ5YzY5LjE4LTM0LjgyIDE2OS4yMy00NC4zMiAyMTguNy00Ni45MmMxNi44OS0uODkgMzAuMDItMTQuNDMgMzAuMDItMzAuNjZWNjIuNzVjLjAxLTE3LjcxLTE1LjM1LTMxLjc0LTMzLjc3LTMwLjdNMjY0LjczIDg3LjY0QzE5Ny41IDQ2LjQ4IDg4LjU4IDM1LjE3IDMzLjc4IDMyLjA1QzE1LjM2IDMxLjAxIDAgNDUuMDQgMCA2Mi43NVY0MDAuNmMwIDE2LjI0IDEzLjEzIDI5Ljc4IDMwLjAyIDMwLjY2YzQ5LjQ5IDIuNiAxNDkuNTkgMTIuMTEgMjE4Ljc3IDQ2Ljk1YzEwLjYyIDUuMzUgMjMuMjEtMS45NCAyMy4yMS0xMy40NlYxMDAuNjNjMC01LjI5LTIuNjItMTAuMTQtNy4yNy0xMi45OSIgLz4KPC9zdmc+
// @match *://*/*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// @grant GM_unregisterMenuCommand
// @license MIT
// ==/UserScript==
(function() {
'use strict';
let ttPolicy;
if (window.trustedTypes && window.trustedTypes.createPolicy) {
try {
ttPolicy = window.trustedTypes.createPolicy('web-assistant-' + Math.random().toString(36).substring(2, 9), {
createHTML: (string) => string
});
} catch (e) {
ttPolicy = { createHTML: (string) => string };
}
} else {
ttPolicy = { createHTML: (string) => string };
}
// 简化的元素创建工具
const elements = {
createAs(nodeType, config, appendTo) {
const element = document.createElement(nodeType);
if (config) {
Object.entries(config).forEach(([key, value]) => {
if (key === 'innerHTML') {
element.innerHTML = ttPolicy.createHTML(value);
} else {
element[key] = value;
}
});
}
if (appendTo) appendTo.appendChild(element);
return element;
},
getAs(selector) {
return document.body.querySelector(selector);
}
};
// 添加CSS样式
const style = elements.createAs('style', {
textContent: `
.web-icon-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
border-radius: 50%;
cursor: pointer;
transition: background-color 0.3s, transform 0.2s;
background-color: #fff;
color: #555;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.12);
text-decoration: none;
}
.web-icon-btn:hover {
background-color: #d0d0d0;
transform: scale(1.1);
}
.web-icon-btn svg {
width: 20px;
height: 20px;
fill: #555;
}
`
}, document.head);
// 网页助手主体
const webViewer = {
buttonAdded: false,
buttonCheckInterval: null,
visible: false,
menuCommandIds: [],
buttonConfigs: [
{ id: 'web-bookmarklet-btn', key: 'autoRunBtn1', label: '护眼模式' },
{ id: 'web-bookmarklet-btn-2', key: 'autoRunBtn2', label: '黑夜模式' },
{ id: 'web-bookmarklet-btn-3', key: 'autoRunBtn3', label: '繁简转换' },
{ id: 'web-bookmarklet-btn-4', key: 'autoRunBtn4', label: '目录导航' },
{ id: 'web-bookmarklet-btn-5', key: 'autoRunBtn5', label: '网页字体' },
],
runButtonAction(id) {
switch (id) {
case 'web-bookmarklet-btn':
this.runEyesCareMode();
break;
case 'web-bookmarklet-btn-2':
this.runDarkMode();
break;
case 'web-bookmarklet-btn-3':
this.runCharConvert();
break;
case 'web-bookmarklet-btn-4':
this.runTOC();
break;
case 'web-bookmarklet-btn-5':
this.runFontChange();
break;
}
},
// 运行“护眼模式”功能
runEyesCareMode() {
var night = function(w) {
(function(d) {
var css = 'html{filter: brightness(0.9);}';
var s = d.getElementsByTagName('style');
for (var i = 0, si; si = s[i]; i++) {
if (si.innerHTML == css) {
si.parentNode.removeChild(si);
return;
}
}
var heads = d.getElementsByTagName('head');
if (heads.length) {
var node = d.createElement('style');
node.type = 'text/css';
node.appendChild(d.createTextNode(css));
heads[0].appendChild(node);
}
})(w.document);
for (var i = 0, f; f = w.frames[i]; i++) {
try { arguments.callee(f); } catch (e) {}
}
};
night(window);
},
// 运行“黑夜模式”功能
runDarkMode() {
var d = document.documentElement;
if (d.hasAttribute('data-dark-mode')) {
var e = document.querySelectorAll('[data-original-style]');
e.forEach(function(n) {
n.style.cssText = n.getAttribute('data-original-style') || '';
n.removeAttribute('data-original-style');
});
d.removeAttribute('data-dark-mode');
} else {
d.setAttribute('data-dark-mode', 'true');
function R(c) {
var r = c[0], g = c[1], b = c[2], M = Math.max(Math.max(r, g), b), m = Math.min(Math.min(r, g), b), s = M + m, f = M - m, l = s / 2, h = 0, S = 0;
if (M != m) {
S = l <= .5 ? f / s : f / (2 - s);
var Rd = r / 6 / f, Gd = g / 6 / f, Bd = b / 6 / f;
h = r == M ? Gd - Bd : g == M ? 1 / 3 + Bd - Rd : 2 / 3 + Rd - Gd;
if (h < 0) h += 1;
if (h > 1) h -= 1;
}
return [h, S, l];
}
function C(n, p) {
var r = getComputedStyle(n, null).getPropertyValue(p);
if (/rgb\((\d+),\s(\d+),\s(\d+)\)/.exec(r)) return [parseInt(RegExp.$1, 10) / 255, parseInt(RegExp.$2, 10) / 255, parseInt(RegExp.$3, 10) / 255];
return r;
}
function H(h) {
if (h[2] < .1) return 'hsl(220,20%,15%)';
return 'hsl(' + Math.round(h[0] * 360) + ',' + Math.round(h[1] * 100) + '%,' + Math.round(h[2] * 100) + '%)';
}
function I(n) {
return n.tagName === 'BUTTON' || n.tagName === 'INPUT' || n.classList.contains('icon') || n.classList.contains('btn') || n.getAttribute('role') === 'button' || /\b(icon|btn|button)\b/i.test(n.className);
}
var P = ['color', 'background-color', 'border-left-color', 'border-right-color', 'border-top-color', 'border-bottom-color'],
P2 = ['color', 'backgroundColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor', 'borderBottomColor'];
if (typeof C(d, 'background-color') == 'string') d.style.backgroundColor = 'white';
(function L(n) {
if (n.nodeType == Node.ELEMENT_NODE) {
if (!n.hasAttribute('data-original-style')) n.setAttribute('data-original-style', n.style.cssText);
for (var i = 0, x; x = n.childNodes[i]; ++i) L(x);
if (!I(n))
for (i = 0; x = P[i]; ++i) {
var c = C(n, x);
if (typeof c != 'string') {
var h = R(c);
h[2] = 1 - h[2];
n.style[P2[i]] = H(h);
}
}
}
})(d);
}
},
// 运行“目录导航”功能
runTOC() {
var toc = function() {
var selectors = ["article", "section", "main", "content", "#article", ".article", "#main", ".main", "#content", ".content", "#post", ".post", "body"];
var headingSelector = "h1, h2, h3, h4, h5, h6";
var shadow;
var buildList = function() {
var headings = [];
var index = 0;
for (var s = 0; s < selectors.length; s++) {
if (document.querySelectorAll(selectors[s]).length) {
document.querySelectorAll(selectors[s]).forEach(function(container) {
container.querySelectorAll(headingSelector).forEach(function(el) {
if (el.innerText.trim()) {
headings.push(el);
if (el.id) {
el.dataset.headerMark = el.id;
} else {
el.dataset.headerMark = "toc_index_" + index++;
el.id = el.dataset.headerMark;
}
}
});
});
break;
}
}
var html = "";
if (headings.length) {
var prevLevel = +headings[0].tagName.replace(/H/g, "");
var indent = 0;
headings.forEach(function(el) {
var level = +el.tagName.replace(/H/g, "");
indent = indent + level - prevLevel;
indent = indent < 0 ? 0 : indent;
prevLevel = level;
var span = document.createElement("span");
span.innerText = el.innerText;
html += '<li class="toc_menu_item toc_header_level_' + indent + '"><a href="#' + el.dataset.headerMark + '">' + span.innerHTML + '</a></li>';
});
} else {
html += '<li class="toc_menu_item">[空]</li>';
}
return html;
};
(function() {
var host = document.createElement("div");
shadow = host.attachShadow({ mode: "open" });
host.id = "toc_menu_root";
shadow.innerHTML = '<style>#toc_menu_root{position:fixed;top:50%;right:20%;transform:translateY(-50%);width:220px;max-height:80vh;z-index:2147483647;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;background:#fff;border-radius:8px;box-shadow:0 4px 12px rgba(0,0,0,0.25);}#toc_menu_root>#toc_header{padding:8px 10px;cursor:move;font-size:14px;border-radius:8px 8px 0 0;border-bottom:1px solid #eee;color:#333;display:flex;justify-content:space-between;align-items:center;}#toc_header_text{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1;}#close_button{cursor:pointer;margin-left:8px;color:#999;width:20px;height:20px;display:flex;align-items:center;justify-content:center;border-radius:50%;transition:all 0.2s ease;flex-shrink:0;}#close_button:hover{background:#dadada;color:#333;}#toc_menu_root>ul#toc_menu_list{box-sizing:border-box!important;margin:0;padding:4px;max-height:calc(80vh - 32px);overflow:auto;background:#fff;border-radius:0 0 8px 8px;}#toc_menu_root>ul#toc_menu_list>li{list-style:none!important;margin:0;padding:0 10px;height:32px;font-size:14px;transition:all 0.2s ease;border-radius:6px;cursor:pointer;}#toc_menu_root>ul#toc_menu_list>li.toc_menu_item>a{display:flex;align-items:center;color:#333;text-decoration:none;font-size:14px;height:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}#toc_menu_root>ul#toc_menu_list>li:hover{background:#dadada;}#toc_menu_root>ul#toc_menu_list>li.toc_menu_item>a:hover{color:#333;}#toc_menu_root>ul#toc_menu_list>li.toc_header_level_1{padding-left:1.2em;}#toc_menu_root>ul#toc_menu_list>li.toc_header_level_2{padding-left:2em;}#toc_menu_root>ul#toc_menu_list>li.toc_header_level_3{padding-left:2.8em;}</style><div id="toc_menu_root"><div id="toc_header"><span id="toc_header_text">▼ 目录导航</span><span id="close_button">✕</span></div><ul id="toc_menu_list"></ul></div>';
document.querySelector("html").appendChild(host);
var menuRoot = shadow.querySelector("#toc_menu_root");
var menuList = shadow.querySelector("#toc_menu_list");
var header = shadow.querySelector("#toc_header");
menuList.innerHTML = buildList();
var isDragging = false;
var offsetX, offsetY;
header.addEventListener("mousedown", function(e) {
if (e.target.id === "close_button") return;
isDragging = true;
offsetX = e.clientX - e.currentTarget.getBoundingClientRect().left;
offsetY = e.clientY - e.currentTarget.getBoundingClientRect().top;
});
document.addEventListener("mousemove", function(e) {
if (!isDragging) return;
var x = e.clientX - offsetX;
var y = e.clientY - offsetY;
e.preventDefault();
menuRoot.style.left = x + "px";
menuRoot.style.top = y + "px";
menuRoot.style.right = "auto";
menuRoot.style.transform = "none";
});
document.addEventListener("mouseup", function() {
isDragging = false;
});
shadow.querySelector("#close_button").addEventListener("click", function() {
host.remove();
});
document.addEventListener("keydown", function(evt) {
if (evt.key === "Escape") {
host.remove();
}
});
})();
};
toc();
},
// 显示提示消息
showToast(message) {
const toast = elements.createAs("div", {
style: `
position: fixed;
top: 12%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #ff2442;
color: white;
padding: 15px 20px;
border-radius: 8px;
font-size: 14px;
font-weight: bold;
z-index: 1000000000;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
`,
textContent: message
}, document.body);
setTimeout(() => {
if (document.body.contains(toast)) {
document.body.removeChild(toast);
}
}, 3000);
},
// 添加按钮到页面浮动容器
addButtons() {
let buttonContainer = elements.getAs('#web-helper-buttons');
if (!buttonContainer) {
buttonContainer = elements.createAs('div', {
id: 'web-helper-buttons',
style: `
position: fixed;
top: 50%;
right: 30px;
transform: translateY(-50%);
display: flex;
flex-direction: column;
align-items: center;
gap: 15px;
z-index: 999999;
`
}, document.body);
}
buttonContainer.style.display = this.visible ? 'flex' : 'none';
// 创建小书签按钮
if (!elements.getAs('#web-bookmarklet-btn')) {
elements.createAs('a', {
id: 'web-bookmarklet-btn',
href: 'javascript:void(0);',
className: 'web-icon-btn',
title: '护眼模式',
innerHTML: '<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><path fill="#555" fill-rule="evenodd" d="M277.333 405.333v85.333h-42.667v-85.333zm99.346-58.824l60.34 60.34l-30.17 30.17l-60.34-60.34zm-241.359 0l30.17 30.17l-60.34 60.34l-30.17-30.17zM256 139.353c64.422 0 116.647 52.224 116.647 116.647c0 64.422-52.225 116.647-116.647 116.647A116.427 116.427 0 0 1 139.352 256c0-64.423 52.225-116.647 116.648-116.647m0 42.666c-40.859 0-73.981 33.123-73.981 74.062a73.76 73.76 0 0 0 21.603 52.296c13.867 13.867 32.685 21.64 52.378 21.603zm234.666 52.647v42.667h-85.333v-42.667zm-384 0v42.667H21.333v-42.667zM105.15 74.98l60.34 60.34l-30.17 30.17l-60.34-60.34zm301.7 0l30.169 30.17l-60.34 60.34l-30.17-30.17zM277.332 21.333v85.333h-42.667V21.333z" /></svg>',
onclick: () => {
webViewer.runEyesCareMode();
}
}, buttonContainer);
}
if (!elements.getAs('#web-bookmarklet-btn-2')) {
elements.createAs('a', {
id: 'web-bookmarklet-btn-2',
href: 'javascript:void(0);',
className: 'web-icon-btn',
title: '黑夜模式',
innerHTML: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#555" d="M11 21q-3.35 0-5.675-2.325T3 13t2.325-5.675T11 5q.125 0 .25.012t.25.013q-.725.8-1.112 1.825T10 9q0 2.5 1.75 4.25T16 15q.775 0 1.513-.187t1.387-.563q-.45 2.95-2.7 4.85T11 21m2.8-10L17 2h2l3.2 9h-1.9l-.7-2h-3.2l-.7 2zm3.05-3.35h2.3L18 4z" /></svg>',
onclick: () => {
webViewer.runDarkMode();
}
}, buttonContainer);
}
if (!elements.getAs('#web-bookmarklet-btn-3')) {
elements.createAs('a', {
id: 'web-bookmarklet-btn-3',
href: 'javascript:void(0);',
className: 'web-icon-btn',
title: '繁简转换',
innerHTML: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-translate" viewBox="0 0 16 16"><path d="M4.545 6.714 4.11 8H3l1.862-5h1.284L8 8H6.833l-.435-1.286H4.545zm1.634-.736L5.5 3.956h-.049l-.679 2.022H6.18z"/><path d="M0 2a2 2 0 0 1 2-2h7a2 2 0 0 1 2 2v3h3a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v-3H2a2 2 0 0 1-2-2V2zm2-1a1 1 0 0 0-1 1v7a1 1 0 0 0 1 1h7a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H2zm7.138 9.995c.193.301.402.583.63.846-.748.575-1.673 1.001-2.768 1.292.178.217.451.635.555.867 1.125-.359 2.08-.844 2.886-1.494.777.665 1.739 1.165 2.93 1.472.133-.254.414-.673.629-.89-1.125-.253-2.057-.694-2.82-1.284.681-.747 1.222-1.651 1.621-2.757H14V8h-3v1.047h.765c-.318.844-.74 1.546-1.272 2.13a6.066 6.066 0 0 1-.415-.492 1.988 1.988 0 0 1-.94.31z"/></svg>',
onclick: () => {
webViewer.runCharConvert();
}
}, buttonContainer);
}
if (!elements.getAs('#web-bookmarklet-btn-4')) {
elements.createAs('a', {
id: 'web-bookmarklet-btn-4',
href: 'javascript:void(0);',
className: 'web-icon-btn',
title: '目录导航',
innerHTML: '<svg xmlns="http://www.w3.org/2000/svg" width="640" height="640" viewBox="0 0 640 640"><path fill="#555" d="M64 136c0-13.2 10.7-24 24-24h48c13.3 0 24 10.7 24 24v104h24c13.3 0 24 10.7 24 24s-10.7 24-24 24H88c-13.3 0-24-10.7-24-24s10.7-24 24-24h24v-80H88c-13.3 0-24-10.7-24-24m30.4 229.2c11.4-8.6 25.3-13.2 39.6-13.2h4.9c33.7 0 61.1 27.4 61.1 61.1c0 19.6-9.4 37.9-25.2 49.4l-24 17.5H184c13.3 0 24 10.7 24 24s-10.7 24-24 24H93.3C77.1 528 64 514.9 64 498.7c0-9.4 4.5-18.2 12.1-23.7l70.5-51.3c3.4-2.5 5.4-6.4 5.4-10.6c0-7.2-5.9-13.1-13.1-13.1H134c-3.9 0-7.7 1.3-10.8 3.6l-20.8 15.6c-10.6 8-25.6 5.8-33.6-4.8s-5.8-25.6 4.8-33.6zM288 128h256c17.7 0 32 14.3 32 32s-14.3 32-32 32H288c-17.7 0-32-14.3-32-32s14.3-32 32-32m0 160h256c17.7 0 32 14.3 32 32s-14.3 32-32 32H288c-17.7 0-32-14.3-32-32s14.3-32 32-32m0 160h256c17.7 0 32 14.3 32 32s-14.3 32-32 32H288c-17.7 0-32-14.3-32-32s14.3-32 32-32" /></svg>',
onclick: () => {
webViewer.runTOC();
}
}, buttonContainer);
}
if (!elements.getAs('#web-bookmarklet-btn-5')) {
elements.createAs('a', {
id: 'web-bookmarklet-btn-5',
href: 'javascript:void(0);',
className: 'web-icon-btn',
title: '网页字体',
innerHTML: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#555" d="M7 2a1 1 0 0 1 .94.658l2.882 7.926l-1.11 2.798L9.209 12H4.792l-.852 2.342a1 1 0 0 1-1.88-.684l4.001-11A1 1 0 0 1 7.001 2m-1.48 8h2.962L7 5.926zm9.848-3.472a1 1 0 0 0-1.86 0L8.151 20.022h-.15a1 1 0 1 0 0 2H11a1 1 0 0 0 0-2h-.697L11.106 18h6.653l.8 2.023H18a1 1 0 0 0 0 2h3.009a1 1 0 0 0 0-2h-.298zM16.967 16H11.9l2.537-6.39z" /></svg>',
onclick: () => {
webViewer.runFontChange();
}
}, buttonContainer);
}
this.buttonAdded = true;
},
runCharConvert() {
javascript:(function(){var s = document.getElementById('tongwenlet_script');if(s != null){document.body.removeChild(s);s = document.createElement('script');s.language = 'javascript';s.type = 'text/javascript';if(window.lastTongwenType === 'cn'){s.src = 'https://gcore.jsdelivr.net/gh/runningcheese/Awesome-Bookmarklets/libs/bookmarklet_tw.js';window.lastTongwenType = 'tw';}else{s.src = 'https://gcore.jsdelivr.net/gh/runningcheese/Awesome-Bookmarklets/libs/bookmarklet_cn.js';window.lastTongwenType = 'cn';}}else{s = document.createElement('script');s.language = 'javascript';s.type = 'text/javascript';s.src = 'https://gcore.jsdelivr.net/gh/runningcheese/Awesome-Bookmarklets/libs/bookmarklet_cn.js';window.lastTongwenType = 'cn';}s.id = 'tongwenlet_script';document.body.appendChild(s);})();
},
runFontChange() {
javascript:(function(){const e=document.createElement('div');e.style.cssText='position:fixed;top:20%;right:20%;transform:translate(-50%,0);background:#fff;border:none;border-radius:8px;padding:4px;width:200px;box-shadow:0 4px 12px rgba(0,0,0,0.25);z-index:999999;cursor:move;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif';let t=0,n=0,o=0,i=0,s=!1;e.onmousedown=l=>{s=!0;t=l.clientX;n=l.clientY;o=e.offsetLeft;i=e.offsetTop;e.style.transform='translateX(-50%)'};document.onmousemove=l=>{if(!s)return;const d=l.clientX-t,r=l.clientY-n;e.style.left=o+d+'px';e.style.top=i+r+'px'};document.onmouseup=()=>s=!1;let lastEscTime=0;document.addEventListener('keydown',function(evt){if(evt.key==='Escape'){const now=Date.now();if(now-lastEscTime<=300){e.remove()}lastEscTime=now}});const l=[{title:'▼ 修改网页字体 ×',isTitle:true},{title:'1、衬线字体',code:` document.body.style.fontFamily = "Georgia,Times,Times New Roman,serif";const allElements = document.querySelectorAll('*');allElements.forEach(el =>{if(el !== e && !e.contains(el)){el.style.fontFamily = "Georgia,Times,Times New Roman,serif";}});`},{title:'2、无衬线字体',code:` document.body.style.fontFamily = "Arial,Helvetica,sans-serif";const allElements = document.querySelectorAll('*');allElements.forEach(el =>{if(el !== e && !e.contains(el)){el.style.fontFamily = "Arial,Helvetica,sans-serif";}});`},{title:'3、思源宋体',code:` document.body.style.fontFamily = "Source Han Serif SC,Source Han Serif CN,Source Han Serif,serif";const allElements = document.querySelectorAll('*');allElements.forEach(el =>{if(el !== e && !e.contains(el)){el.style.fontFamily = "Source Han Serif SC,Source Han Serif CN,Source Han Serif,serif";}});`},{title:'4、思源黑体',code:` document.body.style.fontFamily = "Source Han Sans SC,Source Han Sans CN,Source Han Sans,sans-serif";const allElements = document.querySelectorAll('*');allElements.forEach(el =>{if(el !== e && !e.contains(el)){el.style.fontFamily = "Source Han Sans SC,Source Han Sans CN,Source Han Sans,sans-serif";}});`},{title:'5、Seravek 字体',code:` document.body.style.fontFamily = "Seravek,-apple-system,BlinkMacSystemFont,sans-serif";const allElements = document.querySelectorAll('*');allElements.forEach(el =>{if(el !== e && !e.contains(el)){el.style.fontFamily = "Seravek,-apple-system,BlinkMacSystemFont,sans-serif";}});`},{title:'6、苹方字体',code:` document.body.style.fontFamily = "PingFang SC,PingFang TC,PingFang HK,sans-serif";const allElements = document.querySelectorAll('*');allElements.forEach(el =>{if(el !== e && !e.contains(el)){el.style.fontFamily = "PingFang SC,PingFang TC,PingFang HK,sans-serif";}});`},{title:'7、等宽字体',code:` document.body.style.fontFamily = "Menlo,Monaco,Consolas,'Courier New',monospace";const allElements = document.querySelectorAll('*');allElements.forEach(el =>{if(el !== e && !e.contains(el)){el.style.fontFamily = "Menlo,Monaco,Consolas,'Courier New',monospace";}});`},{title:'8、楷体',code:` document.body.style.fontFamily = "KaiTi,楷体,STKaiti,华文楷体,serif";const allElements = document.querySelectorAll('*');allElements.forEach(el =>{if(el !== e && !e.contains(el)){el.style.fontFamily = "KaiTi,楷体,STKaiti,华文楷体,serif";}});`},{title:'9、宋体',code:` document.body.style.fontFamily = "SimSun,宋体,STSong,华文宋体,serif";const allElements = document.querySelectorAll('*');allElements.forEach(el =>{if(el !== e && !e.contains(el)){el.style.fontFamily = "SimSun,宋体,STSong,华文宋体,serif";}});`},{title:'10、恢复默认',code:` document.body.style.fontFamily = "";const allElements = document.querySelectorAll('*');allElements.forEach(el =>{if(el !== e && !e.contains(el)){el.style.fontFamily = "";}});`}];l.forEach((t,idx)=>{const n=document.createElement('div');n.style.cssText=t.isTitle?'display:flex;justify-content:space-between;align-items:center;padding:4px 10px;font-size:14px;color:#333;border-bottom:1px solid #eee;margin-bottom:2px':'cursor:pointer;padding:0px 10px;height:32px;transition:all 0.2s ease;border-radius:6px;font-size:14px;color:#333;display:flex;align-items:center';if(t.isTitle){const o=document.createElement('span');o.textContent='✕';o.style.cssText='cursor:pointer;color:#999;width:20px;height:20px;display:flex;align-items:center;justify-content:center;border-radius:50%;transition:all 0.2s ease';o.onmouseover=()=>o.style.backgroundColor='#dadada';o.onmouseout=()=>o.style.backgroundColor='';o.onclick=()=>e.remove();n.textContent=t.title.replace(' ×','');n.appendChild(o)}else{n.textContent=t.title;n.onmouseover=()=>n.style.backgroundColor='#dadada';n.onmouseout=()=>n.style.backgroundColor='';if(t.url||t.code){n.onclick=o=>{o.preventDefault();if(t.url){window.open(t.url+encodeURIComponent(window.getSelection().toString()||''))}else if(t.code){eval(t.code);}}}}e.appendChild(n)});document.body.appendChild(e)})();
this.showToast('已切换阅读字体');
},
// 启动按钮检查
startButtonCheck() {
if (this.buttonCheckInterval) {
clearInterval(this.buttonCheckInterval);
}
this.buttonCheckInterval = setInterval(() => {
this.addButtons();
}, 1500);
},
// 切换按钮显示/隐藏
toggleVisibility() {
this.visible = !this.visible;
const container = elements.getAs('#web-helper-buttons');
if (container) {
container.style.display = this.visible ? 'flex' : 'none';
} else if (this.visible) {
this.addButtons();
}
},
// 切换是否自动运行
toggleAutoRun(key, label) {
const newState = !GM_getValue(key, false);
GM_setValue(key, newState);
this.showToast((newState ? '已开启' : '已关闭') + '自动运行' + label);
this.registerMenu();
},
// 注册脚本菜单命令
registerMenu() {
this.menuCommandIds.forEach(id => {
try { GM_unregisterMenuCommand(id); } catch (e) {}
});
this.menuCommandIds = [];
this.buttonConfigs.forEach(config => {
const enabled = GM_getValue(config.key, false);
const id = GM_registerMenuCommand(
config.label + ' ' + (enabled ? '✅' : '❌'),
() => { this.toggleAutoRun(config.key, config.label); }
);
this.menuCommandIds.push(id);
});
},
// 初始化
init() {
this.addButtons();
this.startButtonCheck();
this.buttonConfigs.forEach(config => {
if (GM_getValue(config.key, false)) {
this.runButtonAction(config.id);
}
});
this.registerMenu();
console.log('网页助手初始化成功');
// F8 切换按钮显示/隐藏
document.addEventListener('keydown', (e) => {
if (e.key === 'F8') {
e.preventDefault();
this.toggleVisibility();
}
});
// 监听页面变化
let lastUrl = location.href;
new MutationObserver(() => {
if (lastUrl !== location.href) {
lastUrl = location.href;
// 延迟处理,等待页面元素加载
setTimeout(() => {
this.addButtons();
}, 800);
}
}).observe(document.body, {
childList: true,
subtree: true
});
}
};
webViewer.init();
})();