您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Automatically accelerates hyperlinks on web pages to improve loading speed. Integrates the latest instant.page v5.2.0 features with multi-language support (default: English) and removes store link redirection functionality.
// ==UserScript== // @name Web Page Accelerator // @namespace instant.page // @version v1.0.5.2.0 // @author OB_BUFF // @description Automatically accelerates hyperlinks on web pages to improve loading speed. Integrates the latest instant.page v5.2.0 features with multi-language support (default: English) and removes store link redirection functionality. // @license GPL-v3 // @require https://registry.npmmirror.com/sweetalert2/10.16.6/files/dist/sweetalert2.min.js // @resource swalStyle https://registry.npmmirror.com/sweetalert2/10.16.6/files/dist/sweetalert2.min.css // @match *://*/* // @noframes // @run-at document-idle // @grant GM_openInTab // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @grant GM_getResourceText // @icon data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjggMTI4Ij48cGF0aCBkPSJNMCA3OWMwLTM1LjQgMjguNS02NCA2My45LTY0LjFzNjQuMSAyOC42IDY0LjEgNjRjMCA5LjQtMi4xIDE4LjQtNS43IDI2LjUtMSAyLjMtMi4zIDQuNi0zLjYgNi43LS40LjYtMSAxLTEuNyAxSDExYy0uNyAwLTEuMy0uNC0xLjctMS0xLjMtMi4yLTIuNS00LjQtMy42LTYuN0MyLjEgOTcuNCAwIDg4LjQgMCA3OXptMjQuNC0zOS43Yy01LjIgNS4xLTkuMiAxMS4xLTEyIDE3LjgtMyA2LjktNC41IDE0LjItNC41IDIxLjhhNTUuODYgNTUuODYgMCAwIDAgNC40IDIxLjhjLjcgMS42IDEuNCAzLjIgMi4yIDQuN2g5OC44Yy44LTEuNSAxLjYtMy4xIDIuMi00LjdhNTUuODYgNTUuODYgMCAwIDAgNC40LTIxLjggNTUuODYgNTUuODYgMCAwIDAtNC40LTIxLjhjLTIuOC02LjctNi45LTEyLjctMTItMTcuOC01LjEtNS4yLTExLjEtOS4yLTE3LjgtMTJhNTUuODYgNTUuODYgMCAwIDAtMjEuOC00LjQgNTUuODYgNTUuODYgMCAwIDAtMjEuOCA0LjRjLTYuNiAyLjgtMTIuNiA2LjgtMTcuNyAxMnoiIGZpbGw9IiM0NDQiLz48cGF0aCBkPSJNMTIuNCA1Ny4xYzIuOC02LjcgNi45LTEyLjcgMTItMTcuOCA1LjEtNS4yIDExLjEtOS4yIDE3LjgtMTJBNTUuODYgNTUuODYgMCAwIDEgNjQgMjIuOWE1NS44NiA1NS44NiAwIDAgMSAyMS44IDQuNGM2LjcgMi44IDEyLjcgNi45IDE3LjggMTIgNS4yIDUuMSA5LjIgMTEuMSAxMiAxNy44YTU1Ljg2IDU1Ljg2IDAgMCAxIDQuNCAyMS44IDU1Ljg2IDU1Ljg2IDAgMCAxLTQuNCAyMS44Yy0uNyAxLjYtMS40IDMuMi0yLjIgNC43SDE0LjZjLS44LTEuNS0xLjYtMy4xLTIuMi00LjdBNTUuODYgNTUuODYgMCAwIDEgOCA3OC45Yy0uMS03LjYgMS40LTE0LjkgNC40LTIxLjh6IiBmaWxsPSIjNjQ5OTUwIi8+PHBhdGggZD0iTTc3LjUgNjAuOUM2OCA4MS4yIDY0LjkgODQuNiA2NC42IDg1Yy0xLjUgMS41LTMuNSAyLjMtNS42IDIuM3MtNC4xLS44LTUuNi0yLjNhNy45MSA3LjkxIDAgMCAxIDAtMTEuMmMuMy0uNCAzLjgtMy40IDI0LjEtMTIuOXptMC04Yy0xLjEgMC0yLjMuMi0zLjQuOEM2My4yIDU4LjggNTEgNjQuOSA0Ny44IDY4LjFjLTYuMiA2LjItNi4yIDE2LjMgMCAyMi41IDMuMSAzLjEgNy4yIDQuNyAxMS4yIDQuN3M4LjEtMS42IDExLjItNC43YzMuMi0zLjIgOS4zLTE1LjQgMTQuNC0yNi4zIDIuNi01LjYtMS43LTExLjQtNy4xLTExLjR6TTYzLjkgMjkuOGMtMjcuMiAwLTQ5LjUgMjIuNi00OS4xIDQ5LjggMCAzLjYuNSA3LjIgMS4zIDEwLjYuNCAxLjggMiAzLjEgMy45IDMuMSAyLjYgMCA0LjQtMi40IDMuOS00LjktLjctMy0xLjEtNi4yLTEuMS05LjNBNDIuMDQgNDIuMDQgMCAwIDEgMjYgNjNjMi01IDUtOS40IDguOC0xMy4yUzQzIDQzLjEgNDcuOSA0MWE0Mi4wNCA0Mi4wNCAwIDAgMSAzMi4yIDBjNC45IDIuMSA5LjMgNS4xIDEzLjEgOC45Qzk3IDUzLjYgOTkuOSA1OCAxMDIgNjNhNDIuMDQgNDIuMDQgMCAwIDEgMy4yIDE2LjFjMCAzLjItLjQgNi4zLTEuMSA5LjMtLjYgMi41IDEuMyA0LjkgMy45IDQuOSAxLjggMCAzLjUtMS4zIDMuOS0zLjEuOC0zLjYgMS4zLTcuMyAxLjMtMTEuMSAwLTI3LjMtMjIuMS00OS4zLTQ5LjMtNDkuM3oiIGZpbGw9IiM0NDQiLz48L3N2Zz4= // ==/UserScript== /* ------------------------------- Multi-language support (default: English) You can extend the translations object to support more languages. ---------------------------------- */ const translations = { en: { acceleratedCount: "Accelerated: ", times: " times", resetPrompt: "Are you sure you want to reset the acceleration count?", confirm: "OK", cancel: "Cancel", settingsTitle: "Accelerator Settings", accelerateExternal: "Accelerate external links", accelerateParams: "Accelerate links with parameters", openInSameTab: "Open links in the same tab", animationEffect: "Animation effect", prefetchDelay: "Prefetch delay (ms)", excludeURLs: "Exclude the following URLs (one per line)", excludeKeywords: "Exclude the following keywords (one per line)", save: "Save", usageFooter: "Click here to view the usage instructions. This assistant is free and open-source." } }; const lang = 'en'; // Default language // ------------------------------- // Utility functions // ------------------------------- let util = { getValue(name) { return GM_getValue(name); }, setValue(name, value) { GM_setValue(name, value); }, // Check if the given string (after removing '-' and '_') contains any of the keywords (case-insensitive) include(str, arr) { str = str.replace(/[-_]/ig, ''); for (let i = 0, l = arr.length; i < l; i++) { let val = arr[i].trim(); if (val !== '' && str.toLowerCase().indexOf(val.toLowerCase()) > -1) { return true; } } return false; }, addStyle(id, tag, css) { tag = tag || 'style'; let doc = document, styleDom = doc.getElementById(id); if (styleDom) return; let style = doc.createElement(tag); style.rel = 'stylesheet'; style.id = id; tag === 'style' ? style.innerHTML = css : style.href = css; doc.head.appendChild(style); }, // Common regex patterns reg: { chrome: /^https?:\/\/chrome\.google\.com\/webstore\/.+?\/([a-z]{32})(?=[\/#?]|$)/, chromeNew: /^https?:\/\/chromewebstore\.google\.com\/.+?\/([a-z]{32})(?=[\/#?]|$)/, edge: /^https?:\/\/microsoftedge\.microsoft\.com\/addons\/.+?\/([a-z]{32})(?=[\/#?]|$)/, firefox: /^https?:\/\/(reviewers\.)?(addons\.mozilla\.org|addons(?:-dev)?\.allizom\.org)\/.*?(?:addon|review)\/([^/<>"'?#]+)/, microsoft: /^https?:\/\/(?:apps|www)\.microsoft\.com\/(?:store|p)\/.+?\/([a-zA-Z\d]{10,})(?=[\/#?]|$)/, } }; // ------------------------------- // Main logic // ------------------------------- let main = { // Initialize configuration values (store values using GM storage) initValue() { // Note: The "store link" redirection option has been removed. let value = [{ name: 'setting_success_times', value: 0 }, { name: 'allow_external_links', value: true }, { name: 'allow_query_links', value: true }, { name: 'enable_target_self', value: false }, { name: 'enable_animation', value: false }, { name: 'delay_on_hover', value: 65 }, { name: 'exclude_list', value: '' }, { name: 'exclude_keyword', value: 'login\nlogout\nregister\nsignin\nsignup\nsignout\npay\ncreate\nedit\ndownload\ndel\nreset\nsubmit\ndoubleclick\ngoogleads\nexit' }]; value.forEach((v) => { if (util.getValue(v.name) === undefined) { util.setValue(v.name, v.value); } }); }, // Register menu commands for the settings panel and reset function registerMenuCommand() { GM_registerMenuCommand( "🚀 " + translations[lang].acceleratedCount + util.getValue('setting_success_times') + translations[lang].times, () => { Swal.fire({ showCancelButton: true, title: translations[lang].resetPrompt, icon: 'warning', confirmButtonText: translations[lang].confirm, cancelButtonText: translations[lang].cancel, customClass: { popup: 'instant-popup', }, }).then((res) => { if (res.isConfirmed) { util.setValue('setting_success_times', 0); history.go(0); } }); } ); let dom = `<div style="font-size: 1em;"> <label class="instant-setting-label">${translations[lang].accelerateExternal}<input type="checkbox" id="S-External" ${util.getValue('allow_external_links') ? 'checked' : ''} class="instant-setting-checkbox"></label> <label class="instant-setting-label"><span>${translations[lang].accelerateParams} (<a href="https://www.youxiaohou.com/tool/install-instantpage.html#%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E" target="_blank">Details</a>)</span><input type="checkbox" id="S-Query" ${util.getValue('allow_query_links') ? 'checked' : ''} class="instant-setting-checkbox"></label> <label class="instant-setting-label">${translations[lang].openInSameTab}<input type="checkbox" id="S-Target" ${util.getValue('enable_target_self') ? 'checked' : ''} class="instant-setting-checkbox"></label> <label class="instant-setting-label">${translations[lang].animationEffect}<input type="checkbox" id="S-Animate" ${util.getValue('enable_animation') ? 'checked' : ''} class="instant-setting-checkbox"></label> <label class="instant-setting-label">${translations[lang].prefetchDelay}<input type="number" min="65" id="S-Delay" value="${util.getValue('delay_on_hover')}" class="instant-setting-input"></label> <label class="instant-setting-label-col">${translations[lang].excludeURLs}<textarea placeholder="One per line, e.g., www.example.com" id="S-Exclude" class="instant-setting-textarea">${util.getValue('exclude_list')}</textarea></label> <label class="instant-setting-label-col">${translations[lang].excludeKeywords}<textarea placeholder="One per line, e.g., logout" id="S-Exclude-Word" class="instant-setting-textarea">${util.getValue('exclude_keyword')}</textarea></label> </div>`; GM_registerMenuCommand(translations[lang].settingsTitle, () => { Swal.fire({ title: translations[lang].settingsTitle, html: dom, showCloseButton: true, confirmButtonText: translations[lang].save, footer: `<div style="text-align: center;font-size: 1em;">${translations[lang].usageFooter}</div>`, customClass: { popup: 'instant-popup', }, }).then((res) => { if (res.isConfirmed) { history.go(0); } }); document.getElementById('S-External').addEventListener('change', (e) => { util.setValue('allow_external_links', e.currentTarget.checked); }); document.getElementById('S-Query').addEventListener('change', (e) => { util.setValue('allow_query_links', e.currentTarget.checked); }); document.getElementById('S-Target').addEventListener('change', (e) => { util.setValue('enable_target_self', e.currentTarget.checked); }); document.getElementById('S-Animate').addEventListener('change', (e) => { util.setValue('enable_animation', e.currentTarget.checked); }); document.getElementById('S-Delay').addEventListener('change', (e) => { util.setValue('delay_on_hover', e.currentTarget.value); }); document.getElementById('S-Exclude').addEventListener('change', (e) => { util.setValue('exclude_list', e.currentTarget.value); }); document.getElementById('S-Exclude-Word').addEventListener('change', (e) => { util.setValue('exclude_keyword', e.currentTarget.value); }); }); }, // Check if the current host is in the exclude list inExcludeList() { let exclude = util.getValue('exclude_list').split('\n').map(s => s.trim()); let host = location.host; return exclude.includes(host); }, // ------------------------------- // Main prefetch logic integrating instant.page v5.2.0 features // ------------------------------- instantPage() { if (window.instantLoaded) return; window.instantLoaded = true; // Configuration options (some from GM storage, some from data attributes) const allowQueryString = ('instantAllowQueryString' in document.body.dataset) || util.getValue('allow_query_links'); const allowExternalLinks = ('instantAllowExternalLinks' in document.body.dataset) || util.getValue('allow_external_links'); const _useWhitelist = ('instantWhitelist' in document.body.dataset); const enableAnimation = util.getValue('enable_animation'); const enableTargetSelf = util.getValue('enable_target_self'); const excludeKeyword = util.getValue('exclude_keyword').split('\n'); let delayOnHover = parseInt(util.getValue('delay_on_hover')); // Internal variables similar to instant.page v5.2.0 let _chromiumMajorVersionInUserAgent = null; let _speculationRulesType = 'none'; let _delayOnHover = delayOnHover; // in milliseconds let _lastTouchstartEvent = null; let _mouseoverTimer = null; let _preloadedList = new Set(); // Browser support check: ensure <link rel="prefetch"> is supported let supportChecksRelList = document.createElement('link').relList; if (!(supportChecksRelList && supportChecksRelList.supports && supportChecksRelList.supports('prefetch'))) { return; } const chromium100Check = ('throwIfAborted' in AbortSignal.prototype); // Chromium 100+ const firefox115AndSafari17_0Check = supportChecksRelList.supports('modulepreload'); // Firefox 115+, Safari 17.0+ const safari15_4AndFirefox116Check = (Intl.PluralRules && 'selectRange' in Intl.PluralRules.prototype); const firefox115AndSafari15_4Check = firefox115AndSafari17_0Check || safari15_4AndFirefox116Check; const isBrowserSupported = chromium100Check && firefox115AndSafari15_4Check; if (!isBrowserSupported) return; // If the page sets data-instantVaryAccept (e.g. Shopify), check Chromium version if (document.body.dataset.instantVaryAccept) { const chromiumUserAgentIndex = navigator.userAgent.indexOf('Chrome/'); if (chromiumUserAgentIndex > -1) { _chromiumMajorVersionInUserAgent = parseInt(navigator.userAgent.substring(chromiumUserAgentIndex + 'Chrome/'.length)); } if (_chromiumMajorVersionInUserAgent && _chromiumMajorVersionInUserAgent < 110) { return; } } // Set speculation rules if supported (<script type="speculationrules">) if (HTMLScriptElement.supports && HTMLScriptElement.supports('speculationrules')) { const speculationRulesConfig = document.body.dataset.instantSpecrules; if (speculationRulesConfig === 'prerender') { _speculationRulesType = 'prerender'; } else if (speculationRulesConfig !== 'no') { _speculationRulesType = 'prefetch'; } } // Determine trigger method based on data-instantIntensity (default is mouseover) let useMousedown = false; let useMousedownOnly = false; let useViewport = false; const mousedownShortcut = ('instantMousedownShortcut' in document.body.dataset); if ('instantIntensity' in document.body.dataset) { const intensity = document.body.dataset.instantIntensity; if (intensity === 'mousedown' && !mousedownShortcut) { useMousedown = true; } if (intensity === 'mousedown-only' && !mousedownShortcut) { useMousedown = true; useMousedownOnly = true; } if (intensity === 'viewport' || intensity === 'viewport-all') { const isOnSmallScreen = document.documentElement.clientWidth * document.documentElement.clientHeight < 450000; const isConnectionAdequate = !(navigator.connection && (navigator.connection.saveData || (navigator.connection.effectiveType && navigator.connection.effectiveType.includes('2g')))); if (isOnSmallScreen && isConnectionAdequate) { useViewport = true; } if (intensity === 'viewport-all') { useViewport = true; } } const intensityAsInteger = parseInt(intensity); if (!isNaN(intensityAsInteger)) { _delayOnHover = intensityAsInteger; } } const eventListenersOptions = { capture: true, passive: true, }; // Register event listeners based on trigger method if (useMousedownOnly) { document.addEventListener('touchstart', touchstartEmptyListener, eventListenersOptions); } else { document.addEventListener('touchstart', touchstartListener, eventListenersOptions); } if (!useMousedown) { document.addEventListener('mouseover', mouseoverListener, eventListenersOptions); } if (useMousedown) { document.addEventListener('mousedown', mousedownListener, eventListenersOptions); } if (mousedownShortcut) { document.addEventListener('mousedown', mousedownShortcutListener, eventListenersOptions); } // If viewport prefetch is enabled, use IntersectionObserver to preload links in view if (useViewport) { const requestIdleCallbackOrFallback = window.requestIdleCallback || function(callback) { callback(); }; requestIdleCallbackOrFallback(function () { const intersectionObserver = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { const anchor = entry.target; intersectionObserver.unobserve(anchor); preload(anchor); } }); }); document.querySelectorAll('a').forEach((anchor) => { if (isPreloadable(anchor)) { intersectionObserver.observe(anchor); } }); }, { timeout: 1500 }); } // ------------------------------- // Event handler functions // ------------------------------- function touchstartListener(event) { _lastTouchstartEvent = event; const anchor = event.target.closest('a'); if (!isPreloadable(anchor)) return; preload(anchor, 'high'); } function touchstartEmptyListener(event) { _lastTouchstartEvent = event; } function mouseoverListener(event) { if (isEventLikelyTriggeredByTouch(event)) return; if (!('closest' in event.target)) return; const anchor = event.target.closest('a'); if (!isPreloadable(anchor)) return; anchor.addEventListener('mouseout', mouseoutListener, { passive: true }); _mouseoverTimer = setTimeout(() => { preload(anchor, 'high'); _mouseoverTimer = null; }, _delayOnHover); } function mousedownListener(event) { if (isEventLikelyTriggeredByTouch(event)) return; const anchor = event.target.closest('a'); if (!isPreloadable(anchor)) return; preload(anchor, 'high'); } function mouseoutListener(event) { if (event.relatedTarget && event.target.closest('a') === event.relatedTarget.closest('a')) return; if (_mouseoverTimer) { clearTimeout(_mouseoverTimer); _mouseoverTimer = null; } } function mousedownShortcutListener(event) { if (isEventLikelyTriggeredByTouch(event)) return; const anchor = event.target.closest('a'); if (event.which > 1 || event.metaKey || event.ctrlKey) return; if (!anchor) return; anchor.addEventListener('click', function (e) { if (e.detail === 1337) return; e.preventDefault(); }, { capture: true, passive: false, once: true }); const customEvent = new MouseEvent('click', { view: window, bubbles: true, cancelable: false, detail: 1337 }); anchor.dispatchEvent(customEvent); } // Check if a mouse event is likely triggered by a preceding touch event (avoid duplicate prefetch on touch devices) function isEventLikelyTriggeredByTouch(event) { if (!_lastTouchstartEvent || !event) return false; if (event.target !== _lastTouchstartEvent.target) return false; const now = event.timeStamp; const duration = now - _lastTouchstartEvent.timeStamp; const MAX_DURATION = 2500; // ms return duration < MAX_DURATION; } // Determine whether the link element is preloadable based on various criteria function isPreloadable(anchor) { if (!anchor || !anchor.href) return false; if (_useWhitelist && !('instant' in anchor.dataset)) return false; if (anchor.origin !== location.origin) { const allowed = allowExternalLinks || ('instant' in anchor.dataset); if (!allowed) return false; } if (!['http:', 'https:'].includes(anchor.protocol)) return false; if (anchor.protocol === 'http:' && location.protocol === 'https:') return false; if (!allowQueryString && anchor.search && !('instant' in anchor.dataset)) return false; if (anchor.hash && (anchor.pathname + anchor.search === location.pathname + location.search)) return false; if ('noInstant' in anchor.dataset) return false; // Exclude links containing any of the specified keywords if (util.include(anchor.href, excludeKeyword)) return false; return true; } // Perform prefetch if the link has not been prefetched yet. // Choose between speculation rules (if supported) and <link rel="prefetch"> function preload(anchor, fetchPriority = 'auto') { const url = anchor.href; if (_preloadedList.has(url)) return; if (_speculationRulesType !== 'none') { preloadUsingSpeculationRules(url); } else { preloadUsingLinkElement(url, fetchPriority); } _preloadedList.add(url); if (enableAnimation) { anchor.classList.add("link-instanted"); } if (enableTargetSelf) { anchor.target = '_self'; } util.setValue('setting_success_times', util.getValue('setting_success_times') + 1); } // Prefetch using <script type="speculationrules"> function preloadUsingSpeculationRules(url) { const script = document.createElement('script'); script.type = 'speculationrules'; script.textContent = JSON.stringify({ [_speculationRulesType]: [{ source: 'list', urls: [url] }] }); document.head.appendChild(script); } // Prefetch using <link rel="prefetch"> function preloadUsingLinkElement(url, fetchPriority = 'auto') { const link = document.createElement('link'); link.rel = 'prefetch'; link.href = url; link.fetchPriority = fetchPriority; link.as = 'document'; document.head.appendChild(link); } }, // Add plugin styles to the page addPluginStyle() { let style = ` .instant-popup { font-size: 14px !important; } .instant-setting-label { display: flex; align-items: center; justify-content: space-between; padding-top: 15px; } .instant-setting-label-col { display: flex; align-items: flex-start; padding-top: 15px; flex-direction: column; } .instant-setting-checkbox { width: 16px; height: 16px; } .instant-setting-textarea { width: 100%; margin: 14px 0 0; height: 60px; resize: none; border: 1px solid #bbb; box-sizing: border-box; padding: 5px 10px; border-radius: 5px; color: #666; line-height: 1.2; } .instant-setting-input { border: 1px solid #bbb; box-sizing: border-box; padding: 5px 10px; border-radius: 5px; width: 100px; } @keyframes instantAnminate { from { opacity: 1; } 50% { opacity: 0.4; } to { opacity: 0.9; } } .link-instanted { animation: instantAnminate 0.6s 1; animation-fill-mode: forwards; } .link-instanted * { animation: instantAnminate 0.6s 1; animation-fill-mode: forwards; } `; if (document.head) { util.addStyle('swal-pub-style', 'style', GM_getResourceText('swalStyle')); util.addStyle('instant-style', 'style', style); } // Observe changes in the head element and re-add styles if needed const headObserver = new MutationObserver(() => { util.addStyle('swal-pub-style', 'style', GM_getResourceText('swalStyle')); util.addStyle('instant-style', 'style', style); }); headObserver.observe(document.head, { childList: true, subtree: true }); }, // Initialize the script init() { this.initValue(); this.addPluginStyle(); this.registerMenuCommand(); if (this.inExcludeList()) return; this.instantPage(); } }; main.init();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址