网页加速器

自动帮你加速网页中的超链接,加快打开网页的速度,实测符合条件的网页打开速度减少50%以上。

目前为 2024-02-19 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name 网页加速器
  3. // @namespace https://github.com/Gao-Lezhe/instantpage
  4. // @version 1.0.3
  5. // @author YouXiaoHou、高乐喆(Greasy Fork镜像用户名:lezhe)
  6. // @description 自动帮你加速网页中的超链接,加快打开网页的速度,实测符合条件的网页打开速度减少50%以上。
  7. // @license AGPL
  8. // @supportURL https://github.com/Gao-Lezhe/instantpage
  9. // @require https://registry.npmmirror.com/sweetalert2/10.16.6/files/dist/sweetalert2.min.js
  10. // @resource swalStyle https://registry.npmmirror.com/sweetalert2/10.16.6/files/dist/sweetalert2.min.css
  11. // @match *://*/*
  12. // @noframes
  13. // @run-at document-idle
  14. // @grant GM_openInTab
  15. // @grant GM_setValue
  16. // @grant GM_getValue
  17. // @grant GM_registerMenuCommand
  18. // @grant GM_getResourceText
  19. // @icon data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjggMTI4Ij48cGF0aCBkPSJNMCA3OWMwLTM1LjQgMjguNS02NCA2My45LTY0LjFzNjQuMSAyOC42IDY0LjEgNjRjMCA5LjQtMi4xIDE4LjQtNS43IDI2LjUtMSAyLjMtMi4zIDQuNi0zLjYgNi43LS40LjYtMSAxLTEuNyAxSDExYy0uNyAwLTEuMy0uNC0xLjctMS0xLjMtMi4yLTIuNS00LjQtMy42LTYuN0MyLjEgOTcuNCAwIDg4LjQgMCA3OXptMjQuNC0zOS43Yy01LjIgNS4xLTkuMiAxMS4xLTEyIDE3LjgtMyA2LjktNC41IDE0LjItNC41IDIxLjhhNTUuODYgNTUuODYgMCAwIDAgNC40IDIxLjhjLjcgMS42IDEuNCAzLjIgMi4yIDQuN2g5OC44Yy44LTEuNSAxLjYtMy4xIDIuMi00LjdhNTUuODYgNTUuODYgMCAwIDAgNC40LTIxLjggNTUuODYgNTUuODYgMCAwIDAtNC40LTIxLjhjLTIuOC02LjctNi45LTEyLjctMTItMTcuOC01LjEtNS4yLTExLjEtOS4yLTE3LjgtMTJhNTUuODYgNTUuODYgMCAwIDAtMjEuOC00LjQgNTUuODYgNTUuODYgMCAwIDAtMjEuOCA0LjRjLTYuNiAyLjgtMTIuNiA2LjgtMTcuNyAxMnoiIGZpbGw9IiM0NDQiLz48cGF0aCBkPSJNMTIuNCA1Ny4xYzIuOC02LjcgNi45LTEyLjcgMTItMTcuOCA1LjEtNS4yIDExLjEtOS4yIDE3LjgtMTJBNTUuODYgNTUuODYgMCAwIDEgNjQgMjIuOWE1NS44NiA1NS44NiAwIDAgMSAyMS44IDQuNGM2LjcgMi44IDEyLjcgNi45IDE3LjggMTIgNS4yIDUuMSA5LjIgMTEuMSAxMiAxNy44YTU1Ljg2IDU1Ljg2IDAgMCAxIDQuNCAyMS44IDU1Ljg2IDU1Ljg2IDAgMCAxLTQuNCAyMS44Yy0uNyAxLjYtMS40IDMuMi0yLjIgNC43SDE0LjZjLS44LTEuNS0xLjYtMy4xLTIuMi00LjdBNTUuODYgNTUuODYgMCAwIDEgOCA3OC45Yy0uMS03LjYgMS40LTE0LjkgNC40LTIxLjh6IiBmaWxsPSIjNjQ5OTUwIi8+PHBhdGggZD0iTTc3LjUgNjAuOUM2OCA4MS4yIDY0LjkgODQuNiA2NC42IDg1Yy0xLjUgMS41LTMuNSAyLjMtNS42IDIuM3MtNC4xLS44LTUuNi0yLjNhNy45MSA3LjkxIDAgMCAxIDAtMTEuMmMuMy0uNCAzLjgtMy40IDI0LjEtMTIuOXptMC04Yy0xLjEgMC0yLjMuMi0zLjQuOEM2My4yIDU4LjggNTEgNjQuOSA0Ny44IDY4LjFjLTYuMiA2LjItNi4yIDE2LjMgMCAyMi41IDMuMSAzLjEgNy4yIDQuNyAxMS4yIDQuN3M4LjEtMS42IDExLjItNC43YzMuMi0zLjIgOS4zLTE1LjQgMTQuNC0yNi4zIDIuNi01LjYtMS43LTExLjQtNy4xLTExLjR6TTYzLjkgMjkuOGMtMjcuMiAwLTQ5LjUgMjIuNi00OS4xIDQ5LjggMCAzLjYuNSA3LjIgMS4zIDEwLjYuNCAxLjggMiAzLjEgMy45IDMuMSAyLjYgMCA0LjQtMi40IDMuOS00LjktLjctMy0xLjEtNi4yLTEuMS05LjNBNDIuMDQgNDIuMDQgMCAwIDEgMjYgNjNjMi01IDUtOS40IDguOC0xMy4yUzQzIDQzLjEgNDcuOSA0MWE0Mi4wNCA0Mi4wNCAwIDAgMSAzMi4yIDBjNC45IDIuMSA5LjMgNS4xIDEzLjEgOC45Qzk3IDUzLjYgOTkuOSA1OCAxMDIgNjNhNDIuMDQgNDIuMDQgMCAwIDEgMy4yIDE2LjFjMCAzLjItLjQgNi4zLTEuMSA5LjMtLjYgMi41IDEuMyA0LjkgMy45IDQuOSAxLjggMCAzLjUtMS4zIDMuOS0zLjEuOC0zLjYgMS4zLTcuMyAxLjMtMTEuMSAwLTI3LjMtMjIuMS00OS4zLTQ5LjMtNDkuM3oiIGZpbGw9IiM0NDQiLz48L3N2Zz4=
  20. // ==/UserScript==
  21.  
  22. (function () {
  23. 'use strict';
  24.  
  25. let util = {
  26. getValue(name) {
  27. return GM_getValue(name);
  28. },
  29.  
  30. setValue(name, value) {
  31. GM_setValue(name, value);
  32. },
  33.  
  34. include(str, arr) {
  35. str = str.replace(/[-_]/ig, '');
  36. for (let i = 0, l = arr.length; i < l; i++) {
  37. let val = arr[i];
  38. if (val !== '' && str.toLowerCase().indexOf(val.toLowerCase()) > -1) {
  39. return true;
  40. }
  41. }
  42. return false;
  43. },
  44.  
  45. addStyle(id, tag, css) {
  46. tag = tag || 'style';
  47. let doc = document, styleDom = doc.getElementById(id);
  48. if (styleDom) return;
  49. let style = doc.createElement(tag);
  50. style.rel = 'stylesheet';
  51. style.id = id;
  52. tag === 'style' ? style.innerHTML = css : style.href = css;
  53. doc.head.appendChild(style);
  54. },
  55.  
  56. reg: {
  57. chrome: /^https?:\/\/chrome.google.com\/webstore\/.+?\/([a-z]{32})(?=[\/#?]|$)/,
  58. chromeNew: /^https?:\/\/chromewebstore.google.com\/.+?\/([a-z]{32})(?=[\/#?]|$)/,
  59. edge: /^https?:\/\/microsoftedge.microsoft.com\/addons\/.+?\/([a-z]{32})(?=[\/#?]|$)/,
  60. firefox: /^https?:\/\/(reviewers\.)?(addons\.mozilla\.org|addons(?:-dev)?\.allizom\.org)\/.*?(?:addon|review)\/([^/<>"'?#]+)/,
  61. microsoft: /^https?:\/\/(?:apps|www).microsoft.com\/(?:store|p)\/.+?\/([a-zA-Z\d]{10,})(?=[\/#?]|$)/,
  62. }
  63. };
  64.  
  65. let main = {
  66. initValue() {
  67. let value = [{
  68. name: 'setting_success_times',
  69. value: 0
  70. }, {
  71. name: 'allow_external_links',
  72. value: true
  73. }, {
  74. name: 'allow_query_links',
  75. value: true
  76. }, {
  77. name: 'enable_store_link',
  78. value: true
  79. }, {
  80. name: 'enable_target_self',
  81. value: false
  82. }, {
  83. name: 'enable_animation',
  84. value: false
  85. }, {
  86. name: 'delay_on_hover',
  87. value: 65
  88. }, {
  89. name: 'exclude_list',
  90. value: ''
  91. }, {
  92. name: 'exclude_keyword',
  93. value: 'login\nlogout\nregister\nsignin\nsignup\nsignout\npay\ncreate\nedit\ndownload\ndel\nreset\nsubmit\ndoubleclick\ngoogleads\nexit'
  94. }];
  95.  
  96. value.forEach((v) => {
  97. util.getValue(v.name) === undefined && util.setValue(v.name, v.value);
  98. });
  99. },
  100.  
  101. registerMenuCommand() {
  102. GM_registerMenuCommand('🚀 已加速:' + util.getValue('setting_success_times') + '次', () => {
  103. Swal.fire({
  104. showCancelButton: true,
  105. title: '确定要重置加速次数吗?',
  106. icon: 'warning',
  107. confirmButtonText: '确定',
  108. cancelButtonText: '取消',
  109. customClass: {
  110. popup: 'instant-popup',
  111. },
  112. }).then((res) => {
  113. if (res.isConfirmed) {
  114. util.setValue('setting_success_times', 0);
  115. history.go(0);
  116. }
  117. });
  118. });
  119. GM_registerMenuCommand('⚙️ 设置', () => {
  120. let dom = `<div style="font-size: 1em;">
  121. <label class="instant-setting-label">加速外部链接<input type="checkbox" id="S-External" ${util.getValue('allow_external_links') ? 'checked' : ''} class="instant-setting-checkbox"></label>
  122. <label class="instant-setting-label"><span>加速含参数链接 <a href="https://www.youxiaohou.com/tool/install-instantpage.html#%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E">详见</a></span><input type="checkbox" id="S-Query" ${util.getValue('allow_query_links') ? 'checked' : ''}
  123. class="instant-setting-checkbox"></label>
  124. <label class="instant-setting-label">加速扩展商店链接<input type="checkbox" id="S-Store" ${util.getValue('enable_store_link') ? 'checked' : ''} class="instant-setting-checkbox"></label>
  125. <label class="instant-setting-label">加速链接在当前页打开<input type="checkbox" id="S-Target" ${util.getValue('enable_target_self') ? 'checked' : ''} class="instant-setting-checkbox"></label>
  126. <label class="instant-setting-label">加速动画效果<input type="checkbox" id="S-Animate" ${util.getValue('enable_animation') ? 'checked' : ''}
  127. class="instant-setting-checkbox"></label>
  128. <label class="instant-setting-label">链接预读延时(毫秒)<input type="number" min="65" id="S-Delay" value="${util.getValue('delay_on_hover')}"
  129. class="instant-setting-input"></label>
  130. <label class="instant-setting-label-col">排除下列网址 <textarea placeholder="列表中的域名将不开启加速器,一行一个,例如:www.baidu.com" id="S-Exclude" class="instant-setting-textarea">${util.getValue('exclude_list')}</textarea></label>
  131. <label class="instant-setting-label-col">排除下列关键词 <textarea placeholder="链接中含关键词将不开启加速器,一行一个,例如:logout" id="S-Exclude-Word" class="instant-setting-textarea">${util.getValue('exclude_keyword')}</textarea></label>
  132. </div>`;
  133. Swal.fire({
  134. title: '加速器配置',
  135. html: dom,
  136. showCloseButton: true,
  137. confirmButtonText: '保存',
  138. footer: '<div style="text-align: center;font-size: 1em;">点击查看 <a href="https://www.youxiaohou.com/tool/install-instantpage.html" target="_blank">使用说明</a>,助手免费开源,Powered by <a href="https://www.youxiaohou.com">油小猴</a></div>',
  139. customClass: {
  140. popup: 'instant-popup',
  141. },
  142. }).then((res) => {
  143. if (res.isConfirmed) {
  144. history.go(0);
  145. }
  146. });
  147.  
  148. document.getElementById('S-External').addEventListener('change', (e) => {
  149. util.setValue('allow_external_links', e.currentTarget.checked);
  150. });
  151. document.getElementById('S-Query').addEventListener('change', (e) => {
  152. util.setValue('allow_query_links', e.currentTarget.checked);
  153. });
  154. document.getElementById('S-Store').addEventListener('change', (e) => {
  155. util.setValue('enable_store_link', e.currentTarget.checked);
  156. });
  157. document.getElementById('S-Target').addEventListener('change', (e) => {
  158. util.setValue('enable_target_self', e.currentTarget.checked);
  159. });
  160. document.getElementById('S-Animate').addEventListener('change', (e) => {
  161. util.setValue('enable_animation', e.currentTarget.checked);
  162. });
  163. document.getElementById('S-Delay').addEventListener('change', (e) => {
  164. util.setValue('delay_on_hover', e.currentTarget.value);
  165. });
  166. document.getElementById('S-Exclude').addEventListener('change', (e) => {
  167. util.setValue('exclude_list', e.currentTarget.value);
  168. });
  169. document.getElementById('S-Exclude-Word').addEventListener('change', (e) => {
  170. util.setValue('exclude_keyword', e.currentTarget.value);
  171. });
  172. });
  173. },
  174.  
  175. //在排除名单里
  176. inExcludeList() {
  177. let exclude = util.getValue('exclude_list').split('\n');
  178. let host = location.host;
  179. return exclude.includes(host);
  180. },
  181.  
  182. //加速主代码
  183. instantPage() {
  184. if (window.instantLoaded) return;
  185. let mouseoverTimer;
  186. let lastTouchTimestamp;
  187. const prefetches = new Set();
  188. const prefetchElement = document.createElement('link');
  189. const isSupported = prefetchElement.relList && prefetchElement.relList.supports && prefetchElement.relList.supports('prefetch')
  190. && window.IntersectionObserver && 'isIntersecting' in IntersectionObserverEntry.prototype;
  191. const isOnline = () => window.navigator.onLine;
  192. const allowQueryString = 'instantAllowQueryString' in document.body.dataset || util.getValue('allow_query_links');
  193. const allowExternalLinks = 'instantAllowExternalLinks' in document.body.dataset || util.getValue('allow_external_links');
  194. const useWhitelist = 'instantWhitelist' in document.body.dataset;
  195. const mousedownShortcut = 'instantMousedownShortcut' in document.body.dataset;
  196. const DELAY_TO_NOT_BE_CONSIDERED_A_TOUCH_INITIATED_ACTION = 1111;
  197. const enableAnimation = util.getValue('enable_animation');
  198. const enableTargetSelf = util.getValue('enable_target_self');
  199. const enableStoreLink = util.getValue('enable_store_link');
  200. window.instantLoaded = true;
  201. const excludeKeyword = util.getValue('exclude_keyword').split('\n');
  202.  
  203. let delayOnHover = util.getValue('delay_on_hover');
  204. let useMousedown = false;
  205. let useMousedownOnly = false;
  206. let useViewport = false;
  207.  
  208. if ('instantIntensity' in document.body.dataset) {
  209. const intensity = document.body.dataset.instantIntensity;
  210.  
  211. if (intensity.substr(0, 'mousedown'.length) === 'mousedown') {
  212. useMousedown = true;
  213. if (intensity === 'mousedown-only') {
  214. useMousedownOnly = true;
  215. }
  216. } else if (intensity.substr(0, 'viewport'.length) === 'viewport') {
  217. if (!(navigator.connection && (navigator.connection.saveData || (navigator.connection.effectiveType && navigator.connection.effectiveType.includes('2g'))))) {
  218. if (intensity === "viewport") {
  219. if (document.documentElement.clientWidth * document.documentElement.clientHeight < 450000) {
  220. useViewport = true;
  221. }
  222. } else if (intensity === "viewport-all") {
  223. useViewport = true;
  224. }
  225. }
  226. } else {
  227. const milliseconds = parseInt(intensity);
  228. if (!Number.isNaN(milliseconds)) {
  229. delayOnHover = milliseconds;
  230. }
  231. }
  232. }
  233.  
  234. if (isSupported) {
  235. const eventListenersOptions = {
  236. capture: true,
  237. passive: true,
  238. };
  239.  
  240. if (!useMousedownOnly) {
  241. document.addEventListener('touchstart', touchstartListener, eventListenersOptions);
  242. }
  243.  
  244. if (!useMousedown) {
  245. document.addEventListener('mouseover', mouseoverListener, eventListenersOptions);
  246. } else if (!mousedownShortcut) {
  247. document.addEventListener('mousedown', mousedownListener, eventListenersOptions);
  248. }
  249.  
  250. if (mousedownShortcut) {
  251. document.addEventListener('mousedown', mousedownShortcutListener, eventListenersOptions);
  252. }
  253.  
  254.  
  255. if (useViewport) {
  256. let triggeringFunction;
  257. if (window.requestIdleCallback) {
  258. triggeringFunction = (callback) => {
  259. requestIdleCallback(callback, {
  260. timeout: 1500,
  261. });
  262. };
  263. } else {
  264. triggeringFunction = (callback) => {
  265. callback();
  266. };
  267. }
  268.  
  269. triggeringFunction(() => {
  270. const intersectionObserver = new IntersectionObserver((entries) => {
  271. entries.forEach((entry) => {
  272. if (entry.isIntersecting) {
  273. const linkElement = entry.target;
  274. intersectionObserver.unobserve(linkElement);
  275. preload(linkElement);
  276. }
  277. });
  278. });
  279.  
  280. document.querySelectorAll('a').forEach((linkElement) => {
  281. if (isPreloadable(linkElement)) {
  282. intersectionObserver.observe(linkElement);
  283. }
  284. });
  285. });
  286. }
  287. }
  288.  
  289. function touchstartListener(event) {
  290. /* Chrome on Android calls mouseover before touchcancel so `lastTouchTimestamp`
  291. * must be assigned on touchstart to be measured on mouseover. */
  292. lastTouchTimestamp = performance.now();
  293.  
  294. const linkElement = event.target.closest('a');
  295.  
  296. if (!isPreloadable(linkElement)) {
  297. return;
  298. }
  299.  
  300. preload(linkElement);
  301. }
  302.  
  303. function mouseoverListener(event) {
  304. if (performance.now() - lastTouchTimestamp < DELAY_TO_NOT_BE_CONSIDERED_A_TOUCH_INITIATED_ACTION) {
  305. return;
  306. }
  307.  
  308. if (!('closest' in event.target)) {
  309. // Without this check sometimes an error “event.target.closest is not a function” is thrown, for unknown reasons
  310. // That error denotes that `event.target` isn’t undefined. My best guess is that it’s the Document.
  311.  
  312. // Details could be gleaned from throwing such an error:
  313. //throw new TypeError(`instant.page non-element event target: timeStamp=${~~event.timeStamp}, type=${event.type}, typeof=${typeof event.target}, nodeType=${event.target.nodeType}, nodeName=${event.target.nodeName}, viewport=${innerWidth}x${innerHeight}, coords=${event.clientX}x${event.clientY}, scroll=${scrollX}x${scrollY}`)
  314. return
  315. }
  316.  
  317. const linkElement = event.target.closest('a');
  318.  
  319. if (!isPreloadable(linkElement)) {
  320. return;
  321. }
  322.  
  323. linkElement.addEventListener('mouseout', mouseoutListener, {passive: true});
  324.  
  325. mouseoverTimer = setTimeout(() => {
  326. preload(linkElement);
  327. mouseoverTimer = undefined;
  328. }, delayOnHover);
  329. }
  330.  
  331. function mousedownListener(event) {
  332. const linkElement = event.target.closest('a');
  333.  
  334. if (!isPreloadable(linkElement)) {
  335. return;
  336. }
  337.  
  338. preload(linkElement);
  339. }
  340.  
  341. function mouseoutListener(event) {
  342. if (event.relatedTarget && event.target.closest('a') === event.relatedTarget.closest('a')) {
  343. return;
  344. }
  345.  
  346. if (mouseoverTimer) {
  347. clearTimeout(mouseoverTimer);
  348. mouseoverTimer = undefined;
  349. }
  350. }
  351.  
  352. function mousedownShortcutListener(event) {
  353. if (performance.now() - lastTouchTimestamp < DELAY_TO_NOT_BE_CONSIDERED_A_TOUCH_INITIATED_ACTION) {
  354. return;
  355. }
  356.  
  357. const linkElement = event.target.closest('a');
  358.  
  359. if (event.which > 1 || event.metaKey || event.ctrlKey) {
  360. return;
  361. }
  362.  
  363. if (!linkElement) {
  364. return;
  365. }
  366.  
  367. linkElement.addEventListener('click', function (event) {
  368. if (event.detail === 1337) {
  369. return;
  370. }
  371.  
  372. event.preventDefault();
  373. }, {capture: true, passive: false, once: true});
  374.  
  375. const customEvent = new MouseEvent('click', {
  376. view: window,
  377. bubbles: true,
  378. cancelable: true,
  379. detail: 1337
  380. });
  381. linkElement.dispatchEvent(customEvent);
  382. }
  383.  
  384. function isPreloadable(linkElement) {
  385. if (!linkElement || !linkElement.href) {
  386. return;
  387. }
  388.  
  389. if (util.include(linkElement.href, excludeKeyword)) {
  390. if (!util.reg.chrome.test(linkElement.href) &&
  391. !util.reg.chromeNew.test(linkElement.href) &&
  392. !util.reg.edge.test(linkElement.href) &&
  393. !util.reg.edge.test(linkElement.href) &&
  394. !util.reg.microsoft.test(linkElement.href)) {
  395. return;
  396. }
  397. }
  398.  
  399. if (useWhitelist && !('instant' in linkElement.dataset)) {
  400. return;
  401. }
  402.  
  403. if (!allowExternalLinks && linkElement.origin !== location.origin && !('instant' in linkElement.dataset)) {
  404. return;
  405. }
  406.  
  407. if (!['http:', 'https:'].includes(linkElement.protocol)) {
  408. return;
  409. }
  410.  
  411. if (linkElement.protocol === 'http:' && location.protocol === 'https:') {
  412. if (linkElement.href.indexOf('http://www.baidu.com/link?url') === 0) {
  413. linkElement.href = linkElement.href.replace('http', 'https');
  414. } else {
  415. return;
  416. }
  417. }
  418. //下载文件不加速
  419. if (/\.[a-zA-Z0-9]{0,5}$/i.test(linkElement.href)) {
  420. //排除域名,网站扩展名
  421. if (!/(com|cn|top|ltd|net|tech|shop|vip|xyz|wang|cloud|online|site|love|art|xin|store|fun|cc|website|press|space|beer|luxe|video|ren|group|fit|yoga|org|pro|ink|biz|info|design|link|work|mobi|kim|pub|name|tv|co|asia|red|live|wiki|gov|life|world|run|show|city|gold|today|plus|cool|icu|company|chat|zone|fans|law|host|center|club|email|fund|social|team|guru|htm|html|php|asp|jsp)$/i.test(linkElement.href)) {
  422. return;
  423. }
  424. }
  425.  
  426. if (!allowQueryString && linkElement.search && !('instant' in linkElement.dataset)) {
  427. return;
  428. }
  429.  
  430. if (linkElement.hash && linkElement.pathname + linkElement.search === location.pathname + location.search) {
  431. return;
  432. }
  433.  
  434. if (linkElement.dataset.filename || linkElement.dataset.noInstant) {
  435. return;
  436. }
  437.  
  438. return true;
  439. }
  440.  
  441. function preload(linkElement) {
  442. let url = linkElement.href;
  443.  
  444. if (!isOnline()) {
  445. return;
  446. }
  447.  
  448. if (prefetches.has(url)) {
  449. return;
  450. }
  451.  
  452. if (enableStoreLink) {
  453. if (util.reg.chromeNew.test(url)) {
  454. linkElement.href = url.replace("chromewebstore.google.com", "chrome.crxsoso.com/webstore");
  455. }
  456. if (util.reg.edge.test(url)) {
  457. linkElement.href = url.replace("microsoftedge.microsoft.com", "microsoftedge.crxsoso.com");
  458. }
  459. if (util.reg.firefox.test(url)) {
  460. linkElement.href = url.replace("addons.mozilla.org", "addons.crxsoso.com");
  461. }
  462. }
  463.  
  464. const prefetcher = document.createElement('link');
  465. prefetcher.rel = 'prefetch';
  466. prefetcher.href = url;
  467. document.head.appendChild(prefetcher);
  468.  
  469. prefetches.add(url);
  470.  
  471. if (enableAnimation) {
  472. linkElement.classList.add("link-instanted");
  473. }
  474. if (enableTargetSelf) {
  475. linkElement.target = '_self';
  476. }
  477.  
  478. util.setValue('setting_success_times', util.getValue('setting_success_times') + 1);
  479. }
  480. },
  481.  
  482. addPluginStyle() {
  483. let style = `
  484. .instant-popup { font-size: 14px !important; }
  485. .instant-setting-label { display: flex;align-items: center;justify-content: space-between;padding-top: 15px; }
  486. .instant-setting-label-col { display: flex;align-items: flex-start;;padding-top: 15px;flex-direction:column }
  487. .instant-setting-checkbox { width: 16px;height: 16px; }
  488. .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; }
  489. .instant-setting-input { border: 1px solid #bbb; box-sizing: border-box; padding: 5px 10px; border-radius: 5px; width: 100px}
  490. @keyframes instantAnminate { from { opacity: 1; } 50% { opacity: 0.4 } to { opacity: 0.9; }}
  491. .link-instanted { animation: instantAnminate 0.6s 1; animation-fill-mode:forwards }
  492. .link-instanted * { animation: instantAnminate 0.6s 1; animation-fill-mode:forwards }
  493. `;
  494.  
  495. if (document.head) {
  496. util.addStyle('swal-pub-style', 'style', GM_getResourceText('swalStyle'));
  497. util.addStyle('instant-style', 'style', style);
  498. }
  499.  
  500. const headObserver = new MutationObserver(() => {
  501. util.addStyle('swal-pub-style', 'style', GM_getResourceText('swalStyle'));
  502. util.addStyle('instant-style', 'style', style);
  503. });
  504. headObserver.observe(document.head, {childList: true, subtree: true});
  505. },
  506.  
  507. init() {
  508. this.initValue();
  509. this.addPluginStyle();
  510. this.registerMenuCommand();
  511. if (this.inExcludeList()) return;
  512. this.instantPage();
  513. }
  514. };
  515. main.init();
  516. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址