gm4-polyfill-1.0.1

Polyfill for backward compatibilty of GM functions

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/375359/652238/gm4-polyfill-101.js

  1. /* gm4-polyfill.js v1.0.1 */
  2.  
  3. // ==UserLibrary==
  4. // @pseudoHeader
  5. // @version 1.0.1
  6. // @name GM4 PolyFill
  7. // ==/UserLibrary==
  8.  
  9. /* This helper script bridges backwardly compatibility between the Greasemonkey 4 APIs and
  10. existing/legacy APIs. Say for example your user script includes
  11. // @grant GM_getValue
  12. And you'd like to be compatible with both Greasemonkey 3 and Greasemonkey 4
  13. (and for that matter all versions of Violentmonkey, Tampermonkey, and any other
  14. user script engine). Add:
  15. // @grant GM.getValue
  16. // @require https://raw.githubusercontent.com/SloaneFox/code/master/gm4-polyfill.js
  17. Eg, this will define GM.getValue in older GM versions, so updated code will be backward compatible
  18. to older GM versions. It will not define GM_getValue in newer GM versions.
  19. Missing functions from the new GM api are added, hence GM.registerMenuCommand and GM.addStyle are defined.
  20.  
  21. Include above and recode userscript to the new (GM-dot) APIs, which return promises. If your script
  22. is running in an engine that does not provide the new asynchronous APIs, this
  23. helper will add them, based on the old APIs.
  24. If you use `await` at the top level, you'll need to wrap your script in an
  25. `async` function to be compatible with any user script engine besides
  26. Greasemonkey 4.
  27. var gValue;
  28. async function init_globals() { gValue = await GM.getValue('x'); }
  29. async main() { await init_globals(); }
  30. addEventListener("load",main);
  31.  
  32. */
  33. if (typeof GM == 'undefined')
  34. eval("var GM = {};"); // Defined in the closure given when loaded/injected prevents intra-script clobbering. Eval needed due to GM's declaration as a const in scope wrapper .
  35.  
  36.  
  37. if (typeof GM_addStyle == 'undefined') {
  38. this.GM_addStyle = (aCss) => {
  39. 'use strict';
  40. let head = document.getElementsByTagName('head')[0];
  41. if (head) {
  42. let style = document.createElement('style');
  43. style.setAttribute('type', 'text/css');
  44. style.textContent = aCss;
  45. head.appendChild(style);
  46. return style;
  47. }
  48. return null;
  49. };
  50. }
  51. GM.addStyle=this.GM_addStyle;
  52.  
  53. if (typeof GM_getResourceText == 'undefined')
  54. this.GM_getResourceText = async aResourceName =>
  55. ( await fetch(await GM.getResourceUrl(aResourceName)) ).text();
  56.  
  57. if (typeof GM_registerMenuCommand=="function" && /is not supported[^]{0,100}$/.test(GM_registerMenuCommand.toString()))
  58. GM_registerMenuCommand=undefined;
  59.  
  60. GM.registerMenuCommand = function (caption, commandFunc, accessKey) {
  61. let body=document.body;
  62. if (!body) throw "GM registerMenuCommand aint got no body in document, call again later.";
  63. let contextMenu = body.getAttribute('contextmenu');
  64. let menu = (contextMenu ? document.querySelector('menu#' + contextMenu) : null);
  65. if (!menu) {
  66. menu = document.createElement('menu');
  67. menu.setAttribute('id', 'gm-registered-menu');
  68. menu.setAttribute('type', 'context');
  69. body.insertBefore(menu,body.firstChild);
  70. body.setAttribute('contextmenu', 'gm-registered-menu');
  71. }
  72. let menuItem = document.createElement('menuitem');
  73. menuItem.setAttribute("label",caption);
  74. menuItem.addEventListener('click', commandFunc, true);
  75. menu.appendChild(menuItem);
  76. return menuItem; // The real GM_registerMenuCommand returns undefined. Here user can change eg, label attribute of returned menuItem.
  77. };
  78.  
  79. if (typeof GM_registerMenuCommand == 'undefined') this.GM_registerMenuCommand=GM.registerMenuCommand;
  80.  
  81. Object.entries({
  82. 'log': console.log.bind(console),
  83. 'info': typeof GM_info == "undefined" ? null : GM_info
  84. }).forEach(([newKey, old]) => {
  85. if (old && (typeof GM[newKey] == 'undefined')) {
  86. GM[newKey] = old;
  87. }
  88. });
  89.  
  90. Object.entries({ // Object.entries() returns a 2-d array of all the given object's name value pairs.
  91. 'GM_addStyle': 'addStyle',
  92. 'GM_deleteValue': 'deleteValue',
  93. 'GM_getResourceURL': 'getResourceUrl',
  94. 'GM_getValue': 'getValue',
  95. 'GM_listValues': 'listValues',
  96. 'GM_notification': 'notification',
  97. 'GM_openInTab': 'openInTab',
  98. 'GM_registerMenuCommand': 'registerMenuCommand',
  99. 'GM_setClipboard': 'setClipboard',
  100. 'GM_setValue': 'setValue',
  101. 'GM_xmlhttpRequest': 'xmlHttpRequest',
  102. 'GM_getResourceText': 'getResourceText'
  103. }).forEach(([oldKey, newKey]) => { // Enables eg, "await GM.getValue" to run ok on pre GM4. But not vice versa, ie, it defines no GM_getValue in newer GM.
  104. let old = this[oldKey];
  105. if (old && (typeof GM[newKey] == 'undefined')) {
  106. GM[newKey] = function(...args) {
  107. return new Promise(function(resolve, reject) { try {
  108. resolve(old.apply(this, args));
  109. } catch (e) { reject(e); }
  110. });
  111. };//GM[newKey]=func
  112. }
  113. });//forEach()
  114.  
  115.  

QingJ © 2025

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