diff --git a/src/lib/api/repos.ts b/src/lib/api/repos.ts index f378862..a42fd52 100644 --- a/src/lib/api/repos.ts +++ b/src/lib/api/repos.ts @@ -599,6 +599,18 @@ export const decodeBlobText = (blob: BlobResponse): string => { return blob.content; }; +export const decodeBlobBytes = (blob: BlobResponse): Uint8Array => { + if (!blob.content) { + return new Uint8Array(); + } + + if (blob.encoding === 'base64') { + return Uint8Array.from(atob(blob.content), (char) => char.charCodeAt(0)); + } + + return new TextEncoder().encode(blob.content); +}; + export const buildBlobDataUrl = (blob: BlobResponse): string | null => { if (!blob.content || !blob.mimeType) { return null; diff --git a/src/pages/repo/code.tsx b/src/pages/repo/code.tsx index b758f63..b10f154 100644 --- a/src/pages/repo/code.tsx +++ b/src/pages/repo/code.tsx @@ -2,8 +2,8 @@ import clsx from 'clsx'; import { File, Folder, GitBranch, GitCommitHorizontal, List } from 'lucide-solid'; import { A, useNavigate, useParams } from '@solidjs/router'; import { createQuery, keepPreviousData, useQueryClient } from '@tanstack/solid-query'; -import { For, Match, Show, Switch, createEffect, createMemo, createSignal, type Accessor, type Component } from 'solid-js'; -import { buildBlobDataUrl, decodeBlobText, getRepoBlob, getRepoBranches, getRepoDefaultBranch, getRepoLanguages, getRepoLog, getRepoTags, getRepoTree, type CommitHeadline } from '../../lib/api/repos'; +import { For, Match, Show, Switch, createEffect, createMemo, createSignal, onCleanup, type Accessor, type Component } from 'solid-js'; +import { buildBlobDataUrl, decodeBlobBytes, decodeBlobText, getRepoBlob, getRepoBranches, getRepoDefaultBranch, getRepoLanguages, getRepoLog, getRepoTags, getRepoTree, type CommitHeadline } from '../../lib/api/repos'; import { Avatar, ErrorState, PlaceholderAvatar, buttonStyles, cardStyles } from '../../components/common'; import { CloneDropdown, CodeView, FileRow, MarkdownBlock, OverviewFileRow, ReadmeCard, RepoBlobSkeleton, RepoLanguageBarSkeleton, RepoTreeSkeleton } from '../../components/repo'; import { RepoFrame, useRepoQuery } from './shared'; @@ -899,6 +899,15 @@ export const BlobPage: Component = () => { const lineCount = createMemo(() => countLines(text())); const commitLink = (commit: Accessor) => `/${repo.owner.handle}/${repo.slug}/commit/${commit().hash}`; + const [blobUrl, setBlobUrl] = createSignal(); + createEffect(() => { + const bytes = decodeBlobBytes(blob); + const webBlob = new Blob([bytes.buffer as any], { type: blob.mimeType }); + const url = URL.createObjectURL(webBlob); + setBlobUrl(url); + onCleanup(() => URL.revokeObjectURL(url)); + }); + return (
@@ -915,9 +924,9 @@ export const BlobPage: Component = () => { · {formatBytes(blob.size!)} - + · - + view raw