GreasyFork script icon

On a script info page it shows its icon from the script meta block

  1. // ==UserScript==
  2. // @name GreasyFork script icon
  3. // @namespace wOxxOm.scripts
  4. // @description On a script info page it shows its icon from the script meta block
  5. // @icon https://icons.iconarchive.com/icons/custom-icon-design/mono-general-1/64/information-icon.png
  6. // @version 1.1.7
  7. // @author wOxxOm
  8. // @match https://gf.qytechs.cn/*scripts/*
  9. // @include /^https://(sleazy)fork.org/.*?scripts/.*?/
  10. // @exclude /^https://(greasy|sleazy)fork\.org/([^/]+/)?scripts/(\D|$)/
  11. // @run-at document-start
  12. // @connect-src *
  13. // @grant GM_xmlhttpRequest
  14. // @grant GM_setValue
  15. // @grant GM_getValue
  16. // ==/UserScript==
  17.  
  18. var scriptID = location.href.match(/scripts\/(\d+)/)[1];
  19. var iconsrc = GM_getValue(scriptID);
  20.  
  21. if (iconsrc && iconsrc.match(/^data:image|https:/))
  22. addIcon();
  23. else {
  24. GM_xmlhttpRequest({
  25. method: 'GET',
  26. url: location.pathname.replace(/(scripts\/\d+[^/]+)(\/.*)?$/,'$1/code/1.user.js'),
  27. timeout: 10000,
  28. onload: function (r) {
  29. var url = (r.responseText.match(/\n\s*\/\/\s+@icon(?:url)?\s+((?:https?:\/\/|data:image\/).+)|$/i)[1] || '').trim();
  30. if (!url)
  31. return;
  32. if (!/^http:/.test(url))
  33. return addIcon(url);
  34. // download http icon and store it in script db if it's small
  35. GM_xmlhttpRequest({
  36. method: 'GET',
  37. url: url,
  38. timeout: 10000,
  39. headers: {'Accept':'image/png,image/*;q=0.8,*/*;q=0.5'},
  40. responseType: 'arraybuffer',
  41. onload: function(ri) {
  42. var /**@type ArrayBuffer*/rb = ri.response, rbl = rb.byteLength;
  43. if (rbl > 100000) {
  44. console.log('Script icon exceeds 100k, ignoring');
  45. return;
  46. }
  47. var mime = ri.responseHeaders.match(/(^|\n\s*)Content-Type:\s*(image\/[^;,\s]+)|$/i)[2];
  48. var rb8 = new Uint8Array(rb);
  49. var rbs = Array(rbl);
  50. for (var i=0; i<rbl; i++)
  51. rbs[i] = String.fromCharCode(rb8[i]);
  52. addIcon('data:image/' + (mime || 'png') + ';base64,' + btoa(rbs.join('')));
  53. }
  54. });
  55. }
  56. });
  57. }
  58.  
  59. function addIcon(url) {
  60. if (url)
  61. iconsrc = url;
  62.  
  63. var h2 = document.querySelector('#script-info header h2');
  64. h2 ? __add(h2) : __wait();
  65.  
  66. function __add(h2) {
  67. if (!h2)
  68. if (!(h2 = document.querySelector('#script-info header h2')))
  69. return;
  70.  
  71. h2.insertAdjacentHTML('afterbegin','<div style="\
  72. position: absolute;\
  73. width: 80px;\
  74. margin-left: calc(-80px - 1ex);\
  75. display: inline-block;\
  76. text-align: right"></div>');
  77. var img = h2.firstChild.appendChild(document.createElement('img'));
  78. img.style.maxWidth = img.style.maxHeight = '64px';
  79. img.style.width = img.style.height = 'auto';
  80. img.src = iconsrc;
  81.  
  82. GM_setValue(scriptID, iconsrc);
  83. }
  84.  
  85. function __wait() {
  86. var ob = new MutationObserver(function(mutations){
  87. for (var i=0, ml=mutations.length, m; (i<ml) && (m=mutations[i]); i++) {
  88. if (m.target.localName == 'h2') {
  89. __add();
  90. ob.disconnect();
  91. return;
  92. }
  93. }
  94. });
  95. ob.observe(document, {subtree:true, childList:true});
  96. }
  97. }

QingJ © 2025

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