// ==UserScript==
// @name 【古诗文网】自动展开注释、译文和赏析
// @namespace https://github.com/realSilasYang
// @version 2025-9-13
// @description 修改标签页名;自动展开古诗文网的注释、译文和赏析内容,性能优化版本
// @author 阳熙来
// @match https://www.gushiwen.cn/*
// @grant none
// @icon data:image/webp;base64,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
// @license GNU GPLv3
// ==/UserScript==
(function () {
'use strict';
// 修改网页标题
document.title = "古诗文网";
// ========== 1. 禁用原生弹窗 ==========
// 禁用alert
window.alert = function() {};
// 禁用confirm(默认返回true)
window.confirm = function() { return true; };
// 禁用prompt(返回空字符串)
window.prompt = function() { return ""; };
// ========== 2. 拦截DOM弹窗 ==========
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.nodeType !== Node.ELEMENT_NODE) return;
const element = node;
// 特征匹配:通过类名、ID或标签判断
const isPopup = element.matches([
'div[class*="popup"]', // 类名包含popup
'div[class*="modal"]', // 类名包含modal
'div[id*="dialog"]', // ID包含dialog
'.lightbox', // 灯箱弹窗
'#cookie-consent' // Cookie提示
].join(','));
if (isPopup) {
element.remove();
}
});
});
});
// ========== 3. 阻止弹窗触发事件 ==========
document.addEventListener('click', e => {
const trigger = e.target.closest([
'[onclick*="openModal"]', // 包含openModal的点击事件
'.popup-trigger', // 弹窗触发器类名
'#show-ad' // 弹窗触发器ID
].join(','));
if (trigger) {
e.stopImmediatePropagation();
e.preventDefault();
}
}, true);
// ========== 初始化 ==========
window.addEventListener('DOMContentLoaded', () => {
// 启动DOM监听
observer.observe(document, {
childList: true,
subtree: true
});
// 清理现有弹窗
document.querySelectorAll('.popup, .modal').forEach(popup => {
popup.remove();
});
});
// 配置项
const CONFIG = {
CLICK_DELAY: 50, // 每个按钮点击的延迟时间(毫秒)
LOAD_MARGIN: '100px', // IntersectionObserver 提前加载的距离(像素)
DEBUG: false // 是否开启调试模式
};
// 按钮与诗词容器的选择器
const SELECTORS = {
POEM_CONTAINER: '.sons .cont', // 用于标识诗词内容区域的选择器
BUTTONS: {
NOTE: 'img[src="https://ziyuan.guwendao.net/siteimg/zhu-pic.png"]', // 注释按钮
TRANSLATION: 'img[src="https://ziyuan.guwendao.net/siteimg/yi-pic.png"]', // 译文按钮
ANALYSIS: 'img[src="https://ziyuan.guwendao.net/siteimg/shang-pic.png"]' // 赏析按钮
}
};
/**
* 日志工具,用于输出调试信息
*/
const logger = {
log: (...args) => CONFIG.DEBUG && console.log('[古诗文展开]', ...args),
error: (...args) => CONFIG.DEBUG && console.error('[古诗文展开]', ...args)
};
/**
* 检查元素是否在视口中
* @param {Element} element - 要检查的 HTML 元素
* @returns {boolean} - 返回布尔值,表示元素是否在视口中
*/
function isInViewport(element) {
const rect = element.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
/**
* 快速点击诗词容器内的所有按钮
* @param {Element} container - 诗词容器元素
*/
function clickButtonsInContainer(container) {
try {
// 如果容器已被处理过,则直接返回
if (!container || container.hasAttribute('processed')) {
return;
}
const buttons = [];
// 遍历每种按钮的选择器,收集未点击的按钮
Object.entries(SELECTORS.BUTTONS).forEach(([type, selector]) => {
const button = container.querySelector(selector);
if (button && !button.hasAttribute('clicked') && button.style.display !== 'none') {
buttons.push({ type, element: button });
}
});
// 按顺序点击按钮,并设置点击的时间间隔
if (buttons.length) {
buttons.forEach((button, index) => {
setTimeout(() => {
try {
button.element.setAttribute('clicked', 'true'); // 标记按钮已被点击
button.element.click(); // 执行点击操作
logger.log(`Clicked ${button.type} button`);
} catch (err) {
logger.error(`Error clicking ${button.type} button:`, err);
}
}, index * CONFIG.CLICK_DELAY);
});
}
// 标记容器已处理
container.setAttribute('processed', 'true');
} catch (err) {
logger.error('Error in clickButtonsInContainer:', err);
}
}
/**
* 使用 IntersectionObserver 优化性能,按需加载诗词容器
*/
function setupIntersectionObserver() {
try {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
clickButtonsInContainer(entry.target); // 当进入视口时,处理该容器
observer.unobserve(entry.target); // 停止观察该容器
}
});
}, {
rootMargin: CONFIG.LOAD_MARGIN, // 设置提前加载的距离
threshold: 0 // 当容器完全进入视口时触发
});
// 遍历所有未处理的诗词容器,并开始观察
document.querySelectorAll(`${SELECTORS.POEM_CONTAINER}:not([processed])`).forEach(container => {
observer.observe(container);
});
} catch (err) {
logger.error('Error in setupIntersectionObserver:', err);
processVisibleContainers(); // 降级处理:直接处理当前视口中的容器
}
}
/**
* 降级处理:直接处理当前视口中的容器
*/
function processVisibleContainers() {
try {
const containers = document.querySelectorAll(`${SELECTORS.POEM_CONTAINER}:not([processed])`);
containers.forEach(container => {
if (isInViewport(container)) {
clickButtonsInContainer(container); // 处理视口中的容器
}
});
} catch (err) {
logger.error('Error in processVisibleContainers:', err);
}
}
/**
* 监听 DOM 中新增的内容,用于动态加载的场景
*/
function observeNewContent() {
try {
const observer = new MutationObserver((mutations) => {
let shouldProcess = false;
// 遍历所有变动记录,判断是否有新增的诗词容器
for (const mutation of mutations) {
if (mutation.addedNodes.length) {
const hasNewPoems = Array.from(mutation.addedNodes).some(node =>
node.nodeType === Node.ELEMENT_NODE &&
(node.matches(SELECTORS.POEM_CONTAINER) ||
node.querySelector(SELECTORS.POEM_CONTAINER))
);
if (hasNewPoems) {
shouldProcess = true;
break;
}
}
}
if (shouldProcess) {
setupIntersectionObserver(); // 如果有新增内容,则重新设置观察器
}
});
// 监听整个文档的子节点变动
observer.observe(document.body, {
childList: true,
subtree: true
});
} catch (err) {
logger.error('Error in observeNewContent:', err);
}
}
/**
* 防抖函数:限制高频调用,延迟执行
* @param {Function} func - 要防抖的函数
* @param {number} wait - 延迟时间(毫秒)
* @returns {Function}
*/
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
/**
* 初始化脚本
*/
function init() {
try {
logger.log('Initializing...');
setupIntersectionObserver(); // 设置 IntersectionObserver
observeNewContent(); // 监听新增内容
} catch (err) {
logger.error('Error in init:', err);
}
}
// 使用防抖包装初始化函数
const debouncedInit = debounce(init, 100);
// 添加页面事件监听器
window.addEventListener('load', debouncedInit);
window.addEventListener('popstate', debouncedInit);
window.addEventListener('scroll', debounce(processVisibleContainers, 100));
// 重写 history.pushState 方法,监控前端路由变化
const originalPushState = history.pushState;
history.pushState = function () {
originalPushState.apply(this, arguments);
debouncedInit();
};
// 立即初始化
debouncedInit();
// 如果开启了调试模式,导出调试接口
if (CONFIG.DEBUG) {
window._gushiwen_debug = {
processVisibleContainers,
clickButtonsInContainer,
CONFIG,
SELECTORS
};
}
})();