Skip to content

Commit f2a0744

Browse files
committed
Fix rate limit issues and remove injected css when changing user pages
1 parent f1f3b74 commit f2a0744

File tree

8 files changed

+126
-22
lines changed

8 files changed

+126
-22
lines changed

manifest.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
"description": "A simple extension that allows users to view custom css on GitHub profiles.",
66
"author": "Bims-sh",
77
"permissions": [
8-
"activeTab",
8+
"webNavigation",
99
"tabs",
10-
"storage"
10+
"activeTab"
1111
],
1212
"icons": {
1313
"48": "images/extension_48.png",

package.json

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,13 @@
1313
"extension": "latest"
1414
},
1515
"scripts": {
16-
"dev": "extension dev",
17-
"start": "extension start",
18-
"build": "extension build"
16+
"dev:chrome": "extension dev -b chrome",
17+
"dev:ff": "extension dev -b firefox",
18+
"start:chrome": "extension start -b chrome",
19+
"start:ff": "extension start -b firefox",
20+
"build:all": "extension build -b chrome && extension build -b firefox",
21+
"build:chrome": "extension build -b firefox",
22+
"build:ff": "extension build -b firefox"
1923
},
2024
"dependencies": {}
2125
}

src/background.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,23 @@
1-
console.log("Hello world!")
1+
function handleCssInjection(tabId: number): void {
2+
chrome.tabs.sendMessage(tabId, { action: "injectCss" }).catch((error: any) => {
3+
console.error("Failed to send message:", error);
4+
});
5+
}
6+
7+
// Listen for history state changes (SPA navigation)
8+
chrome.webNavigation.onHistoryStateUpdated.addListener((details: chrome.webNavigation.WebNavigationTransitionCallbackDetails) => {
9+
console.log("History state updated");
10+
handleCssInjection(details.tabId);
11+
}, { url: [{ urlMatches: 'github.com' }] });
12+
13+
// Listen for tab updates (page load or refresh)
14+
chrome.tabs.onUpdated.addListener((tabId: number, changeInfo: chrome.tabs.TabChangeInfo) => {
15+
if (changeInfo.status === 'complete') {
16+
chrome.tabs.get(tabId, (tab) => {
17+
if (tab.url && tab.url.includes("github.com")) {
18+
console.log("Tab updated");
19+
handleCssInjection(tabId);
20+
}
21+
});
22+
}
23+
});

src/content/ghcss.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
1-
import {fetchGitHubCss} from "../lib/utils/GitHubUtils";
2-
import {injectCss} from "../lib/utils/InjectCss";
1+
import {injectOrUpdateCss, removeInjectedCss} from "../lib/utils/InjectCss";
32

43
async function main() {
54
try {
6-
const css = await fetchGitHubCss();
7-
8-
if (css !== null) {
9-
injectCss(css);
10-
}
5+
await injectOrUpdateCss(document.URL);
116
} catch (error) {
127
console.error(error);
138
}
149
}
1510

16-
main().then();
11+
chrome.runtime.onMessage.addListener((message) => {
12+
switch (message.action) {
13+
case "injectCss":
14+
main().then();
15+
break;
16+
case "removeInjectedCss":
17+
removeInjectedCss();
18+
break;
19+
}
20+
});

