Copy & Select Unlocker

Unblock text selection, copy, right-click and remove overlay blockers on all sites

当前为 2025-04-17 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Copy & Select Unlocker
  3. // @namespace http://shinobu-scripts.local/
  4. // @version 2.1
  5. // @description Unblock text selection, copy, right-click and remove overlay blockers on all sites
  6. // @author Shinobu
  7. // @match *://*/*
  8. // @run-at document-end
  9. // @license GPLv3
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. // Add CSS to allow text selection
  16. function injectSelectionStyles() {
  17. const css = '* { user-select: text !important; -webkit-user-select: text !important; -moz-user-select: text !important; -ms-user-select: text !important; } [style*="user-select: none"], [style*="user-select:none"] { user-select: text !important; }';
  18. const styleEl = document.createElement('style');
  19. styleEl.textContent = css;
  20. document.head.appendChild(styleEl);
  21. }
  22.  
  23. // Remove full-page overlays
  24. function removeOverlays() {
  25. document.querySelectorAll('div, section').forEach(el => {
  26. const st = getComputedStyle(el);
  27. if ((st.position === 'fixed' || st.position === 'absolute') &&
  28. el.offsetWidth >= window.innerWidth * 0.9 &&
  29. el.offsetHeight >= window.innerHeight * 0.9) {
  30. el.remove();
  31. }
  32. });
  33. }
  34.  
  35. // Observe and clean overlays
  36. function observeOverlays() {
  37. const obs = new MutationObserver(removeOverlays);
  38. obs.observe(document, { childList: true, subtree: true });
  39. removeOverlays();
  40. }
  41.  
  42. // Restore native selection events
  43. function restoreEvents() {
  44. ['onselectstart', 'onmousedown', 'ondragstart'].forEach(evt => {
  45. document[evt] = null;
  46. });
  47. if (window.getSelection().empty) {
  48. window.getSelection().empty = () => {};
  49. }
  50. }
  51.  
  52. // Prevent blocking handlers
  53. function stopPropagation(e) {
  54. e.stopImmediatePropagation();
  55. }
  56.  
  57. // Initialise all features
  58. function init() {
  59. injectSelectionStyles();
  60. document.addEventListener('contextmenu', stopPropagation, true);
  61. document.addEventListener('selectstart', stopPropagation, true);
  62. document.addEventListener('copy', stopPropagation, true);
  63. document.addEventListener('keydown', e => {
  64. if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'c') {
  65. e.stopImmediatePropagation();
  66. }
  67. }, true);
  68. restoreEvents();
  69. observeOverlays();
  70. console.log('Copy & Select Liberator active');
  71. }
  72.  
  73. if (document.readyState === 'loading') {
  74. window.addEventListener('load', init);
  75. } else {
  76. init();
  77. }
  78. })();