Greasy Fork is available in English.

GreasyFork: download script button

If you have a script manager and you want to download some script without installing it, this script will help

2021-01-29 يوللانغان نەشرى. ئەڭ يېڭى نەشرىنى كۆرۈش.

  1. // ==UserScript==
  2. // @name GreasyFork: download script button
  3. // @description If you have a script manager and you want to download some script without installing it, this script will help
  4. // @namespace https://greatest.deepsurf.us/users/424058
  5. // @version 1.0.0
  6. // @author Konf
  7. // @include /^http(s|):\/\/greatest.deepsurf.us\/[a-zA-Z_-]*\/scripts\/\d.*$/
  8. // @run-at document-end
  9. // @resource iconDownload https://img.icons8.com/pastel-glyph/64/ffffff/download.png
  10. // @compatible Chrome
  11. // @compatible Opera
  12. // @compatible Firefox
  13. // @grant GM_getResourceUrl
  14. // @grant GM.getResourceUrl
  15. // @noframes
  16. // ==/UserScript==
  17.  
  18. /* jshint esversion: 6 */
  19. /* eslint-disable no-multi-spaces */
  20.  
  21. (function() {
  22. 'use strict';
  23.  
  24. (GM.getResourceUrl || GM_getResourceUrl)('iconDownload')
  25. .then(downloadIconUrl => {
  26. addCSS(`
  27. .tm-dsb-downloadBtn {
  28. width: 43px;
  29. height: 38px;
  30. position: relative;
  31. padding: 0;
  32. vertical-align: bottom;
  33. cursor: pointer;
  34. border: none;
  35. outline: none;
  36. background: #0F750F;
  37. transition: box-shadow 0.2s;
  38. }
  39.  
  40. .tm-dsb-downloadBtn:hover,
  41. .tm-dsb-downloadBtn:focus {
  42. box-shadow: 0 8px 16px 0 rgb(0 0 0 / 20%), 0 6px 20px 0 rgb(0 0 0 / 19%);
  43. }
  44.  
  45.  
  46. .tm-dsb-downloadBtn__icon {
  47. position: absolute;
  48. }
  49.  
  50. .tm-dsb-downloadBtn__icon--download {
  51. width: 35px;
  52. height: 35px;
  53. top: 1px;
  54. left: 4px;
  55. background: url(${downloadIconUrl});
  56. background-size: contain;
  57. }
  58.  
  59. .tm-dsb-downloadBtn__icon--loading,
  60. .tm-dsb-downloadBtn__icon--loading:after {
  61. border-radius: 50%;
  62. width: 16px;
  63. height: 16px;
  64. }
  65.  
  66. .tm-dsb-downloadBtn__icon--loading {
  67. top: 6px;
  68. left: 8px;
  69. text-indent: -9999em;
  70. border-top: 5px solid rgba(255, 255, 255, 0.2);
  71. border-right: 5px solid rgba(255, 255, 255, 0.2);
  72. border-bottom: 5px solid rgba(255, 255, 255, 0.2);
  73. border-left: 5px solid #ffffff;
  74. -webkit-transform: translateZ(0);
  75. -ms-transform: translateZ(0);
  76. transform: translateZ(0);
  77. -webkit-animation: loading 1.1s infinite linear;
  78. animation: loading 1.1s infinite linear;
  79. }
  80.  
  81. @-webkit-keyframes loading {
  82. 0% {
  83. -webkit-transform: rotate(0deg);
  84. transform: rotate(0deg);
  85. }
  86. 100% {
  87. -webkit-transform: rotate(360deg);
  88. transform: rotate(360deg);
  89. }
  90. }
  91.  
  92. @keyframes loading {
  93. 0% {
  94. -webkit-transform: rotate(0deg);
  95. transform: rotate(0deg);
  96. }
  97. 100% {
  98. -webkit-transform: rotate(360deg);
  99. transform: rotate(360deg);
  100. }
  101. }
  102. `);
  103. });
  104.  
  105. const userLang = location.pathname.split('/')[1];
  106. const langStringsList = {
  107. en: {
  108. Dl: 'Download without installing',
  109. unableDl: 'Unable to download the script'
  110. },
  111. ru: {
  112. Dl: 'Скачать не устанавливая',
  113. unableDl: 'Не удалось скачать скрипт'
  114. }
  115. };
  116. const langStrings = langStringsList[userLang] || langStringsList.en;
  117.  
  118. const b = document.createElement('button'); // downloadBtn
  119. const bIcon = document.createElement('div');
  120. const bParent = document.body.querySelector('div#install-area');
  121. const bNeighbour = document.body.querySelector('a.install-help-link');
  122. const installBtn = document.body.querySelector('a.install-link');
  123.  
  124. b.title = langStrings.Dl;
  125. b.className = 'tm-dsb-downloadBtn';
  126. bIcon.className = 'tm-dsb-downloadBtn__icon tm-dsb-downloadBtn__icon--download';
  127. bParent.insertBefore(b, bNeighbour);
  128. b.appendChild(bIcon);
  129.  
  130. let fetchingDelay = false;
  131.  
  132. b.addEventListener('click', () => {
  133. setTimeout(() => {
  134. if (b === document.activeElement) document.activeElement.blur();
  135. }, 750);
  136.  
  137. if (fetchingDelay) return;
  138. fetchingDelay = true;
  139. bIcon.className = 'tm-dsb-downloadBtn__icon tm-dsb-downloadBtn__icon--loading';
  140.  
  141. fetch(installBtn.href)
  142. .then(res => res.blob())
  143. .then(blob => {
  144. const url = window.URL.createObjectURL(blob);
  145. const a = document.createElement('a');
  146.  
  147. a.href = url;
  148. a.download = `${installBtn.dataset.scriptName}.user.js`;
  149. document.body.appendChild(a); // needed due to firefox bug
  150. a.click();
  151. a.remove();
  152.  
  153. setTimeout(closeFetchUX, 300);
  154. window.URL.revokeObjectURL(url);
  155. })
  156. .catch(e => {
  157. setTimeout(closeFetchUX, 300);
  158. alert(`${langStrings.unableDl}: \n${e}`);
  159. });
  160. });
  161.  
  162.  
  163. // utils -------------------------------------------------------------
  164.  
  165. function closeFetchUX() {
  166. fetchingDelay = false;
  167. bIcon.className = 'tm-dsb-downloadBtn__icon tm-dsb-downloadBtn__icon--download';
  168. }
  169.  
  170. function addCSS(cssCode) {
  171. const styleEl = document.createElement("style");
  172. styleEl.type = "text/css";
  173.  
  174. if (styleEl.styleSheet) {
  175. styleEl.styleSheet.cssText = cssCode;
  176. } else {
  177. styleEl.appendChild(document.createTextNode(cssCode));
  178. }
  179.  
  180. document.getElementsByTagName("head")[0].appendChild(styleEl);
  181.  
  182. return styleEl;
  183. }
  184.  
  185. // --------------------------------------------------------------------
  186.  
  187. })();