GreasyFork: download script button

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

Verze ze dne 30. 01. 2021. Zobrazit nejnovější verzi.

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