Remove Restrictions and Restore Default Behavior

Allows you select, cut, copy, paste, save and open the DevTools on any website.

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

  1. // ==UserScript==
  2. // @name Remove Restrictions and Restore Default Behavior
  3. // @name:zh-CN 解除网页限制,恢复默认行为
  4. // @name:en-US Remove Restrictions and Restore Default Behavior
  5. // @namespace http://hl-bo.github.io/namespaces/user-script/remove-limits
  6. // @source https://github.com/HL-Bo/user-script
  7. // @supportURL https://github.com/HL-Bo/user-script/issues
  8. // @version 2.3
  9. // @license AGPLv3
  10. // @description Allows you select, cut, copy, paste, save and open the DevTools on any website.
  11. // @description:zh-CN 恢复选择、剪切、复制、粘贴、保存、右键菜单和打开开发者工具的默认行为。
  12. // @description:en-US Allows you select, cut, copy, paste, save and open the DevTools on any website.
  13. // @author HL-Bo
  14. // @match *://*/**
  15. // @exclude *://vscode.dev
  16. // @exclude *://vscode.dev/**
  17. // @exclude *://*.github.dev
  18. // @exclude *://*.github.dev/**
  19. // @exclude *://github.com/*/*/edit/**
  20. // @exclude *://gitee.com/*/*/edit/**
  21. // @exclude *://codeberg.org/*/*/_edit/**
  22. // @exclude *://www.figma.com/file/**
  23. // @exclude *://www.notion.so/**
  24. // @exclude *://outlook.live.com/**
  25. // @exclude *://mail.netease.com/**
  26. // @exclude *://mail.163.com/**
  27. // @exclude *://mail.126.com/**
  28. // @exclude *://www.yeah.net/**
  29. // @exclude *://mail.qq.com/**
  30. // @exclude *://uutool.cn/*
  31. // @exclude *://anytexteditor.com/*/online-notepad
  32. // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAspJREFUWEfVl89PE1EQx7/TdpcabKFAoEKQH22ktEYSqRevXiRijEr8cSDe/DNM9D/xhPFn4oF4MeBZuJi0SiiQikTjD2gLCLS7jNmFLt2mu/uWYtB36G73zWQ+b2bevDeEijE5Od/Q3ut5CNA9gMOVc3bvG7+3MLeYRU9nhxqP9r2WURoPh8ObIvpUKTSbzkww6I6IYqWMAdAVxmCkF8z8zk/KFREIA2BmbilGu7tpZpigRGCqATQdAk3LKI46QRjGZtOZ6wx6KWKwWqYWgCbDzNN+UmwhDID3HxduEuP5UQKIQPx1gDJEnpTRoRqJaQnw/dcqVvPrANf2iST50N/dCSKCVQjMmjyVg3K1GsISILvyFT/X8pYRkXw+nD3TD4/HIwigp+ZUDkUThG0I9MVbeIAq9srW9g7SmSW0t4ZwPjHglEZvf3xZGkkmk6W93bI/qpNQUVVs7xRtPOBFgyzr88yM1PwidoolRE53oS3UbAuhMo8Mx/re2ALMZ5dRWLcuZlrsh2JReL1e3ZiWB5nsMlR118kDII/39v2xy09tAQobm8jrALVjIEsSOtpaTMZKioLVXAHaU/OK1fAAt65duvjMFsBxGXUIMGHswmDkhS2AtpK1wnodZg5UQ8EAWpqDxgchgIXPK8gdEUBzMKAnZ3kIAWgxLCmq9T4U9g1B8nn1gvV/ARx7CI49CYVDfAhBoSR0KkTidglNgUYETza6S0KtrO5VwvqHBhDt6XYH4HQYucHyN8jw7Z8Z+uElUgl1QePHjbkqWao4cvenhACcLiRukNpCTejpOuUuBE5XMmEAAlqaAmhvPTg5hTwgbOAQgv8mQD2NiVsnEPjGcDz6ynQfmPkwFyPJd6jWzA0AEZhLSjx5buCTCUD7M5temGDAdXPqCgB4MhyP3C3rmBrRVColb5H/kdv2XAyAvgH8+ARvP0gkEsZ1+w+ixcUwoQ+80AAAAABJRU5ErkJggg==
  33. // @require https://unpkg.com/default-passive-events
  34. // @grant none
  35. // @run-at document-start
  36. // ==/UserScript==
  37.  
  38. (function () {
  39. 'use strict';
  40. let in_frame = false;
  41. if (window.frameElement && window.frameElement.tagName === 'IFRAME' || window !== window.top) {
  42. in_frame = true;
  43. }
  44. if (!in_frame) {
  45. console.log(
  46. " ____ _ _ _ _ \n" +
  47. " | _ \\ ___ _ __ ___ ___ __ __ ___ | | (_) _ __ ___ (_) | |_ ___ \n" +
  48. " | |_) | / _ \\ | '_ ` _ \\ / _ \\ \\ \\ / / / _ \\ | | | | | '_ ` _ \\ | | | __| / __|\n" +
  49. " | _ < | __/ | | | | | | | (_) | \\ V / | __/ | |___ | | | | | | | | | | | |_ \\__ \\\n" +
  50. " |_| \\_\\ \\___| |_| |_| |_| \\___/ \\_/ \\___| |_____| |_| |_| |_| |_| |_| \\__| |___/\n" +
  51. " \n" +
  52. " By HL-Bo"
  53. )
  54. }
  55. if (in_frame) {
  56. console.debug('Start the installation of user-script/remove-limits (IN-FRAME)');
  57. } else {
  58. console.info('Start the installation of user-script/remove-limits');
  59. }
  60.  
  61. // 尝试禁用 debugger
  62. // 仅在 eval('debugger') 或 setInterval('debugger', sec) 构造前执行才能阻止
  63. try {
  64. Function.prototype.__constructor_back = Function.prototype.constructor;
  65. Function.prototype.constructor = function () {
  66. if (arguments && typeof arguments[0] === 'string') {
  67. if ('debugger' === arguments[0]) {
  68. console.debug('Disable an function which may execute debugger');
  69. return;
  70. }
  71. }
  72. return Function.prototype.__constructor_back.apply(this, arguments);
  73. }
  74. } catch (error) { console.warn(error); } finally { }
  75.  
  76. let logError = function (error) {
  77. let error_message = error.toString();
  78. if (document) {
  79. if (document.body.rl_errors) {
  80. if (!document.body.rl_errors.includes(error_message)) {
  81. if (in_frame) { console.debug(error_message); } else { console.warn(error_message); }
  82. document.body.rl_errors.push(error_message);
  83. }
  84. } else {
  85. document.body.rl_errors = new Array();
  86. }
  87. }
  88. };
  89. let executeWithInterval = function (func, delay) {
  90. setTimeout(func, 0); // 异步执行,防止阻塞
  91. setInterval(func, delay);
  92. };
  93. let setEventListener = function (element, event_name, listener) {
  94. if (element.rl_events) {
  95. if (element.rl_events.has(event_name)) {
  96. element.removeEventListener(event_name, element.rl_events.get(event_name));
  97. }
  98. } else {
  99. element.rl_events = new Map();
  100. }
  101. element.rl_events.set(event_name, listener);
  102. element.addEventListener(event_name, listener);
  103. };
  104. let returnEventAllowed = function (event, event_name) {
  105. try {
  106. event.returnValue = true;
  107. } catch (error) { logError(error); } finally { }
  108. if (event_name !== null && event.currentTarget === document) {
  109. console.debug(`Allow ${event_name}`);
  110. }
  111. };
  112. let allowEvent = function (element, event_name) {
  113. setEventListener(element, event_name, function (event) { returnEventAllowed(event, event_name); return true; });
  114. };
  115. let onKeyEvents = function (event) {
  116. let keyCode = event.keyCode || event.which || event.charCode;
  117. let ctrlKey = event.ctrlKey || event.metaKey;
  118. let shiftKey = event.shiftKey;
  119. if (ctrlKey && (keyCode == 65 || keyCode == 88 || keyCode == 67 || keyCode == 86 || keyCode == 83 || keyCode == 85)) {
  120. // Ctrl+A (select-all), Ctrl+X (cut), Ctrl+C (copy), Ctrl+V (paste), Ctrl+S (save), Ctrl+U (view-source)
  121. returnEventAllowed(event, 'hotkey');
  122. } else if (ctrlKey && shiftKey && (keyCode == 73 || keyCode == 74 || keyCode == 67)) {
  123. // Ctrl+Shift+I (devtools), Ctrl+Shift+J (console), Ctrl+Shift+C (elements)
  124. returnEventAllowed(event, 'hotkey (DevTools)');
  125. } else if (keyCode && keyCode == 123) { // F12
  126. returnEventAllowed(event, 'hotkey (F12)');
  127. }
  128. return true;
  129. };
  130. let allowKeyEvents = function (element, event_name) {
  131. setEventListener(element, event_name, onKeyEvents);
  132. };
  133. let preventEventChecks = function (element) {
  134. let all_events = ['onbeforecopy', 'oncopy', 'onbeforecut', 'oncut', 'onbeforepaste', 'onpaste', 'onselectstart', 'oncontextmenu', 'ondragstart', 'ondragenter', 'ondragover', 'ondragleave', 'ondragend', 'ondrop', 'onkeypress', 'onkeydown', 'onkeyup', 'onvisibilitychange', 'onmousedown', 'onmouseup', 'onmousewheel', 'onwheel', 'onmouseenter', 'onmousemove', 'onmouseover', 'onmouseout', 'onmouseleave', 'ongotpointercapture', 'onlostpointercapture', 'onpointerdown', 'onpointerrawupdate', 'onpointerup', 'onpointerenter', 'onpointermove', 'onpointerover', 'onpointerout', 'onpointerleave', 'onpointercancel', 'onfocus', 'onfocusin', 'onfocusout', 'onblur'];
  135. for (let i of all_events) {
  136. Object.defineProperty(element, i, { get: () => { (event) => false }, set: (value) => { if (value === null) { } } });
  137. }
  138. };
  139. let allowElement = function (element) {
  140. // 取消通过 JavaScript 实现的禁止复制
  141. try { element.onbeforecopy = null; } catch (error) { logError(error); } finally { allowEvent(element, 'beforecopy'); }
  142. try { element.oncopy = null; } catch (error) { logError(error); } finally { allowEvent(element, 'copy'); }
  143. // 取消通过 JavaScript 实现的禁止剪切实现的禁止复制
  144. try { element.onbeforecut = null; } catch (error) { logError(error); } finally { allowEvent(element, 'beforecut'); }
  145. try { element.oncut = null; } catch (error) { logError(error); } finally { allowEvent(element, 'cut'); }
  146. // 取消通过 JavaScript 实现的禁止粘贴
  147. try { element.onbeforepaste = null; } catch (error) { logError(error); } finally { allowEvent(element, 'beforepaste'); }
  148. try { element.onpaste = null; } catch (error) { logError(error); } finally { allowEvent(element, 'paste'); }
  149. // 取消通过 JavaScript 实现的禁止文字选择
  150. try { element.onselectstart = null; } catch (error) { logError(error); } finally { allowEvent(element, 'selectstart'); }
  151. // 取消通过 JavaScript 实现的禁止右键菜单
  152. try { element.oncontextmenu = null; } catch (error) { logError(error); } finally { allowEvent(element, 'contextmenu'); }
  153. // 取消通过 JavaScript 实现的禁止拖动
  154. try { element.ondragstart = null; } catch (error) { logError(error); } finally { allowEvent(element, 'dragstart'); }
  155. try { element.ondragenter = null; } catch (error) { logError(error); } finally { allowEvent(element, 'dragenter'); }
  156. try { element.ondragover = null; } catch (error) { logError(error); } finally { allowEvent(element, 'dragover'); }
  157. try { element.ondragleave = null; } catch (error) { logError(error); } finally { allowEvent(element, 'dragleave'); }
  158. try { element.ondragend = null; } catch (error) { logError(error); } finally { allowEvent(element, 'dragend'); }
  159. // try { element.ondrop = null; } catch (error) { logError(error); } finally { allowEvent(element, 'drop'); }
  160. // 取消通过 CSS 实现的禁止选中
  161. try { element.style.mozUserSelect = 'auto'; } catch (error) { logError(error); } finally { }
  162. try { element.style.webkitUserSelect = 'auto'; } catch (error) { logError(error); } finally { }
  163. try { element.style.msUserSelect = 'auto'; } catch (error) { logError(error); } finally { }
  164. try { element.style.userSelect = 'auto'; } catch (error) { logError(error); } finally { }
  165. // 取消通过 JavaScript 实现的禁用快捷键
  166. try { element.onkeypress = null; } catch (error) { logError(error); } finally { allowKeyEvents(element, 'keypress'); }
  167. try { element.onkeydown = null; } catch (error) { logError(error); } finally { allowKeyEvents(element, 'keydown'); }
  168. try { element.onkeyup = null; } catch (error) { logError(error); } finally { allowKeyEvents(element, 'keyup'); }
  169. // 取消通过 JavaScript 实现的页面离开检测
  170. try { element.onvisibilitychange = null; } catch (error) { logError(error); } finally { allowEvent(element, 'visibilitychange'); }
  171. // 取消通过 JavaScript 实现的鼠标离开检测
  172. // try { element.onmousedown = null; } catch (error) { logError(error); } finally { allowEvent(element, 'mousedown'); }
  173. // try { element.onmouseup = null; } catch (error) { logError(error); } finally { allowEvent(element, 'mouseup'); }
  174. // try { element.onmousewheel = null; } catch (error) { logError(error); } finally { allowEvent(element, 'mousewheel'); }
  175. // try { element.onwheel = null; } catch (error) { logError(error); } finally { allowEvent(element, 'wheel'); }
  176. // try { element.onmouseenter = null; } catch (error) { logError(error); } finally { allowEvent(element, 'mouseenter'); }
  177. // try { element.onmousemove = null; } catch (error) { logError(error); } finally { allowEvent(element, 'mousemove'); }
  178. // try { element.onmouseover = null; } catch (error) { logError(error); } finally { allowEvent(element, 'mouseover'); }
  179. try { element.onmouseout = null; } catch (error) { logError(error); } finally { allowEvent(element, 'mouseout'); }
  180. try { element.onmouseleave = null; } catch (error) { logError(error); } finally { allowEvent(element, 'mouseleave'); }
  181. // 取消通过 JavaScript 实现的指针离开检测
  182. // try { element.ongotpointercapture = null; } catch (error) { logError(error); } finally { allowEvent(element, 'gotpointercapture'); }
  183. try { element.onlostpointercapture = null; } catch (error) { logError(error); } finally { allowEvent(element, 'lostpointercapture'); }
  184. // try { element.onpointerdown = null; } catch (error) { logError(error); } finally { allowEvent(element, 'pointerdown'); }
  185. // try { element.onpointerrawupdate = null; } catch (error) { logError(error); } finally { allowEvent(element, 'pointerrawupdate'); }
  186. try { element.onpointerup = null; } catch (error) { logError(error); } finally { allowEvent(element, 'pointerup'); }
  187. // try { element.onpointerenter = null; } catch (error) { logError(error); } finally { allowEvent(element, 'pointerenter'); }
  188. // try { element.onpointermove = null; } catch (error) { logError(error); } finally { allowEvent(element, 'pointermove'); }
  189. // try { element.onpointerover = null; } catch (error) { logError(error); } finally { allowEvent(element, 'pointerover'); }
  190. try { element.onpointerout = null; } catch (error) { logError(error); } finally { allowEvent(element, 'pointerout'); }
  191. try { element.onpointerleave = null; } catch (error) { logError(error); } finally { allowEvent(element, 'pointerleave'); }
  192. try { element.onpointercancel = null; } catch (error) { logError(error); } finally { allowEvent(element, 'pointercancel'); }
  193. // 取消通过 JavaScript 实现的焦点离开检测
  194. try { element.onfocus = null; } catch (error) { logError(error); } finally { allowEvent(element, 'focus'); }
  195. try { element.onfocusin = null; } catch (error) { logError(error); } finally { allowEvent(element, 'focusin'); }
  196. try { element.onfocusout = null; } catch (error) { logError(error); } finally { allowEvent(element, 'focusout'); }
  197. try { element.onblur = null; } catch (error) { logError(error); } finally { allowEvent(element, 'blur'); }
  198. // 防止 JavaScript 事件检测
  199. preventEventChecks(element);
  200. };
  201. let allowElementRecursion = function (element) {
  202. allowElement(element);
  203. for (let i of element.children) {
  204. allowElementRecursion(i);
  205. }
  206. };
  207. // let removeAllListeners = function (old_element) {
  208. // let new_element = old_element.cloneNode(true);
  209. // old_element.parentNode.replaceChild(new_element, old_element);
  210. // };
  211. let removeHiddenElements = function (element, recursion) {
  212. if ((element.hidden || element.style.display == 'none' || element.style.visibility == 'hidden' || ((element.style.height <= 0 || element.style.width <= 0) && element.style.overflow == 'hidden') && element.children.length <= 0)) {
  213. console.info(`Remove <${element.tagName} id='${element.id}' class='${element.className}' />`);
  214. element.remove();
  215. } else if (recursion) {
  216. for (let i of element.children) {
  217. removeHiddenElements(i, recursion);
  218. }
  219. }
  220. };
  221. let getMainContainerElement = function () {
  222. // 获取正文节点
  223. let main_container_element = null;
  224. if (document) {
  225. if (main_container_element === null) { // 检查 main 标签
  226. let elements = document.getElementsByTagName('main');
  227. if (elements.length > 0) { main_container_element = elements[0]; }
  228. }
  229. if (main_container_element === null) { // 检查 id='main' 的标签
  230. main_container_element = document.getElementById('main');
  231. }
  232. if (main_container_element === null) { // 检查 id='main-content' 的标签
  233. main_container_element = document.getElementById('main-content');
  234. }
  235. if (main_container_element === null) { // 检查 id='main-contents' 的标签
  236. main_container_element = document.getElementById('main-content');
  237. }
  238. if (main_container_element === null) { // 检查 id='content' 的标签
  239. main_container_element = document.getElementById('content');
  240. }
  241. if (main_container_element === null) { // 检查 id='contents' 的标签
  242. main_container_element = document.getElementById('contents');
  243. }
  244. if (main_container_element === null) { // 检查 class='main' 的标签
  245. let elements = document.getElementsByClassName('main');
  246. if (elements.length > 0) { main_container_element = elements[0]; }
  247. }
  248. if (main_container_element === null) { // 检查 class='main-content' 的标签
  249. let elements = document.getElementsByClassName('content');
  250. if (elements.length > 0) { main_container_element = elements[0]; }
  251. }
  252. if (main_container_element === null) { // 检查 class='main-contents' 的标签
  253. let elements = document.getElementsByClassName('content');
  254. if (elements.length > 0) { main_container_element = elements[0]; }
  255. }
  256. if (main_container_element === null) { // 检查 class='content' 的标签
  257. let elements = document.getElementsByClassName('content');
  258. if (elements.length > 0) { main_container_element = elements[0]; }
  259. }
  260. if (main_container_element === null) { // 检查 class='contents' 的标签
  261. let elements = document.getElementsByClassName('contents');
  262. if (elements.length > 0) { main_container_element = elements[0]; }
  263. }
  264. }
  265. return main_container_element;
  266. };
  267.  
  268. // 对抗延迟运行(即在此脚本执行后运行)的禁用程序和循环执行的禁用程序,
  269. executeWithInterval( // 每 0.2 秒执行一次。
  270. (function () {
  271. if (document) {
  272. try { allowElement(document); } catch (error) { logError(error); } finally { }
  273. }
  274. }), 200
  275. );
  276. executeWithInterval( // 每 0.3 秒执行一次。
  277. (function () {
  278. if (document) {
  279. try { allowElement(document.body); } catch (error) { logError(error); } finally { }
  280. }
  281. }), 300
  282. );
  283. executeWithInterval( // 每 2.0 秒执行一次。
  284. (function () {
  285. let mce = getMainContainerElement()
  286. if (document && mce) {
  287. try { allowElementRecursion(mce); } catch (error) { logError(error); } finally { }
  288. }
  289. }), 2000
  290. );
  291.  
  292. // 对抗延迟运行(即在此脚本执行后运行)的混淆程序和循环执行的混淆程序,
  293. setTimeout(
  294. // 延迟 1.0 秒,有助于动态加载的内容的显示。
  295. function () {
  296. executeWithInterval(
  297. // 每 3.0 秒执行一次。
  298. function () {
  299. if (document) {
  300. // 移除正文中的不可见元素
  301. try {
  302. let mce = getMainContainerElement();
  303. // 移除不可见元素
  304. if (mce) {
  305. removeHiddenElements(mce, true);
  306. }
  307. } catch (error) { logError(error); } finally { }
  308. }
  309. }, 3000
  310. );
  311. }, 1000
  312. )
  313.  
  314. if (in_frame) {
  315. console.debug('Complete the installation of user-script/remove-limits (IN-FRAME)');
  316. } else {
  317. console.info('Complete the installation of user-script/remove-limits');
  318. }
  319. })();

QingJ © 2025

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