// ==UserScript==
// @name LD 丑化脚本
// @namespace http://tampermonkey.net/
// @version 1.26
// @description 替换文字、图片、链接,并隐藏指定元素
// @author chengdu
// @match https://linux.do/*
// @grant none
// @run-at document-idle
// @license GPL-3.0-or-later
// ==/UserScript==
(function () {
'use strict';
/* ---------- 文字替换规则 ---------- */
const textReplacements = [
{ oldText: /Where possible begins\./g, newText: '遇事不决,可问春风。' },
{ oldText: /Where possible begins/g, newText: '遇事不决,可问春风。' },
{ oldText: /常见问题解答/g, newText: '社区准则' },
{ oldText: /我的帖子/g, newText: '帖子' },
{ oldText: /我的消息/g, newText: '消息' },
{ oldText: /近期活动/g, newText: '分发' },
{ oldText: /Leaderboard/g, newText: '排行榜' },
{ oldText: /外部链接/g, newText: '外链' },
{ oldText: /类别/g, newText: '版块' },
{ oldText: /搞七捻三/g, newText: '朋友圈' },
{ oldText: /运营反馈/g, newText: '运营' },
{ oldText: /深海幽域/g, newText: '深海' },
{ oldText: /直接消息/g, newText: '聊天' }
];
/* ---------- 图片替换规则 ---------- */
const imageReplacements = [
{
oldSrc: 'https://linux.do/user_avatar/linux.do/neo/288/12_2.png',
newSrc: 'https://s2.loli.net/2025/07/07/x6TdsjPHtv3Op8U.jpg'
},
{
oldSrc: 'https://linux.do/user_avatar/linux.do/neo/96/12_2.png',
newSrc: 'https://s2.loli.net/2025/07/07/x6TdsjPHtv3Op8U.jpg'
},
{
oldSrc: 'https://linux.do/user_avatar/linux.do/neo/48/12_2.png',
newSrc: 'https://s2.loli.net/2025/07/07/x6TdsjPHtv3Op8U.jpg'
}
];
/* ---------- 链接修改规则 ---------- */
const linkReplacements = [
{
selector: '[data-link-name="upcoming-events"]',
newHref: 'https://cdk.linux.do',
newTitle: '分发',
newTarget: '_blank'
}
];
/* ---------- 要隐藏的元素(已移除AI机器人按钮) ---------- */
const hideSelectors = [
'.menu-content.wrap',
// ↓↓↓ 版块分类行拦截
'tr[data-category-id="49"]',
'tr[data-category-id="30"]',
'tr[data-category-id="63"]',
'tr[data-category-id="64"]',
'tr[data-category-id="65"]'
];
/* ---------- 文本节点替换 ---------- */
function replaceInTextNodes(root) {
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false);
let node;
while ((node = walker.nextNode())) {
let text = node.nodeValue;
textReplacements.forEach(({ oldText, newText }) => {
text = text.replace(oldText, newText);
});
node.nodeValue = text;
}
}
/* ---------- 图片 src 替换 ---------- */
function replaceImageSources(root) {
root.querySelectorAll('img').forEach(img => {
imageReplacements.forEach(({ oldSrc, newSrc }) => {
if (img.src === oldSrc) {
img.src = newSrc;
console.log(`🖼️ 图片已替换: ${oldSrc} → ${newSrc}`);
}
});
});
}
/* ---------- 链接属性修改 ---------- */
function replaceLinks(root) {
linkReplacements.forEach(({ selector, newHref, newTitle, newTarget }) => {
root.querySelectorAll(selector).forEach(element => {
const oldHref = element.getAttribute('href');
const oldTitle = element.getAttribute('title');
element.setAttribute('href', newHref);
element.setAttribute('title', newTitle);
if (newTarget) {
element.setAttribute('target', newTarget);
element.setAttribute('rel', 'noopener noreferrer');
}
console.log(`🔗 链接已修改: ${oldHref} → ${newHref}`);
console.log(`📝 标题已修改: ${oldTitle} → ${newTitle}`);
});
});
}
/* ---------- 隐藏指定元素(CSS 注入) ---------- */
function hideElements() {
const style = document.createElement('style');
style.textContent = hideSelectors
.map(s => `${s} { display: none !important; }`)
.join('\n');
document.head.appendChild(style);
console.log('🚫 指定元素已隐藏:', hideSelectors.join(', '));
}
/* ---------- 综合替换 ---------- */
function performReplacements(root) {
replaceInTextNodes(root);
replaceImageSources(root);
replaceLinks(root);
}
/* ---------- 初始执行 ---------- */
function init() {
performReplacements(document.body);
hideElements();
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
/* ---------- 监听动态内容 ---------- */
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.nodeType === Node.ELEMENT_NODE) {
performReplacements(node);
}
});
});
});
observer.observe(document.body, { childList: true, subtree: true });
})();