src/lib/utils/FetchData.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
export async function fetchMainBranch(owner: string, repo: string): Promise<string | null> {
1+
import {GitHubPageType} from "../types/GitHubPageType";
2+
3+
export async function fetchMainBranch(owner: string, repo: string): Promise<string | null> {
24
const url = `https://api.github.com/repos/${owner}/${repo}`;
35

46
try {
@@ -17,6 +19,33 @@
1719
}
1820
}
1921

22+
export async function tryFetchFromAllCommonBranches(basePath: string, pageType: GitHubPageType, owner: string, repo: string): Promise<string | null> {
23+
const commonBranches = ["main", "master"];
24+
const cssFileNames = {
25+
[GitHubPageType.Organization]: "org.css",
26+
[GitHubPageType.Repo]: "repo.css",
27+
[GitHubPageType.User]: "user.css"
28+
};
29+
30+
const cssFile = cssFileNames[pageType];
31+
32+
for (const branch of commonBranches) {
33+
const url = `${basePath}/${owner}/${repo || owner}/${branch}/${cssFile}`;
34+
try {
35+
const response = await fetch(url, { method: 'HEAD' });
36+
if (response.ok) {
37+
return url;
38+
} else if (response.status === 404) {
39+
console.log(`Could not find custom css for ${owner} on branch ${branch}`);
40+
}
41+
} catch (error) {
42+
console.log(`Failed to fetch CSS file at ${url}: ${error}`);
43+
}
44+
}
45+
46+
return null;
47+
}
48+
2049
export async function fetchPlainCss(url: string): Promise<string | null> {
2150
try {
2251
const response = await fetch(url, { headers: { "Accept": "text/plain" } });

src/lib/utils/GitHubUtils.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {GitHubPageType} from "../types/GitHubPageType";
2-
import {fetchMainBranch, fetchPlainCss} from "./FetchData";
2+
import {fetchPlainCss, tryFetchFromAllCommonBranches} from "./FetchData";
33

44
export async function fetchGitHubCss(): Promise<string | null> {
55
let css: string | null = null;
@@ -25,7 +25,7 @@ export async function fetchGitHubCss(): Promise<string | null> {
2525
return css;
2626
}
2727

28-
function getGitHubPageType(): { type: GitHubPageType | null, id: string | null } {
28+
export function getGitHubPageType(): { type: GitHubPageType | null, id: string | null } {
2929
const metaOrganization = document.querySelector('meta[content^="organization:"]')?.getAttribute("content")?.split(":").pop() || null;
3030
const metaRepository = document.querySelector('meta[content^="repository:"]')?.getAttribute("content")?.split(":").pop() || null;
3131
const metaUser = document.querySelector('meta[name="octolytics-dimension-user_id"]')?.getAttribute("content") || null;
@@ -44,8 +44,10 @@ async function getGitHubCssPath(pageType: GitHubPageType): Promise<string | null
4444
const repo = pathSegments[1] || "";
4545

4646
try {
47-
let cssPath: string | null = null;
48-
const mainBranch = await fetchMainBranch(owner, pageType === GitHubPageType.Organization ? ".github" : repo || owner);
47+
let cssPath: string | null;
48+
49+
// fetching the main branch without auth causes ip wide rate limits pretty quickly, we probably need to cache this or store the css on our end
50+
/*const mainBranch = await fetchMainBranch(owner, pageType === GitHubPageType.Organization ? ".github" : repo || owner);
4951
5052
if (!mainBranch) {
5153
return null;
@@ -61,7 +63,10 @@ async function getGitHubCssPath(pageType: GitHubPageType): Promise<string | null
6163
case GitHubPageType.User:
6264
cssPath = `${basePath}/${owner}/${owner}/${mainBranch}/user.css`;
6365
break;
64-
}
66+
}*/
67+
68+
// temporary "fix"
69+
cssPath = await tryFetchFromAllCommonBranches(basePath, pageType, owner, repo);
6570

6671
return cssPath;
6772
} catch (error) {

src/lib/utils/InjectCss.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,42 @@
1-
export function injectCss(css: string): void {
1+
import {fetchGitHubCss} from "./GitHubUtils";
2+
import {getBaseUrl} from "./Urls";
3+
4+
let lastBaseUrl: string | null = null;
5+
6+
export async function injectOrUpdateCss(url: string) {
7+
if (lastBaseUrl !== getBaseUrl(url) || lastBaseUrl === null) {
8+
lastBaseUrl = url;
9+
10+
removeInjectedCss();
11+
12+
const css = await fetchGitHubCss();
13+
14+
if (css !== null && css.length > 0) {
15+
injectCss(css);
16+
}
17+
}
18+
}
19+
20+
function injectCss(css: string): void {
221
let styleElement = document.getElementById("ghss-container") as HTMLStyleElement;
322

423
if (!styleElement) {
524
styleElement = document.createElement("style");
625
styleElement.id = "ghss-container";
726
document.head.appendChild(styleElement);
8-
}
27+
}
928

1029
styleElement.textContent = css;
30+
}
31+
32+
export function removeInjectedCss(): void {
33+
let styleElement = document.getElementById("ghss-container") as HTMLStyleElement;
34+
if (styleElement !== null) {
35+
styleElement.remove();
36+
}
37+
}
38+
39+
export function isCssInjected(): boolean {
40+
let styleElement = document.getElementById("ghss-container") as HTMLStyleElement;
41+
return styleElement === null;
1142
}

src/lib/utils/Urls.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export function getBaseUrl(url: string): string {
2+
try {
3+
const urlObj = new URL(url);
4+
return `${urlObj.protocol}//${urlObj.host}${urlObj.pathname}`;
5+
} catch (e) {
6+
console.error("Invalid URL:", e);
7+
return url;
8+
}
9+
}

0 commit comments

Comments
 (0)