GreasyFork script icon

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

Fra 18.11.2019. Se den seneste versjonen.

  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.5
  7. // @author wOxxOm
  8. // @match https://greatest.deepsurf.us/*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. /* jshint lastsemic:true, multistr:true, laxbreak:true, -W030, -W041, -W084 */
  19.  
  20. var scriptID = location.href.match(/scripts\/(\d+)/)[1];
  21. var iconsrc = GM_getValue(scriptID);
  22.  
  23. if (iconsrc && iconsrc.match(/^data:image|https:/))
  24. addIcon();
  25. else {
  26. GM_xmlhttpRequest({
  27. method: 'GET',
  28. url: location.href.replace(/(scripts\/\d+[^/]+)(\/.*)?$/,'$1/code/1.user.js'),
  29. timeout: 10000,
  30. onload: function (r) {
  31. var m = r.responseText.match(/\n\s*\/\/\s+@icon(?:url)?\s+(https?|data)(:(?:\/\/|image).*?)[\s\r\n]/i);
  32. if (!m)
  33. return;
  34.  
  35. if (m[1] == 'https' || m[1] == 'data')
  36. return addIcon(m[1]+m[2]);
  37.  
  38. // download http icon and store it in script db if it's small
  39. GM_xmlhttpRequest({
  40. method: 'GET',
  41. url: m[1]+m[2],
  42. timeout: 10000,
  43. headers: {'Accept':'image/png,image/*;q=0.8,*/*;q=0.5'},
  44. overrideMimeType: 'text\/plain; charset=x-user-defined',
  45. onload: function(ri) {
  46. var rb = ri.response, rbl = rb.length;
  47. if (rbl > 100000) {
  48. console.log('Script icon exceeds 100k, ignoring');
  49. return;
  50. }
  51.  
  52. var ext = ri.finalUrl.substr(ri.finalUrl.lastIndexOf('.')+1).toLowerCase();
  53. var mime = ['png','bmp','gif'].indexOf(ext) >= 0 ? ext : ext.match(/'^jpe?g?/) ? 'jpeg' : ext=='ico' ? 'x-icon' : null;
  54. if (!mime)
  55. return;
  56.  
  57. var rb8 = new Uint8Array(rbl);
  58. for (var i=0; i<rbl; i++)
  59. rb8[i] = rb.charCodeAt(i);
  60. var rbs = String.fromCharCode.apply(null, rb8);
  61.  
  62. addIcon('data:image/' + mime + ';base64,' + btoa(rbs));
  63. }
  64. });
  65. }
  66. });
  67. }
  68.  
  69. function addIcon(url) {
  70. if (url)
  71. iconsrc = url;
  72.  
  73. var h2 = document.querySelector('#script-info header h2');
  74. h2 ? __add(h2) : __wait();
  75.  
  76. function __add(h2) {
  77. if (!h2)
  78. if (!(h2 = document.querySelector('#script-info header h2')))
  79. return;
  80.  
  81. h2.insertAdjacentHTML('afterbegin','<div style="\
  82. position: absolute;\
  83. width: 80px;\
  84. margin-left: calc(-80px - 1ex);\
  85. display: inline-block;\
  86. text-align: right"></div>');
  87. var img = h2.firstChild.appendChild(document.createElement('img'));
  88. img.style.maxWidth = img.style.maxHeight = '64px';
  89. img.style.width = img.style.height = 'auto';
  90. img.src = iconsrc;
  91.  
  92. GM_setValue(scriptID, iconsrc);
  93. }
  94.  
  95. function __wait() {
  96. var ob = new MutationObserver(function(mutations){
  97. for (var i=0, ml=mutations.length, m; (i<ml) && (m=mutations[i]); i++) {
  98. if (m.target.localName == 'h2') {
  99. __add();
  100. ob.disconnect();
  101. return;
  102. }
  103. }
  104. });
  105. ob.observe(document, {subtree:true, childList:true});
  106. }
  107. }