您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Converts URLs into clickable links on YouTube Shorts.
当前为
// ==UserScript== // @name YouTube Shorts Linkify // @namespace http://tampermonkey.net/ // @version 1.2 // @license GPL-3.0-or-later // @description Converts URLs into clickable links on YouTube Shorts. // @match https://www.youtube.com/shorts/* // @icon https://www.google.com/s2/favicons?domain=www.youtube.com&sz=64 // @grant none // ==/UserScript== (function(){ 'use strict'; function initLinkify(){ const policy = window.trustedTypes ? trustedTypes.createPolicy('ytShortsLinkify',{createHTML: input=>input}) : null; const style = document.createElement('style'); style.textContent = "a.yt-short-linkify { color: inherit; text-decoration: underline; cursor: pointer; } .custom-tooltip { position: absolute; background: #333; color: #fff; padding: 4px 8px; border-radius: 4px; font-size: 12px; pointer-events: none; z-index: 10000; opacity: 0; white-space: nowrap; transition: opacity 0.2s ease; }"; document.head.appendChild(style); const urlRegex = /(?<=(?:\s|^|[(]))(?<![!@#$%^&*()_+\-=\[\]{};:'"\\|,\.<>\/?`~])((?:https?:\/\/)?(?:www\.)?[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*\.[a-zA-Z]{2,}(?:\/\S*)?)\b/g; function linkifyTextNode(textNode){ if(!textNode.nodeValue || !urlRegex.test(textNode.nodeValue)) return; const span = document.createElement('span'); let text = textNode.nodeValue, lastIndex = 0; urlRegex.lastIndex = 0; let match; while((match = urlRegex.exec(text)) !== null){ const url = match[0], index = match.index; span.appendChild(document.createTextNode(text.substring(lastIndex,index))); const a = document.createElement('a'); a.className = 'yt-short-linkify'; a.style.color = 'inherit'; a.href = /^https?:\/\//i.test(url) ? url : 'https://' + url; a.target = '_blank'; a.rel = 'noopener noreferrer'; a.textContent = url.replace(/^https?:\/\//i,''); a.addEventListener('mouseenter', function(){ const tooltip = document.createElement('div'); tooltip.className = 'custom-tooltip'; tooltip.textContent = a.href; document.body.appendChild(tooltip); tooltip.offsetWidth; const rect = a.getBoundingClientRect(); const tooltipRect = tooltip.getBoundingClientRect(); tooltip.style.left = (rect.left+window.pageXOffset+rect.width/2-tooltipRect.width/2)+'px'; tooltip.style.top = (rect.top+window.pageYOffset-tooltipRect.height-5)+'px'; tooltip.style.opacity = "1"; a._tooltip = tooltip; }); a.addEventListener('mouseleave', function(){ if(a._tooltip){ a._tooltip.style.opacity = "0"; setTimeout(()=>{ a._tooltip.remove(); a._tooltip = null; },200); } }); span.appendChild(a); lastIndex = index + url.length; } span.appendChild(document.createTextNode(text.substring(lastIndex))); textNode.parentNode.replaceChild(span,textNode); } function linkifyElement(element){ const treeWalker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT, { acceptNode: function(node){ return (node.parentNode && node.parentNode.nodeName==='A') ? NodeFilter.FILTER_REJECT : (node.nodeValue && urlRegex.test(node.nodeValue)) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT; } }); const nodes = []; while(treeWalker.nextNode()){ nodes.push(treeWalker.currentNode); } nodes.forEach(linkifyTextNode); } const io = new IntersectionObserver(entries=>{ entries.forEach(entry=>{ if(entry.isIntersecting){ linkifyElement(entry.target); io.unobserve(entry.target); } }); },{threshold:0.1}); document.querySelectorAll('body *').forEach(el=>io.observe(el)); const mutationObserver = new MutationObserver(mutations=>{ mutations.forEach(mutation=>{ if(mutation.type==='childList'){ mutation.addedNodes.forEach(node=>{ if(node.nodeType===Node.ELEMENT_NODE){ io.observe(node); } }); } else if(mutation.type==='characterData'){ if(mutation.target.parentNode){ io.observe(mutation.target.parentNode); } } else if(mutation.type==='attributes'){ if(mutation.target){ io.observe(mutation.target); } } }); }); mutationObserver.observe(document.body,{childList:true, subtree:true, characterData:true, attributes:true, attributeFilter:['class','style']}); function fixJSVoidAnchorsFor(anchor){ let urlText = anchor.textContent.trim(); if(!urlText)return; if(!/^https?:\/\//i.test(urlText)){ urlText = 'https://' + urlText; } const newAnchor = document.createElement('a'); newAnchor.className = 'yt-short-linkify'; newAnchor.style.color = 'inherit'; newAnchor.href = urlText; newAnchor.target = '_blank'; newAnchor.rel = 'noopener noreferrer'; newAnchor.textContent = urlText.replace(/^https?:\/\//i,''); newAnchor.addEventListener('mouseenter', function(){ const tooltip = document.createElement('div'); tooltip.className = 'custom-tooltip'; tooltip.textContent = newAnchor.href; document.body.appendChild(tooltip); tooltip.offsetWidth; const rect = newAnchor.getBoundingClientRect(); const tooltipRect = tooltip.getBoundingClientRect(); tooltip.style.left = (rect.left+window.pageXOffset+rect.width/2-tooltipRect.width/2)+'px'; tooltip.style.top = (rect.top+window.pageYOffset-tooltipRect.height-5)+'px'; tooltip.style.opacity = "1"; newAnchor._tooltip = tooltip; }); newAnchor.addEventListener('mouseleave', function(){ if(newAnchor._tooltip){ newAnchor._tooltip.style.opacity = "0"; setTimeout(()=>{ newAnchor._tooltip.remove(); newAnchor._tooltip = null; },200); } }); anchor.parentNode.replaceChild(newAnchor,anchor); } const ioJS = new IntersectionObserver(entries=>{ entries.forEach(entry=>{ if(entry.isIntersecting){ if(entry.target.matches && entry.target.matches('a[href^="javascript:void"]')){ fixJSVoidAnchorsFor(entry.target); } ioJS.unobserve(entry.target); } }); },{threshold:0.1}); const mutationObserverJS = new MutationObserver(mutations=>{ mutations.forEach(mutation=>{ mutation.addedNodes.forEach(node=>{ if(node.nodeType===Node.ELEMENT_NODE){ if(node.matches && node.matches('a[href^="javascript:void"]')){ ioJS.observe(node); } else if(node.querySelectorAll){ node.querySelectorAll('a[href^="javascript:void"]').forEach(anchor=>ioJS.observe(anchor)); } } }); }); }); mutationObserverJS.observe(document.body,{childList:true, subtree:true}); } window.addEventListener('load', ()=>{ initLinkify(); }); })();