您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
快速预览网页链接,鼠标移至链接并按下Enter键即可预览。
当前为
// ==UserScript== // @name 💡 链接速览 // @namespace https://ez118.github.io/ // @version 2.0.0 // @description 快速预览网页链接,鼠标移至链接并按下Enter键即可预览。 // @author ZZY_WISU // @match *://*/* // @connect * // @license GPLv3 // @icon data:image/webp;base64,UklGRpIAAABXRUJQVlA4WAoAAAAwAAAAIgAAIgAAVlA4THMAAAAvIoAIEA8wdtMxwfMf8HBT27ac7ISpY0UAgwXK3yVSkPBLOpBGhY4nIRrIHyxE9F9t2zaMNjs9Z3Ciy+S0SIRMFiRLzBPrG68Vl+/A+bPjaPffdtt35+i+8zsVbKJIKRoVS1brpkDONc8HYi4oREE3pXwJAA== // @run-at document-end // @grant GM_xmlhttpRequest // @grant GM_addStyle // @grant window.onurlchange // @require https://unpkg.com/[email protected]/dist/zepto.min.js // @require https://unpkg.com/@mozilla/[email protected]/Readability.js // ==/UserScript== const contentEleSelList = { "blog.csdn.net": "#article_content", "zhuanlan.zhihu.com": ".Post-Main", "jingyan.baidu.com": "#format-exp", "www.bilibili.com": "#article-content", "zhidao.baidu.com": "#qb-content", "www.cnblogs.com": "#topics", "www.sohu.com": "#mp-editor" }; /* 储存特定网站内容优化数据(文章主体的父元素) */ const mediaPrevSupport = [ { "site": "https://v.youku.com/v_show/*.html", "player": "https://player.youku.com/embed/*", "type": "video" }, { "site": "https://v.qq.com/x/page/*.html", "player": "https://v.qq.com/txp/iframe/player.html?vid=*", "type": "video" }, { "site": "https://www.bilibili.com/video/BV*/", "player": "https://www.bilibili.com/blackboard/html5mobileplayer.html?bvid=*", "type": "video" }, { "site": "https://www.bilibili.com/video/av*/", "player": "https://www.bilibili.com/blackboard/html5mobileplayer.html?aid=*", "type": "video" }, { "site": "https://www.youtube.com/watch?v=*", "player": "https://www.youtube.com/embed/*", "type": "video" }, { "site": "https://music.163.com/#/song?id=*", "player": "https://music.163.com/outchain/player?type=2&id=*&auto=0&height=66", "type": "music" }, { "site": "https://music.163.com/song?id=*", "player": "https://music.163.com/outchain/player?type=2&id=*&auto=0&height=66", "type": "music" }, { "site": "https://open.spotify.com/track/*", "player": "https://open.spotify.com/embed/track/*", "type": "music" }, { "site": "https://music.apple.com/cn/song/*", "player": "https://embed.music.apple.com/cn/album/*", "type": "music" }, { "site": "https://music.youtube.com/watch?v=*", "player": "https://www.youtube.com/embed/*", "type": "music" } ]; /* 储存支持预览播放视频/预览试听音乐的网站及其嵌入播放器链接 */ function judgeMediaSupport(url){ var jflag = null; mediaPrevSupport.forEach(function(item, index) { if (url.includes(item.site.split("*")[0])) { jflag = { "state": true, "data": item }; } }); return jflag || { "state": false, "data": null }; } function getWebContents(html, url) { /* 去掉影响转换的标签 */ html = html.replace(/<script.*?>.*?<\/script>/gis, "") .replace(/<style.*?>.*?<\/style>/gis, "") .replace(/<nav.*?>.*?<\/nav>/gis, ""); /* 提取正文 */ const parser = new DOMParser(); const doc = parser.parseFromString(html, 'text/html'); const readability = new Readability(doc); const result = readability.parse(doc); return result.content; } function openReader(url) { /* 打开阅读器 */ /* 阅读器加载提示 */ var closeBtn = $("#userscript-closeBtn"); var previewReader = $("#userscript-webPreviewReader"); previewReader.html("<p style='font-size:22px;margin-top:33%;' align='center'>正在载入...<br/><span>" + url + "</span></p>"); previewReader.show(); closeBtn.show(); /* 判断当前链接是支持预览的视频网站,并作出对应处理 */ var showMedia = judgeMediaSupport(url); if(showMedia.state){ /* 被支持的视频网站的处理 */ var origUrl = url; var frameUrl = ""; var mediaType = (showMedia.data.type == "video") ? "视频" : "音乐"; /* 将链接参数与嵌入式播放器链接拼接 */ url = url.replace(showMedia.data.site.split("*")[0], ""); url = url + "?#"; url = url.split("#")[0].split("?")[0]; url = url.replace(showMedia.data.site.split("*")[1], ""); frameUrl = showMedia.data.player.replace("*", url); previewReader.html(` <div id="FadeInContainer"> <div style="height:48px; overflow:hidden;"> <p style="margin:16px 14px;font-size:medium;user-select:none;">${mediaType}预览</p> </div> <iframe id="videoFrame" style="min-height:300px;" src="${frameUrl}"></iframe> <br> <a href="${origUrl}" target="_blank">在原网站中继续 ▶ </a><br/> <a href="${frameUrl}" target="_blank">在播放器中继续 ▶ </a> </div> `); } else { /* 普通网站的处理 */ GM_xmlhttpRequest({ method: "GET", url: url, headers: { "Content-Type": "application/x-www-form-urlencoded;charset=utf-8" }, onload: (response) => { var result = response.responseText; /* 源数据处理(csdn存在利用img的onerror属性注入xss脚本的行为) */ result = result.replace(/<img\s+[^>]*src\s*=\s*["']{2}[^>]*>/gi, ''); /* 删除src为空的标签 */ result = result.replace(/<img([^>]*)onerror\s*=\s*(['"]?[^'">]*['"]?)([^>]*)>/gi, '<img$1$3>'); /* 删除所有img标签的onerror属性 */ /* 对指定网站进行内容过滤,指定元素获取 */ let orig_result_backup = result; const domain = url.split("/")[2]; if (contentEleSelList[domain]) { try { const selector = contentEleSelList[domain]; result = $(result).find(selector).html(); } catch (e) { console.log("[WebPrvw] 无法对特定网站进行内容优化") } } if (!result) { result = orig_result_backup; } /* 调用解析网页 */ let web_content = getWebContents(result, url); /* 将所有结果添加进阅读器,并显示 */ previewReader.html(` <div id="FadeInContainer"> <div style="height:48px; overflow:hidden;"> <p style="margin:16px 14px;font-size:medium;user-select:none;">正文预览</p> </div> <div class="ContentShow"> ${web_content} </div> </div> `); }, onerror: () => console.log("[WebPrvw] 请求失败") }); } /* 执行结束 */ } function initAnalyze() { // 创建提示框 const tooltip = $('<div class="userscript-webPreviewTooltip" style="display:none;"></div>'); $('body').append(tooltip); // 获取所有有效的 a 标签 const $links = $('a:not(#userscript-webPreviewReader)'); // 过滤出有效链接(非 javascript: 和 mailto:) const $validLinks = $links.filter(function() { const href = $(this).attr('href'); return href && !href.startsWith('javascript:') && !href.startsWith('mailto:'); }); // 绑定鼠标悬停事件 $validLinks.on('mouseover', function(e) { const rect = this.getBoundingClientRect(); tooltip.css({ left: rect.left + window.scrollX, top: rect.top + window.scrollY - 30, display: 'block' }); tooltip.text('按 Enter 键预览'); }).on('mouseout', function() { tooltip.hide(); }); // 记录当前鼠标悬停的链接 let hoveredLink = null; $(document).on('mousemove', function(e) { let LinkCounter = 0; $validLinks.each(function() { const rect = this.getBoundingClientRect(); if ( e.clientX >= rect.left && e.clientX <= rect.right && e.clientY >= rect.top && e.clientY <= rect.bottom ) { hoveredLink = this; LinkCounter += 1; } }); if(LinkCounter <= 0) { hoveredLink = null; } }); // 监听 Enter 键 $(document).on('keydown', function(e) { if (e.key.toLowerCase() == 'enter' && hoveredLink) { openReader(hoveredLink.href); } }); } /* =========================== */ function init(){ /* 初始化 */ /* 插入样式 */ GM_addStyle(` :root{--bg-color:#FFFFFFAA;--text-color:#386a1f;--border-color:#285a0f;--hover-bg-color:#edf1e5;--active-bg-color:#d7e1cd;--close-btn-bg:#386a1f;--close-btn-text:#FFF;--reader-bg:#fdfdf6;--reader-text-color:#131f0d;--link-color:#386a1f;--link-hover:#487631;--pre-bg-color:#eeeee8;--pre-border-color:#dee5d8;--code-bg-color:#e2e3dd} @media (prefers-color-scheme:dark){:root{--bg-color:#00390a55;--text-color:#7edb7b;--border-color:#7edb7b;--hover-bg-color:#00390aAA;--active-bg-color:#7edb7b;--close-btn-bg:#7edb7b;--close-btn-text:#00390a;--reader-bg:#1a1c19;--reader-text-color:#e2e3dd;--link-color:#7edb7b;--link-hover:#76cd74;--pre-bg-color:#1e201d;--pre-border-color:#424940;--code-bg-color:#42494047}} .userscript-webPreviewTooltip{position:absolute;z-index:9999;user-select:none;background:var(--active-bg-color);color:var(--close-btn-text);padding:1px 8px;font-size:12px;font-weight:normal;height:fit-content;border-radius:16px;border:1px solid var(--border-color);} .userscript-closeBtn{position:fixed;top:calc(8% + 5px);right:18px;z-index:100000;background:var(--close-btn-bg);color:var(--close-btn-text);padding:8px 20px;margin:6px;border-radius:30px;font-weight:bold;border:0;border-bottom:1px solid var(--border-color);cursor:pointer} .userscript-closeBtn:hover{background:var(--link-hover)} .userscript-webPreviewReader{font-size:medium;text-align:left;position:fixed;top:8vh;right:10px;bottom:0px;z-index:99999;width:35%;height:calc(100vh - 8%);min-width:340px;background:var(--reader-bg);color:var(--reader-text-color);overflow:hidden;box-shadow:0 0 0 1px rgba(0,0,0,.1),0 2px 4px 1px rgba(0,0,0,.18);border-radius:28px 28px 0px 0px} .userscript-webPreviewReader #videoFrame{width:calc(100% - 16px);height:calc(100% - 120px);background:var(--code-bg-color);border:none;border-radius:30px;margin:8px 8px;box-shadow:0 .5px 1.5px 0 rgba(0,0,0,.19),0 0 1px 0 rgba(0,0,0,.039)} .userscript-webPreviewReader #FadeInContainer{overflow-y:scroll;overflow-x:hidden;border-radius:15px 15px 0px 0px;width:100%;height:100%} #FadeInContainer .ContentShow{padding:16px;margin:8px;background:var(--code-bg-color);border-radius:30px;overflow:hidden;color:var(--reader-text-color);box-shadow:0 .5px 1.5px 0 rgba(0,0,0,.19),0 0 1px 0 rgba(0,0,0,.039)} #FadeInContainer img{max-width:92% !important;max-height:85vh !important;position:relative !important;top:0 !important;left:0 !important;border-radius:10px} #FadeInContainer svg{max-width:40% !important;max-height:60vh !important;position:relative !important;top:0 !important;left:0 !important;border-radius:10px} #FadeInContainer a{color:var(--link-color);text-decoration:underline 1px solid var(--link-hover);margin:0px 3px} #FadeInContainer code{font-family:Consolas,Courier,Courier New,monospace} #FadeInContainer pre{color:var(--reader-text-color);background:var(--pre-bg-color);width:90%;padding:5px;margin:5px 0px;overflow-y:auto;height:fit-content;border:1px solid var(--pre-border-color);border-radius:5px} #FadeInContainer code:not(pre code){color:var(--reader-text-color);background:var(--code-bg-color);border-radius:0.25rem;padding:.125rem .375rem;line-height:1.75;word-wrap:break-word;border:1px solid var(--pre-border-color)} `); /* 页面加载时插入DOM */ /* 阅读器 */ if( $("#userscript-webPreviewReader").length == 0 ){ var $previewReader = $('<div>', { class: 'userscript-webPreviewReader', id: 'userscript-webPreviewReader' }).appendTo('body'); var $closeBtn = $('<button>', { text: '关闭', class: 'userscript-closeBtn', id: 'userscript-closeBtn', }).appendTo('body'); $closeBtn.on('click', function() { $previewReader.hide(); $closeBtn.hide(); }); } /* 隐藏阅读器 */ $("#userscript-webPreviewReader").hide(); $("#userscript-closeBtn").hide(); /* 自动匹配搜索结果并插入按钮 */ initAnalyze(); return; } (function() { 'use strict'; init(); window.addEventListener('urlchange', (info) => { if($(".userscript-webPreviewReader").length > 0 && $(".userscript-webPreviewTooltip").length > 0) { return; } setTimeout(function(){ init(); }, 1600) }); })();