(null);
@@ -60,22 +35,9 @@ export function MarkdownCopyHandler({ children }: { children: ReactNode }) {
// Inject copy buttons on every that doesn't already have one
injectCopyButtons(container);
- // Make images in markdown look clickable
- const images = container.querySelectorAll(".ghmd img");
- for (const img of images) {
- img.style.cursor = "zoom-in";
- }
-
function handleClick(e: MouseEvent) {
const target = e.target as HTMLElement;
- // Image lightbox
- if (target.tagName === "IMG" && target.closest(".ghmd")) {
- const img = target as HTMLImageElement;
- openLightbox(img.src, img.alt || "");
- return;
- }
-
// Package-manager install copy
const pkgBtn = target.closest(".ghmd-pkg-copy[data-copy]");
if (pkgBtn) {
diff --git a/apps/web/src/components/shared/markdown-renderer.tsx b/apps/web/src/components/shared/markdown-renderer.tsx
index e8202b0..3186c78 100644
--- a/apps/web/src/components/shared/markdown-renderer.tsx
+++ b/apps/web/src/components/shared/markdown-renderer.tsx
@@ -77,19 +77,6 @@ function resolveUrls(html: string, ctx: RepoContext): string {
return html;
}
-/**
- * Rewrite github.com/user-attachments image/video URLs to go through our proxy.
- * These URLs require GitHub auth cookies to resolve the S3 redirect.
- */
-function proxyGitHubAssets(html: string): string {
- return html.replace(
- /((?:src|poster|srcset)=")([^"]*github\.com\/user-attachments\/assets\/[^"]+)(")/gi,
- (_match, before, url, after) => {
- return `${before}/api/image-proxy?url=${encodeURIComponent(url)}${after}`;
- },
- );
-}
-
// Convert GitHub alert syntax: > [!NOTE] / [!TIP] / [!IMPORTANT] / [!WARNING] / [!CAUTION]
function processAlerts(html: string): string {
const alertTypes: Record = {
@@ -385,9 +372,6 @@ export async function renderMarkdownToHtml(
html = resolveUrls(html, repoContext);
}
- // Proxy GitHub user-attachment images/videos through our API to handle auth redirects
- html = proxyGitHubAssets(html);
-
// Convert github.com links to internal app paths
html = html.replace(/ {
const internal = toInternalUrl(href);
diff --git a/apps/web/src/components/theme-toggle.tsx b/apps/web/src/components/theme-toggle.tsx
index 081bebd..b540127 100644
--- a/apps/web/src/components/theme-toggle.tsx
+++ b/apps/web/src/components/theme-toggle.tsx
@@ -1,29 +1,8 @@
"use client";
+import { Moon, Sun } from "lucide-react";
import { useColorTheme } from "@/components/theme/theme-provider";
-function SunIcon({ className }: { className?: string }) {
- return (
-
- );
-}
-
-function MoonIcon({ className }: { className?: string }) {
- return (
-
- );
-}
-
export function ThemeToggle() {
const { mode, toggleMode } = useColorTheme();
const isDark = mode === "dark";
@@ -39,9 +18,9 @@ export function ThemeToggle() {
style={{ left: isDark ? "2px" : "16px" }}
>
{isDark ? (
-
+
) : (
-
+
)}
Toggle theme
diff --git a/apps/web/src/lib/github-utils.ts b/apps/web/src/lib/github-utils.ts
index ac7d33b..85310f2 100644
--- a/apps/web/src/lib/github-utils.ts
+++ b/apps/web/src/lib/github-utils.ts
@@ -156,13 +156,6 @@ const GITHUB_NON_USER_PATHS = new Set([
"watching",
]);
-/** GitHub top-level paths that look like owner/repo but aren't real repositories */
-const GITHUB_NON_REPO_OWNERS = new Set([
- "user-attachments",
- "assets",
- "github",
-]);
-
type ParsedGitHubUrl =
| {
owner: string;
@@ -193,9 +186,6 @@ export function parseGitHubUrl(htmlUrl: string): ParsedGitHubUrl | null {
const [owner, repo, ...rest] = parts;
- // Skip GitHub system paths that are not real repos (e.g. user-attachments/assets)
- if (GITHUB_NON_REPO_OWNERS.has(owner)) return null;
-
if (rest.length === 0) return { owner, repo, type: "repo" };
if (rest[0] === "pull" && rest[1])
return { owner, repo, type: "pull", number: parseInt(rest[1], 10) };
diff --git a/apps/web/src/lib/github.ts b/apps/web/src/lib/github.ts
index a7974e1..f3e9597 100644
--- a/apps/web/src/lib/github.ts
+++ b/apps/web/src/lib/github.ts
@@ -2339,13 +2339,6 @@ export interface PRBundleData {
};
author: { login: string; avatar_url: string } | null;
}[];
- stateEvents: {
- id: string;
- event: "closed" | "reopened" | "merged" | "ready_for_review" | "convert_to_draft";
- created_at: string;
- actor: { login: string; avatar_url: string } | null;
- merge_ref_name?: string;
- }[];
}
const PR_BUNDLE_QUERY = `
@@ -2447,32 +2440,6 @@ const PR_BUNDLE_QUERY = `
resourcePath
}
}
- timelineItems(first: 100, itemTypes: [CLOSED_EVENT, REOPENED_EVENT, MERGED_EVENT, READY_FOR_REVIEW_EVENT, CONVERT_TO_DRAFT_EVENT]) {
- nodes {
- __typename
- ... on ClosedEvent {
- createdAt
- actor { login avatarUrl }
- }
- ... on ReopenedEvent {
- createdAt
- actor { login avatarUrl }
- }
- ... on MergedEvent {
- createdAt
- actor { login avatarUrl }
- mergeRefName
- }
- ... on ReadyForReviewEvent {
- createdAt
- actor { login avatarUrl }
- }
- ... on ConvertToDraftEvent {
- createdAt
- actor { login avatarUrl }
- }
- }
- }
}
}
}
@@ -2640,29 +2607,9 @@ function transformGraphQLPRBundle(node: Record): PRBundleData {
author: null,
};
});
-
- const eventTypeMap: Record = {
- ClosedEvent: "closed",
- ReopenedEvent: "reopened",
- MergedEvent: "merged",
- ReadyForReviewEvent: "ready_for_review",
- ConvertToDraftEvent: "convert_to_draft",
- };
-
- const stateEvents: PRBundleData["stateEvents"] = (node.timelineItems?.nodes ?? [])
- .filter((e: Record) => e?.__typename && eventTypeMap[e.__typename])
- .map((e: Record, index: number) => ({
- id: `${e.__typename}-${e.createdAt}-${index}`,
- event: eventTypeMap[e.__typename],
- created_at: e.createdAt,
- actor: e.actor
- ? { login: e.actor.login, avatar_url: e.actor.avatarUrl }
- : null,
- merge_ref_name: e.mergeRefName ?? undefined,
- }));
/* eslint-enable @typescript-eslint/no-explicit-any */
- return { pr, issueComments, reviewComments, reviews, reviewThreads, commits, stateEvents };
+ return { pr, issueComments, reviewComments, reviews, reviewThreads, commits };
}
async function fetchPRBundleFromGitHub(