OpenAnySelectedURL

Open all unique URLs found in the selected text using Ctrl + Escape.

当前为 2025-05-07 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name OpenAnySelectedURL
  3. // @version 25.5.7
  4. // @description Open all unique URLs found in the selected text using Ctrl + Escape.
  5. // @author 8TM (https://github.com/8tm/Tampermonkey-OpenAnySelectedURL)
  6. // @license CC-BY-NC-4.0
  7. // @icon https://raw.githubusercontent.com/8tm/Tampermonkey-OpenAnySelectedURL/4cf59b8545017d6358ffb7e02a933e3d2929f346/icon.png
  8. // @match *://*/*
  9. // @compatible firefox
  10. // @grant GM_openInTab
  11. // @namespace https://greasyfork.org/users/1386567
  12. // ==/UserScript==
  13.  
  14. (() => {
  15. 'use strict';
  16.  
  17. // Simple regex for detecting URLs (used only in normalizeUrl)
  18. const urlPattern = /^(https?:\/\/[\S]+)|(www\.[^\s]+)/i;
  19.  
  20. // Check if URL is valid
  21. function isValidUrl(string) {
  22. try {
  23. new URL(string);
  24. return true;
  25. } catch (_) {
  26. return false;
  27. }
  28. }
  29.  
  30. // Normalizes and auto-completes the protocol if missing (www → http://www)
  31. function normalizeUrl(str) {
  32. let url = str.trim();
  33. if (!/^https?:\/\//i.test(url)) {
  34. if (/^www\./i.test(url)) {
  35. url = 'http://' + url;
  36. } else {
  37. return null;
  38. }
  39. }
  40. return url;
  41. }
  42.  
  43. // Common function for handling the current selection
  44. function handleOpen() {
  45. const sel = window.getSelection().toString().trim();
  46. if (!sel) return;
  47.  
  48. // Locate all URLs in the text, excluding surrounding parentheses, quotes or angle brackets
  49. const matches = sel.match(/(https?:\/\/[^\s\(\)'\"<>]+|www\.[^\s\(\)'\"<>]+)/ig);
  50. if (!matches) return;
  51.  
  52. // Normalize, filter out invalid and dedupe
  53. const urls = Array.from(new Set(
  54. matches
  55. .map(raw => {
  56. // 1) remove all BBCode tags [/<tagname>]
  57. const cleaned = raw.replace(/(\[\/[^\]]+\])+$/gi, '');
  58. // 2) normalize
  59. const normalized = normalizeUrl(cleaned);
  60. if (!normalized) return null;
  61. // 3) Czeck if it's real URL
  62. if (!isValidUrl(normalized)) {
  63. alert(`Invalid URL: ${normalized}`);
  64. return null;
  65. }
  66. return normalized;
  67. })
  68. .filter(u => u)
  69. ));
  70.  
  71. // Open each URL in the background
  72. urls.forEach(u => {
  73. GM_openInTab(u, true);
  74. });
  75. }
  76.  
  77. // Keyboard shortcut: Ctrl + Escape
  78. document.addEventListener('keydown', e => {
  79. if (e.ctrlKey && e.key === 'Escape') {
  80. e.preventDefault();
  81. handleOpen();
  82. }
  83. });
  84.  
  85. })();