Skip to content

Instantly share code, notes, and snippets.

@TheEpicFace007
Last active May 30, 2021 01:44
Show Gist options
  • Save TheEpicFace007/9d88c08eee2c9681d2dc86350a1d6b97 to your computer and use it in GitHub Desktop.
Save TheEpicFace007/9d88c08eee2c9681d2dc86350a1d6b97 to your computer and use it in GitHub Desktop.
Add some quality of life improvement feature on npm
// ==UserScript==
// @name NPM Quality of life changes
// @namespace http://tampermonkey.net/
// @version 0.1
// @description Add some quality of life improvenet to npm
// @author You
// @match http**://www.npmjs.com/**
// @grant none
// ==/UserScript==
function showNotif(notifText) {
const copyNotifHTML = `<div class="ts-copy-notif ee9e731a pa3 ph5-ns bb b--black-10 tl pointer z-999 w-100 flex flex-row justify-between d76ab310">
<p class="ma0">${notifText}</p>
<p aria-label="Close notification" class="_545224b8 ma0 f3 fw6">×</p>
</div>`;
const notifSpot = document.querySelector("#app > div > div:nth-child(1) > ul")
notifSpot.insertAdjacentHTML("beforeend", copyNotifHTML);
setTimeout(() => {
notifSpot.lastChild.remove()
}, 1500)
}
if (document.location.pathname.search("package") >= 0) {
setTimeout(() => {
'use strict';
const $ = document.querySelector;
// if the page is a pakcage
if (document.location.pathname.search("package") >= 0) {
// If it has definitly type typedef
const hasDefinitlyTypedTypedef =
document.querySelector("#top > div.w-100.ph0-l.ph3.ph4-m > h2 > div > a > img") ? true : false;
const hasTypescrptTypedefIncluded =
document.querySelector("#top > div.w-100.ph0-l.ph3.ph4-m > h2 > div > img") ? true : false;
const packageName = document.querySelector("#top > div.w-100.ph0-l.ph3.ph4-m > h2 > span").innerText;
const packageInfo = document.querySelector("#top > div.fdbf4038.w-third-l.mt3.w-100.ph3.ph4-m.pv3.pv0-l.order-1-ns.order-0");
// change the text of the license so u know if it has license or not
if (!document.querySelector("#top > div.fdbf4038.w-third-l.mt3.w-100.ph3.ph4-m.pv3.pv0-l.order-1-ns.order-0 > div:nth-child(5) > h3") &&
document.querySelector("#top > div.fdbf4038.w-third-l.mt3.w-100.ph3.ph4-m.pv3.pv0-l.order-1-ns.order-0 > div:nth-child(5) > p"))
throw new ReferenceError("Couldn't find the required text to change the license text")
document.querySelector("#top > div.fdbf4038.w-third-l.mt3.w-100.ph3.ph4-m.pv3.pv0-l.order-1-ns.order-0 > div:nth-child(5) > h3").innerText =
"Typescript compatible?";
document.querySelector("#top > div.fdbf4038.w-third-l.mt3.w-100.ph3.ph4-m.pv3.pv0-l.order-1-ns.order-0 > div:nth-child(5) > p").innerText =
hasDefinitlyTypedTypedef || hasTypescrptTypedefIncluded ? "✔️" : "❌";
const installPackageText = document.querySelector("#top > div.fdbf4038.w-third-l.mt3.w-100.ph3.ph4-m.pv3.pv0-l.order-1-ns.order-0 > p > code > span").innerText;
document.querySelector("#top > div.fdbf4038.w-third-l.mt3.w-100.ph3.ph4-m.pv3.pv0-l.order-1-ns.order-0 > p > code > span").innerText
= installPackageText.replace("npm i", "yarn add")
if (hasDefinitlyTypedTypedef) {
const copyButtonHtml = `<p id="copy-typedef-cmd" class="d767adf4 lh-copy ts-copy truncate ph0 mb3 black-80 b5be2af6 f6 flex flex-row"><svg viewBox="0 0 12.32 9.33">
<g>
<line class="st1" x1="7.6" y1="8.9" x2="7.6" y2="6.9"></line>
<rect width="1.9" height="1.9"></rect>
<rect x="1.9" y="1.9" width="1.9" height="1.9"></rect>
<rect x="3.7" y="3.7" width="1.9" height="1.9"></rect>
<rect x="1.9" y="5.6" width="1.9" height="1.9"></rect>
<rect y="7.5" width="1.9" height="1.9"></rect>
</g>
</svg><code class="flex-auto truncate db" title="Copy Command to Clipboard"><span>yarn add --dev @types/${packageName}</span></code><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">
<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>
</svg></p>`
const copyTypedef = packageInfo.lastElementChild;
packageInfo.insertAdjacentHTML("afterBegin", copyButtonHtml);
document.getElementById("copy-typedef-cmd").onclick = () => {
navigator.clipboard.writeText(`yarn add --dev @types/${packageName}`);
showNotif("✔ Copied to clipboard!")
}
packageInfo.insertAdjacentHTML("afterbegin", '<h3 class="c84e15be f5 mt2 pt2 mb0">Install type definition</h3>')
}
}
document.body.insertAdjacentHTML("afterBegin", `
<style>
.ts-copy:hover {
border-color: rgb(0, 122, 204) !important;
background-color: #007acc15 !important;
}
</style>
`)
}, 200);
}
else if (document.location.pathname == "/search") {
setTimeout(() => {
document.querySelector("#search > div > fieldset > div:nth-child(4)").insertAdjacentHTML("afterend",
`<label for="search_ranking_typescript" class="_9d16cd42 lh-copy"><input type="radio" class="_128f502f mr2"
aria-label="Sort Packages Typescript" name="ranking" id="search_ranking_typescript" value="typescript">
<div><b>Typescript</b><br></div>
</label>`);
const typescriptSorter = document.querySelector("._9390ec46 label[for='search_ranking_typescript'] ")
let iteration = 1n;
typescriptSorter.addEventListener("click", () => {
if (iteration % 2n !== 0n) {
typescriptSorter.classList.toggle("selected")
console.log('typescriptSorter.classList.contains("selected")', typescriptSorter.classList.contains("selected"))
if (typescriptSorter.classList.contains("selected")) {
showNotif("\u2026 Filtering out all non typescript compatible package")
filterSearchResult("typescript")
.then(() => showNotif("\u2713 Finished filtering the non typescript comptabile package"))
.catch(() => showNotif("\u2718 Error while filtering the non typescript package"));;
}
else {
showNotif("\u2026 Showing all packages")
filterSearchResult("all")
.then(() => showNotif("\u2713 Finished showing all package"))
.catch(() => showNotif("\u2718 Error while showing all package"))
}
}
iteration++;
})
document.body.insertAdjacentHTML("afterbegin", `
<style>
._9390ec46 label[for='search_ranking_typescript'] {
animation: all 0.5s linear;
border-bottom: 1.5px solid #007ACC;
}
._9390ec46 label[for='search_ranking_typescript'].selected {
color: black;
animation: all 0.5s linear;
}
.show {
transition: opacity 400ms;
}
.hide {
opacity: 0;
}
</style>
`)
}, 100);
let hedElement = [];
/**
* @param {"all" | "typescript"} filter
*/
async function filterSearchResult(filter) {
const fadeInDuration = 600;
if (filter == "typescript") {
const promises = []
for (let i = 0; i <= 20; i++) {
const module = document.querySelector("#main > div._23fffac0.w-100.mw9.ph5-ns.ph3-l.ph1-m.mh3-ns.center.center-ns.flex.flex-column.flex-row-l.justify-between > div > section:nth-child(" + i + ")");
if (module) {
/** @type {string} */
const moduleLink = module.firstElementChild.firstElementChild.href ?? module.firstElementChild.firstElementChild.firstElementChild.href;
fetch(moduleLink).then(async (res) => {
const text = await res.text();
if (text.search("TypeScript") < 0) {
fadeOut(module, fadeInDuration)
hedElement.push(module)
console.log("Hiding non typescript module")
}
else {
console.log("Keeping the typescript module")
}
})
.catch(console.error);
}
}
}
else {
for (const element of hedElement) {
fadeIn(element, fadeInDuration)
}
hedElement = [];
}
}
}
function fadeIn(elem, ms) {
if (!elem)
return;
elem.style.opacity = 0;
elem.style.filter = "alpha(opacity=0)";
elem.style.display = ""
if (ms) {
var opacity = 0;
var timer = setInterval(function () {
opacity += 50 / ms;
if (opacity >= 1) {
clearInterval(timer);
opacity = 1;
}
elem.style.opacity = opacity;
elem.style.filter = "alpha(opacity=" + opacity * 100 + ")";
}, 50);
}
else {
elem.style.opacity = 1;
elem.style.filter = "alpha(opacity=1)";
}
}
function fadeOut(elem, ms) {
if (!elem)
return;
if (ms) {
var opacity = 1;
var timer = setInterval(function () {
opacity -= 50 / ms;
if (opacity <= 0) {
clearInterval(timer);
opacity = 0;
elem.style.display = "none";
}
elem.style.opacity = opacity;
elem.style.filter = "alpha(opacity=" + opacity * 100 + ")";
}, 50);
}
else {
elem.style.opacity = 0;
elem.style.filter = "alpha(opacity=0)";
elem.style.display = "none";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment