保留纯英文段落,遮挡中文段落(含其中的英文缩写)
// ==UserScript==
// @name 中文段落遮挡助手
// @namespace http://tampermonkey.net/
// @version 0.6
// @description 保留纯英文段落,遮挡中文段落(含其中的英文缩写)
// @author 基尼胎美
// @match *://*/*
// @grant GM_addStyle
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// 按钮样式
GM_addStyle(`
.chinese-toggle-btn {
position: fixed;
top: 20px;
right: 20px;
z-index: 999999;
padding: 10px 15px;
background: #f39c12;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
transition: all 0.3s;
}
.chinese-toggle-btn:hover {
background: #d35400;
transform: translateY(-2px);
}
`);
// 创建切换按钮
const toggleBtn = document.createElement('button');
toggleBtn.className = 'chinese-toggle-btn';
toggleBtn.textContent = '遮挡中文段落';
document.body.appendChild(toggleBtn);
// 状态管理
let isHidden = false;
const chineseCharRegex = /[\u4e00-\u9fa5]/; // 用于判断是否含中文字符
const allCharsRegex = /./g; // 匹配所有字符(中文段落中全部处理)
const originalTextAttr = 'data-original-text'; // 保存原始文本的属性
// 判断一个元素是否包含中文字符(用于区分中英文段落)
function hasChineseCharacters(element) {
return chineseCharRegex.test(element.textContent);
}
// 找到文本节点所在的"段落级"父元素(优先块级元素,如p、div等)
function getParagraphElement(textNode) {
let parent = textNode.parentNode;
// 向上查找最近的块级元素或语义化段落元素
while (parent && parent !== document.body) {
const display = getComputedStyle(parent).display;
if (display.includes('block') ||
['P', 'DIV', 'SECTION', 'ARTICLE', 'LI', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6'].includes(parent.tagName)) {
return parent;
}
parent = parent.parentNode;
}
return document.body; // 找不到则默认body
}
// 处理单个文本节点
function processTextNode(node, hide) {
// 跳过不需要处理的节点(脚本、样式、输入框等)
if (node.nodeType !== Node.TEXT_NODE ||
!node.parentNode ||
['SCRIPT', 'STYLE', 'NOSCRIPT', 'IFRAME', 'INPUT', 'TEXTAREA', 'SELECT'].includes(node.parentNode.tagName)) {
return;
}
// 找到文本节点所在的段落元素
const paragraph = getParagraphElement(node);
// 判断是否为中文段落(含中文字符)
const isChineseParagraph = hasChineseCharacters(paragraph);
if (hide && isChineseParagraph) {
// 中文段落且需要遮挡:保存原始文本,移除所有内容
if (!node[originalTextAttr]) {
node[originalTextAttr] = node.nodeValue; // 保存原始文本
node.nodeValue = node.nodeValue.replace(allCharsRegex, ''); // 清空所有字符
}
} else if (!hide) {
// 恢复原始文本(无论是否中文段落,有保存就恢复)
if (node[originalTextAttr]) {
node.nodeValue = node[originalTextAttr];
delete node[originalTextAttr];
}
}
// 英文段落无论是否遮挡,都不处理(保持原样)
}
// 遍历所有文本节点处理
function processAllTextNodes(hide) {
const walker = document.createTreeWalker(
document.body,
NodeFilter.SHOW_TEXT,
null,
false
);
let currentNode;
while (currentNode = walker.nextNode()) {
processTextNode(currentNode, hide);
}
console.log(`已${hide ? '遮挡所有中文段落' : '恢复所有段落'}`);
}
// 按钮点击事件
toggleBtn.addEventListener('click', () => {
isHidden = !isHidden;
toggleBtn.textContent = isHidden ? '恢复所有段落' : '遮挡中文段落';
processAllTextNodes(isHidden);
});
// 监听动态加载内容
const observer = new MutationObserver(mutations => {
if (isHidden) {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.nodeType === Node.ELEMENT_NODE) {
const walker = document.createTreeWalker(
node,
NodeFilter.SHOW_TEXT,
null,
false
);
let currentNode;
while (currentNode = walker.nextNode()) {
processTextNode(currentNode, true);
}
} else if (node.nodeType === Node.TEXT_NODE) {
processTextNode(node, true);
}
});
});
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
characterData: true
});
console.log('中英文段落分离遮挡助手已加载,点击右上角按钮切换状态');
})();