您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Luogu Feed hidden link display tool with keyword highlight.
// ==UserScript== // @name Luogu Feed: Show hidden link // @namespace https://imken.link/lfshl // @version 0.1.8.1 // @description Luogu Feed hidden link display tool with keyword highlight. // @author Imken Luo // @match https://www.luogu.com.cn/ // @match https://www.luogu.com.cn/?* // @icon https://www.luogu.com.cn/favicon.ico // @license GPL-3.0-or-later // ==/UserScript== //// *请注意,更新之前请备份您自定义的关键词列表!!!* //// //// *请注意,更新之前请备份您自定义的关键词列表!!!* //// //// *请注意,更新之前请备份您自定义的关键词列表!!!* //// const keywordMap = { 'BV1GJ411x7h7': 'RickRoll', 'BV1va411w7aM': 'RickRoll', 'BV1BP4y1G78b': 'RickRoll', 'BV1mu411U7GU': 'RickRoll', 'BV1Px411w7FH': 'RickRoll', 'BV1Ti4y1f7td': 'RickRoll', 'av156766': 'RickRoll', 'id=5221167': 'RickRoll', // Netease Music 'milime.top': 'RickRoll', 'rrHrxMt': 'RickRoll', '192d9a98d782d9c74c96f09db9378d93.mp4': 'RickRoll', }; // 将字符串转换为合法的类名 function toValidClassName(str) { str = str.replace(/[^a-zA-Z0-9_-]/g, '-'); if (/^\d/.test(str)) { str = '-' + str; } return str; } // 生成需要的 CSS function genCSS(keywordMap) { let res = '' res += `.ass-warn::after { background-color: yellow; font-family: monospace; color: red; margin-left: 0.25em; }`; res += `.ass-unmatch::after { content: '[Warn: 链接不匹配]'; }`; for (let i in keywordMap) { res += `.${toValidClassName(`ass-${i}`)}::after { content: '[Warn: ${keywordMap[i]}]'; }`; } return res; } // 将 CSS 注入到网页 function addCSS(css) { let style = document.createElement('style'); style.innerHTML = css; document.head.appendChild(style); } const linkTextRegex = /^(https?:\/\/)?([a-z0-9-]+\.){1,}[a-z]{2,}(\/.*)?$/i; // 去除字符串末尾的斜杠 function removeTrailingSlash(str) { return str.replace(/\/$/, ''); } // 判断字符串是否看起来像一个链接 function isLinkLike(str) { return linkTextRegex.test(str); } (function() { // 选择需要观察变动的节点 const targetNode = document.getElementById('feed'); if (targetNode) { addCSS(genCSS(keywordMap)); // 观察器的配置(需要观察什么变动) const config = { attributes: false, childList: true, subtree: false }; // 当观察到变动时执行的回调函数 const callback = function(mutationsList, observer) { for (let mutation of mutationsList) { if (mutation.type === 'childList') { // 选择所有犇犇下的文字 const urlElements = document.querySelectorAll('.feed-comment p'); // 遍历每一个元素 for (let i in urlElements) { if (urlElements[i].innerHTML && !urlElements[i].getAttribute('vist')) { urlElements[i].setAttribute('vist', '1'); // 正则表达式替换 urlElements[i].innerHTML = urlElements[i].innerHTML.replace(/<a\s+[^>]*href="([^"]*)"[^>]*>(\s*| )<\/a>/g, function(match, href) { // 替换为内容为 href 的 <span> 标签 return '<span style="background-color: black; color: white;">' + decodeURIComponent(href) + '</span>'; }); } } // 获取所有图片元素 const imgElements = document.querySelectorAll('.feed-comment img'); // 遍历每个图片元素 for (let i in imgElements) { if (imgElements[i].getAttribute && !imgElements[i].getAttribute('vist')) { let altText = imgElements[i].getAttribute('alt'); let src = imgElements[i].getAttribute('src'); let title = imgElements[i].getAttribute('title'); let newAltText = altText + ' | ' + src + (title ? ' | ' + title : ''); src = decodeURIComponent(src); imgElements[i].setAttribute('alt', newAltText); imgElements[i].setAttribute('style', 'background: gray; color: white;'); imgElements[i].setAttribute('vist', '1'); } } const linkElements = document.querySelectorAll('.feed-comment p a'); for (let i in linkElements) { if (!linkElements[i].href) break; if (linkElements[i].getAttribute('vist')) continue; let link = linkElements[i].getAttribute('href'); let text = linkElements[i].innerText; let isKeywordMatched = 0; for (let keyword in keywordMap) { if (link.includes(keyword)) { linkElements[i].classList.add('ass-warn'); linkElements[i].classList.add(toValidClassName(`ass-${keyword}`)); linkElements[i].style['background-color'] = 'yellow'; isKeywordMatched = 1; break; } } // 去除链接文字和 href 末尾的斜杠 var cleanedText = removeTrailingSlash(text); var cleanedHref = removeTrailingSlash(link); // 检查链接文字和 href(去除末尾斜杠后)是否不同,并且链接文字看起来是一个链接 if (!isKeywordMatched && cleanedText !== cleanedHref && isLinkLike(cleanedText)) { linkElements[i].classList.add("ass-warn"); linkElements[i].classList.add("ass-unmatch"); linkElements[i].style['background-color'] = 'yellow'; } linkElements[i].setAttribute('vist', '1'); } } } }; // 创建一个观察器实例并传入回调函数 const observer = new MutationObserver(callback); // 以上述配置开始观察目标节点 observer.observe(targetNode, config); } })(); /// It's end. That's it.