Skip to content

Instantly share code, notes, and snippets.

@tony-sol
Created February 13, 2025 11:30
Show Gist options
  • Save tony-sol/2a5c004dd64e8ac54d6eb250e4dfa70d to your computer and use it in GitHub Desktop.
Save tony-sol/2a5c004dd64e8ac54d6eb250e4dfa70d to your computer and use it in GitHub Desktop.
coezbek/github-fork-bookmarklet but with token support
javascript:(async () => {
/* Ensure the script is run on a valid GitHub repository page */
const ensureForksPage = () => {
const match = window.location.href.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)(\/forks\/?)?/);
if (!match) {
alert('Run this from a GitHub repository page.');
throw new Error('Not on a valid GitHub repository page.');
}
if (!match[3]) {
window.location.href = `https://github.com/${match[1]}/${match[2]}/forks`;
throw new Error('Redirecting to the forks page.');
}
return { user: match[1], repo: match[2] };
};
/* Fetch the default branch of a repository */
const getDefaultBranch = async (user, repo) => {
let token = prompt("Insert your GITHUB_TOKEN. It won't be saved");
const res = await fetch(`https://api.github.com/repos/${user}/${repo}`, { headers: { accept: 'application/json', authorization: `Bearer ${token}` } });
if (!res.ok) throw new Error(`Failed to fetch default branch for ${user}/${repo}`);
return (await res.json()).default_branch;
};
/* Fetch branch information */
const fetchBranchInfo = async (user, repo, branch) => {
try {
const res = await fetch(`https://github.com/${user}/${repo}/branch-infobar/${branch}`, { headers: { accept: 'application/json' } });
if (res.ok) return (await res.json()).refComparison;
} catch (e) {
console.error(`Error fetching branch info for ${user}/${repo}:`, e);
}
return null;
};
try {
/* Ensure on the forks page and get main repository details */
const { user: mainUser, repo: mainRepo } = ensureForksPage();
const defaultBranch = await getDefaultBranch(mainUser, mainRepo);
/* Process fork links */
const forks = [...document.querySelectorAll('ul[data-view-component="true"] > li')];
for (const fork of forks) {
const repoLink = fork.querySelector('a[href*="/"]:nth-of-type(2)');
const match = repoLink?.href.match(/github\.com\/([^/]+)\/([^/]+)/);
if (!match) continue;
const [_, user, repo] = match;
let branchInfo = await fetchBranchInfo(user, repo, defaultBranch);
if (!branchInfo) branchInfo = await fetchBranchInfo(user, repo, await getDefaultBranch(user, repo));
if (branchInfo) {
const { ahead, behind } = branchInfo;
const info = `Ahead: <font color="#0c0">${ahead}</font>, Behind: <font color="red">${behind}</font>`;
const infoDiv = document.createElement('div');
infoDiv.innerHTML = info;
infoDiv.style.marginTop = '10px';
infoDiv.style.fontSize = 'small';
fork.appendChild(infoDiv);
if (ahead === 0) fork.style.display = 'none';
}
}
} catch (e) {
console.error('Error in bookmarklet execution:', e);
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment