diff --git a/js/main.js b/js/main.js index 9a8b64f..c476897 100644 --- a/js/main.js +++ b/js/main.js @@ -1,20 +1,20 @@ "use strict"; -const ForksDiff = (() => { - // Icons - const starIcon = - ''; - const forkIcon = - ''; - const loadingIcon = - ''; +window._forksdiffconstants = { + icons: { + loading: + '', - // Regex - const diffRegex = - /
[\S\s]*?This branch is[\S\s]*?((?[0-9]*) commits? ahead[\S\s]*?(?[0-9]*) commits? behind|(?[0-9]*) commits? behind|(?[0-9]*) commits? ahead)/; - const starsRegex = /([0-9]+) users? starred this repository/; - const githubUrlRegex = /https?:\/\/github\.com\/.*\/network\/members/; + star: '', + fork: '', + }, + regex: { + diff: /
[\S\s]*?This branch is[\S\s]*?((?[0-9]*) commits? ahead[\S\s]*?(?[0-9]*) commits? behind|(?[0-9]*) commits? behind|(?[0-9]*) commits? ahead)/, + stars: /([0-9]+) users? starred this repository/, + }, +}; +const LegacyLoadDiffButton = (() => { const queue = []; const parallelNum = 3; @@ -30,7 +30,7 @@ const ForksDiff = (() => { // Add spinner const spinner = document.createElement("span"); - spinner.innerHTML = loadingIcon; + spinner.innerHTML = window._forksdiffconstants.icons.loading; currentRepo.appendChild(spinner); const request = new XMLHttpRequest(); @@ -45,7 +45,7 @@ const ForksDiff = (() => { currentRepo.removeChild(spinner); // Read diff - const diffRegexResult = diffRegex.exec(body); + const diffRegexResult = window._forksdiffconstants.regex.diff.exec(body); if (!diffRegexResult) { _addSpan(currentRepo, "is even", "text-gray"); } else { @@ -66,9 +66,10 @@ const ForksDiff = (() => { // Read stars _addSpan(currentRepo, " "); - const stars = body.match(starsRegex); + const stars = body.match(window._forksdiffconstants.regex.stars); const starIndicator = document.createElement("span"); - starIndicator.innerHTML = starIcon + " " + stars[1]; + starIndicator.innerHTML = + window._forksdiffconstants.icons.star + " " + stars[1]; currentRepo.appendChild(starIndicator); // Process next repo @@ -88,7 +89,9 @@ const ForksDiff = (() => { e.target.removeEventListener("click", _buttonAction); // Iterate through repos - const repos = document.getElementById("network").querySelector("div").children; + const repos = document + .getElementById("network") + .querySelector("div").children; for (let i = 0; i < repos.length; i++) { // Skip root fork if (repos[i].getElementsByClassName("network-tree").length === 0) { @@ -106,7 +109,7 @@ const ForksDiff = (() => { } }; - const init = () => { + const addButton = () => { const network = document.getElementById("network"); // Check if we have at least one div.repo, if not we are on Network page and not Forks page @@ -114,7 +117,7 @@ const ForksDiff = (() => { const mainButton = document.createElement("button"); mainButton.className = "btn float-right"; - mainButton.innerHTML = forkIcon + " Load diff"; + mainButton.innerHTML = window._forksdiffconstants.icons.fork + " Load diff"; mainButton.addEventListener("click", _buttonAction); network.insertBefore(mainButton, network.childNodes[0]); @@ -130,6 +133,157 @@ const ForksDiff = (() => { } }; + return { + addButton: addButton, + }; +})(); + +const LoadDiffButton = (() => { + const queue = []; + const parallelNum = 3; + + const addSpan = (parent, text, className) => { + const span = document.createElement("span"); + span.className = className; + span.appendChild(document.createTextNode(text)); + parent.appendChild(span); + }; + + const createInfoBox = () => { + const box = document.createElement("div"); + box.className = "mr-4 f6"; + return box; + }; + + const processRepo = () => { + const currentRepo = queue.shift(); + + // Get info box + const infoBoxContainer = currentRepo + .querySelector("div") + .querySelector("div"); + + // Create info box + const infoBox = createInfoBox(); + infoBoxContainer.insertBefore(infoBox, infoBoxContainer.children[4]); + + // Add spinner + const spinner = document.createElement("span"); + spinner.innerHTML = window._forksdiffconstants.icons.loading; + infoBox.appendChild(spinner); + + // TODO: Maybe switch to fetch + const request = new XMLHttpRequest(); + request.addEventListener("load", function () { + // Remove spinner + infoBox.removeChild(spinner); + + if (this.status == 429) { + // Rate limited :( + console.log(this.getResponseHeader("Retry-After")); + return; + } + + const body = this.responseText; + + // Read diff + const diffRegexResult = window._forksdiffconstants.regex.diff.exec(body); + if (!diffRegexResult) { + addSpan(infoBox, "is even", "text-gray"); + } else { + const { + groups: { a1, a2, b, c }, + } = diffRegexResult; + + if (a1 && a2) { + addSpan(infoBox, "+" + a1, "cadd"); + addSpan(infoBox, " "); + addSpan(infoBox, "-" + a2, "cdel"); + } else if (b) { + addSpan(infoBox, "-" + b, "cdel"); + } else if (c) { + addSpan(infoBox, "+" + c, "cadd"); + } + } + + // Process next repo + if (queue.length > 0) { + processRepo(); + } + }); + + // Send request + request.open("GET", currentRepo.querySelectorAll("a")[1].href); + request.send(); + }; + + const buttonAction = (e) => { + console.log(e); + + // Disable button + e.target.setAttribute("disabled", "disabled"); + e.target.removeEventListener("click", buttonAction); + + // Extract forks links + const forks = document + .querySelector(".Layout-main") + .querySelector("ul") + .querySelectorAll("li"); + console.log(forks); + queue.push.apply(queue, forks); + console.log(queue); + + // Start + for (let i = 0; i < parallelNum; i++) { + if (queue.length > 0) { + processRepo(); + } + } + }; + + const addButton = () => { + const buttons = document + .querySelector("search-control-menu") + .querySelector("div"); + + const mainButton = document.createElement("button"); + mainButton.className = + "Button--secondary Button--small Button text-normal mt-2 ml-lg-2 mt-lg-0"; + mainButton.addEventListener("click", buttonAction); + + // Add text + // const span1 = document.createElement("span"); + // span1.className = "Button-content"; + // const span2 = document.createElement("span"); + // span2.className = "Button-label"; + // span2.appendChild(document.createTextNode("Load diff")); + // span1.appendChild(span2); + // mainButton.appendChild(span1); + mainButton.appendChild(document.createTextNode("Load diff")); + + buttons.appendChild(mainButton); + }; + + return { + addButton: addButton, + }; +})(); + +const ForksDiff = (() => { + // Regex + const legacyNetworkRegex = + /https?:\/\/github.com\/[\w\.\-]+\/[\w\.\-]+\/network\/members/; + const forksUrlRegex = /https?:\/\/github.com\/[\w\.\-]+\/[\w\.\-]+\/forks/; + + const init = () => { + // Check page + if (forksUrlRegex.test(location.href)) { + LoadDiffButton.addButton(); + } else if (legacyNetworkRegex.test(location.href)) { + LegacyLoadDiffButton.addButton(); + } + }; + return { init: init, }; diff --git a/manifest.json b/manifest.json index 8e145b5..2b6d0a9 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "__MSG_appName__", - "version": "1.2.3", + "version": "1.2.4", "description": "__MSG_appDescription__", "default_locale": "en", diff --git a/pack.sh b/pack.sh index 545c953..b7e076f 100755 --- a/pack.sh +++ b/pack.sh @@ -1,15 +1,15 @@ #!/usr/bin/env bash -VERSION="1.2.3-chrome" +VERSION="1.2.4-chrome" ICONS_SIZES="16 32 48 64 128" OUTPUT_FOLDER=".build" # Prepare icons for size in ${ICONS_SIZES}; do - ( - cd icons || exit 1 - inkscape -w "${size}" -h "${size}" source.svg --export-filename "icon.${size}.png" - ) + ( + cd icons || exit 1 + inkscape -w "${size}" -h "${size}" source.svg --export-filename "icon.${size}.png" + ) done # Pack to zip