NPM - More Install Button

Allows you to add more install buttons.

  1. // ==UserScript==
  2. // @name NPM - More Install Button
  3. // @namespace armagan.rest
  4. // @match http*://www.npmjs.com/*
  5. // @grant none
  6. // @version 0.2.1
  7. // @author Kıraç Armağan Önal
  8. // @description Allows you to add more install buttons.
  9. // @run-at document-end
  10. // ==/UserScript==
  11.  
  12. (() => {
  13.  
  14. // Add your buttons to here!
  15. const buttons = Object.freeze(
  16. [
  17. ({moduleName, moduleVersion})=>{
  18. return `yarn add ${moduleName}@${moduleVersion}`;
  19. },
  20. ({moduleName, moduleVersion})=>{
  21. return `yarn add --dev ${moduleName}@${moduleVersion}`;
  22. },
  23. ({moduleName, moduleVersion})=>{
  24. return `yarn global add ${moduleName}@${moduleVersion}`;
  25. },
  26. ({ moduleName, hasDeclarations, declarationsModuleName, moduleVersion }) => {
  27. if (moduleName.startsWith("@types/")) return;
  28. return hasDeclarations ? `yarn add --dev @types/${declarationsModuleName}@${moduleVersion}` : null;
  29. },
  30. ({ moduleName, hasDeclarations, declarationsModuleName, moduleVersion }) => {
  31. if (moduleName.startsWith("@types/")) return;
  32. return hasDeclarations ? `yarn add ${moduleName} && yarn add --dev @types/${declarationsModuleName}@${moduleVersion}` : null;
  33. }
  34. ].reverse()
  35. );
  36.  
  37. function appendStyle(style = "") {
  38. let element = document.createElement("style");
  39. element.innerHTML = style;
  40. document.head.appendChild(element);
  41. }
  42.  
  43. function copyToClipboard(text = "") {
  44. let element = document.createElement("textarea");
  45. element.value = text;
  46. element.setAttribute("style", `position:absolute;top:0;left:0;opacity:0;z-index:9999999999;`);
  47. document.body.prepend(element);
  48. element.focus({ preventScroll: true });
  49. element.select();
  50. document.execCommand("copy", false, false);
  51. element.remove();
  52. }
  53.  
  54. function createCopyElement(text = "") {
  55. let element = document.createElement("p");
  56. element.className = "d767adf4 lh-copy truncate ph0 mb3 black-80 b5be2af6 f6 flex flex-row mib-container";
  57. element.innerHTML = `
  58. <svg viewBox="0 0 12.32 9.33">
  59. <g>
  60. <line class="st1" x1="7.6" y1="8.9" x2="7.6" y2="6.9"></line>
  61. <rect width="1.9" height="1.9"></rect>
  62. <rect x="1.9" y="1.9" width="1.9" height="1.9"></rect>
  63. <rect x="3.7" y="3.7" width="1.9" height="1.9"></rect>
  64. <rect x="1.9" y="5.6" width="1.9" height="1.9"></rect>
  65. <rect y="7.5" width="1.9" height="1.9"></rect>
  66. </g>
  67. </svg>
  68. <code class="flex-auto truncate db" title="Copy Command to Clipboard">
  69. <span>${text}</span>
  70. </code>
  71. <svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="copy" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
  72. <path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"></path>
  73. </svg>
  74. `
  75. element.addEventListener("click", () => {
  76. copyToClipboard(text);
  77. element.classList.add("mib-copied");
  78. setTimeout(() => {
  79. element.classList.remove("mib-copied");
  80. }, 100);
  81. });
  82. return element;
  83. }
  84.  
  85. appendStyle(`
  86. .mib-container span {
  87. text-overflow: ellipsis;
  88. white-space: nowrap;
  89. overflow: hidden;
  90. }
  91.  
  92. .mib-container svg {
  93. transition: transform 100ms ease-in-out !important;
  94. }
  95. .mib-copied svg {
  96. transform: scale(1.5) !important;
  97. }
  98. `);
  99.  
  100. window.createCopyElement = createCopyElement;
  101.  
  102. let mem = { _moduleName: null };
  103.  
  104. setInterval(() => {
  105. let moduleName = document.querySelector("#top h2.no-underline [title]")?.title;
  106. let moduleVersion = document.querySelector("span.f6.dib.ph0.pv2.mb2-ns.black-80.nowrap.f5.fw4.lh-copy")?.textContent?.split(" ")?.[0];
  107.  
  108. if (`${moduleName}@${moduleVersion}` != mem._moduleName) {
  109. console.log(moduleName)
  110. mem._moduleName = `${moduleName}@${moduleVersion}`;
  111. let originalButton = document.querySelector(`[title*="Copy Command"]`);
  112. let buttonContainer = originalButton?.parentNode?.parentNode;
  113. originalButton.remove();
  114. if (!buttonContainer) return;
  115. console.log(buttonContainer);
  116. let locationSplitted = window.location.href.split("/");
  117. let hasDeclarations = !!document.querySelector(`#top h2.no-underline [title*="This package has TypeScript"]`);
  118. let declarationsModuleName = hasDeclarations ? moduleName.replace("@","").replace("/","__") : null;
  119. buttons.forEach(buttonTextFunction => {
  120. let text = buttonTextFunction({ moduleName, hasDeclarations, declarationsModuleName, moduleVersion });
  121. if (!text) return;
  122. console.log(text)
  123. let element = createCopyElement(text);
  124. console.log(element);
  125. buttonContainer.insertBefore(element, buttonContainer.children[1]);
  126. });
  127. }
  128. }, 250);
  129.  
  130. })();

QingJ © 2025

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