-
-
- Loading...
-
-
- {isValid && (
+ {!iframeError ? (
+ <>
+
+
+ Loading...
+
setIframeError('Error loading the code...Try again')}
/>
+ >
+ ) : (
+
{iframeError}
)}
)}
diff --git a/src/lib/octokit/client.ts b/src/lib/octokit/client.ts
index 4f1d0a8..be4f4f8 100644
--- a/src/lib/octokit/client.ts
+++ b/src/lib/octokit/client.ts
@@ -1,5 +1,34 @@
import { Octokit } from 'octokit'
+// Default Octokit instance for public access or pre-configured token
export const octokit = new Octokit({
- auth: process.env.NEXT_PUBLIC_GITHUB_TOKEN!,
+ auth: process.env.NEXT_PUBLIC_GITHUB_TOKEN!,
})
+
+// Function to fetch file content with an optional token for private repos
+export async function getFileContent({
+ owner,
+ repo,
+ path,
+ token,
+}: {
+ owner: string
+ repo: string
+ path: string
+ token?: string
+}): Promise
{
+ // Use a new Octokit instance if a token is provided, otherwise use the default
+ const authOctokit = token ? new Octokit({ auth: token }) : octokit
+ try {
+ const { data } = await authOctokit.rest.repos.getContent({
+ owner,
+ repo,
+ path,
+ mediaType: { format: 'raw' },
+ })
+ return String(data)
+ } catch (error) {
+ console.error('Error fetching file content:', error)
+ throw error
+ }
+}
\ No newline at end of file
diff --git a/src/lib/octokit/github.ts b/src/lib/octokit/github.ts
new file mode 100644
index 0000000..7e8ff49
--- /dev/null
+++ b/src/lib/octokit/github.ts
@@ -0,0 +1,56 @@
+// src/lib/octokit/github.ts
+export async function fetchGithubFileContent(
+ owner: string,
+ repo: string,
+ path: string,
+ token?: string,
+): Promise {
+ const apiUrl = `https://api.github.com/repos/${owner}/${repo}/contents/${path}`;
+ const rawUrl = `https://raw.githubusercontent.com/${owner}/${repo}/main/${path}`; // Fallback for public repos
+ const baseHeaders: HeadersInit = {
+ 'Accept': 'application/vnd.github.v3+json',
+ };
+
+ // Try API without token first (for public repos)
+ console.log(`Fetching ${apiUrl} without token...`);
+ let response = await fetch(apiUrl, { headers: baseHeaders });
+ console.log(`API Response status: ${response.status}, OK: ${response.ok}`);
+
+ // If rate limit (429) or auth error (401/403), try with token if provided
+ if ((response.status === 429 || response.status === 401 || response.status === 403) && token) {
+ const authHeaders: HeadersInit = {
+ ...baseHeaders,
+ 'Authorization': `token ${token}`,
+ };
+ console.log(`Retrying ${apiUrl} with token due to ${response.status}...`);
+ response = await fetch(apiUrl, { headers: authHeaders });
+ console.log(`Retry status: ${response.status}, OK: ${response.ok}`);
+ }
+
+ if (!response.ok) {
+ if (response.status === 429 || response.status === 403) {
+ // Fallback to raw URL for public repos when rate limited
+ console.log(`Rate limit hit, trying raw URL: ${rawUrl}`);
+ const rawResponse = await fetch(rawUrl);
+ if (rawResponse.ok) {
+ return await rawResponse.text();
+ }
+ console.error(`Raw fetch failed: ${rawResponse.status} - ${await rawResponse.text()}`);
+ }
+ const errorText = await response.text();
+ console.error(`Failed to fetch ${owner}/${repo}/${path}: ${response.status} - ${errorText}`);
+ throw new Error(
+ response.status === 429
+ ? 'API rate limit exceeded. Try using a personal access token for higher limits.'
+ : `Failed to fetch ${owner}/${repo}/${path}: ${response.status} - ${errorText}`
+ );
+ }
+
+ const data = await response.json();
+ if (!data.content || typeof data.content !== 'string') {
+ console.error('No valid content in response:', data);
+ throw new Error('No valid content found in response');
+ }
+
+ return atob(data.content);
+}
\ No newline at end of file
diff --git a/src/lib/store.ts b/src/lib/store.ts
index 8feffe6..9ce1085 100644
--- a/src/lib/store.ts
+++ b/src/lib/store.ts
@@ -2,7 +2,7 @@ import { bundledThemes } from 'shiki'
import { create } from 'zustand'
import { dev } from '@/lib/env'
-export const DOMAIN = 'https://github-iframe.vercel.app'
+export const DOMAIN = 'https://github-iframe-kappa.vercel.app'
export const DISPLAYS = ['none', 'repo', 'path', 'all'] as const
export const DEFAULT_THEME: Theme = 'dark-plus'
@@ -19,6 +19,7 @@ export const store = create<{
lineNums?: boolean
highlight?: string
scrollTo?: boolean
+ token?: string // New
setRepo: (repo: string) => void
setPath: (path: string) => void
@@ -28,6 +29,7 @@ export const store = create<{
setLineNums: (lineNums?: boolean) => void
setHighlight: (highlight?: string) => void
setScrollTo: (scrollTo?: boolean) => void
+ setToken: (token?: string) => void // New
}>((set) => ({
repo: 'nuotsu/github-iframe',
path: 'src/lib/store.ts',
@@ -37,6 +39,7 @@ export const store = create<{
lineNums: false,
highlight: undefined,
scrollTo: false,
+ token: undefined, // New
setRepo: (repo: string) => set({ repo }),
setPath: (path: string) => set({ path }),
@@ -46,11 +49,22 @@ export const store = create<{
setLineNums: (lineNums?: boolean) => set({ lineNums }),
setHighlight: (highlight?: string) => set({ highlight }),
setScrollTo: (scrollTo?: boolean) => set({ scrollTo }),
+ setToken: (token?: string) => set({ token }), // New
}))
export function getSrc() {
return store(
- ({ repo, path, theme, lang, display, lineNums, highlight, scrollTo }) => {
+ ({
+ repo,
+ path,
+ theme,
+ lang,
+ display,
+ lineNums,
+ highlight,
+ scrollTo,
+ token,
+ }) => {
const domain = dev ? 'http://localhost:3000' : DOMAIN
const url = new URL(
`${domain}/${repo}/${path}${highlight ? `#L${highlight}` : ''}`,
@@ -61,6 +75,7 @@ export function getSrc() {
if (display !== 'none') url.searchParams.set('display', display)
if (lineNums) url.searchParams.set('lineNums', '0')
if (highlight && scrollTo) url.searchParams.set('scrollTo', '1')
+ if (token) url.searchParams.set('token', token) // New: Add token to URL
return url.toString()
},