summaryrefslogtreecommitdiff
path: root/cgithub/src/scraper.ts
diff options
context:
space:
mode:
authorJoe Mou <dev@mou.fo>2026-01-22 18:35:27 -0500
committerJoe Mou <dev@mou.fo>2026-01-23 01:02:59 -0500
commiteff2e1e7b31f046c974b88b409296af81b9f5615 (patch)
tree4e356d40c1144cbb5c8e14c679ad1e3802a0cf5e /cgithub/src/scraper.ts
parentd0dccc7a910a579d8c172c3d5a5a02ea3abd964d (diff)
Add blob view for displaying file contents
Diffstat (limited to 'cgithub/src/scraper.ts')
-rw-r--r--cgithub/src/scraper.ts77
1 files changed, 77 insertions, 0 deletions
diff --git a/cgithub/src/scraper.ts b/cgithub/src/scraper.ts
index add03b2..fa8d655 100644
--- a/cgithub/src/scraper.ts
+++ b/cgithub/src/scraper.ts
@@ -15,6 +15,20 @@ export interface GitHubTree {
};
}
+export interface GitHubBlob {
+ path: string;
+ branch: string;
+ content: string;
+ rawContent: string;
+ language: string | null;
+ size: number;
+ repo: {
+ name: string;
+ owner: string;
+ isPublic: boolean;
+ };
+}
+
export async function getGitHubTree(
owner: string,
repo: string,
@@ -89,3 +103,66 @@ export async function getGitHubTree(
},
};
}
+
+export async function getGitHubBlob(
+ owner: string,
+ repo: string,
+ branch: string,
+ path: string,
+): Promise<GitHubBlob> {
+ const url = `https://github.com/${owner}/${repo}/blob/${branch}/${path}`;
+
+ const response = await fetch(url, {
+ headers: {
+ "User-Agent":
+ "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
+ Accept:
+ "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
+ "Accept-Language": "en-US,en;q=0.5",
+ },
+ });
+ const html = await response.text();
+
+ // GitHub embeds file data in a JSON script tag
+ let payload;
+
+ const match = html.match(
+ /<script type="application\/json" data-target="react-app\.embeddedData">([^<]+)<\/script>/,
+ );
+ if (match) {
+ try {
+ const data = JSON.parse(match[1]);
+ if (data.payload?.blob) {
+ payload = data.payload;
+ }
+ } catch (e) {
+ // Skip invalid JSON
+ }
+ }
+
+ if (!payload) {
+ throw new Error("Could not find blob data in embedded JSON");
+ }
+
+ const blob = payload.blob;
+ const rawLines = blob.rawLines || [];
+ const rawContent = rawLines.join("\n");
+ const highlightedLines = blob.highlightedLines || [];
+ const content = highlightedLines
+ .map((line: any) => line.text || "")
+ .join("\n");
+
+ return {
+ path: payload.path,
+ branch: payload.refInfo.name,
+ content: content || rawContent,
+ rawContent,
+ language: blob.language || null,
+ size: blob.size,
+ repo: {
+ name: payload.repo.name,
+ owner: payload.repo.ownerLogin,
+ isPublic: payload.repo.public,
+ },
+ };
+}