Something went wrong. Try again.
Monorepo for Tangled forked from tangled.org/core
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136import { error } from "@sveltejs/kit";import { getRequestEvent } from "$app/server";import { classifyBlob, contentStats, countLines, formatBytes, hasRenderedView, hasTextView, MAX_INLINE_SIZE, type RepoBlobView} from "#lib/api/blob.ts";import { ClientResponseError } from "#lib/api/client.ts";import { blob as gitBlob, gitTarget, requireGit } from "#lib/api/gitclient.ts";import { toHttpError } from "#lib/api/load.ts";import { toTreeCommitSummary } from "#lib/api/repo.ts";import { withAuthorHandles } from "#lib/api/repoIndex.ts";import type { StringRecord } from "#lib/api/records.ts";import { isMarkdownFile } from "#lib/markup/index.ts";import type { RepoLoadEvent, RepoParent } from "#lib/server/repoIndex.ts";
export const loadRepoBlob = async ( event: RepoLoadEvent, parent: RepoParent, ref: string, path: string): Promise<RepoBlobView> => { const { fetch } = getRequestEvent(); const repo = requireGit(await parent.repo); const git = gitTarget(parent.publicConfig, repo, fetch);
// the knot 404s directories and missing paths alike // knot2's repo_blob answers 413 over its serving limit instead of // sending size json (knot-xrpc reads.rs) const output = await gitBlob(git, { ref, path }, MAX_INLINE_SIZE).catch( (cause: unknown): Awaited<ReturnType<typeof gitBlob>> | null => { if (cause instanceof ClientResponseError && cause.status === 404) { error(404, `${path} does not exist at ${ref}`); } if ( cause instanceof ClientResponseError && (cause.status === 413 || cause.error === "BlobTooLarge") ) { return null; } return toHttpError(cause, "Could not load file"); } );
if (output === null) { return { ref, path, kind: "other", sizeLabel: null, lines: null, contents: null, fileTooLarge: true, defaultView: "code", submodule: null, lastCommit: null }; }
const kind = classifyBlob(output); const size = output.size ?? null; const fileTooLarge = output.fileTooLarge === true || (hasTextView(kind) && size !== null && size > MAX_INLINE_SIZE);
const contents = hasTextView(kind) && !fileTooLarge && output.encoding === "utf-8" ? (output.content ?? null) : null;
const summary = output.lastCommit ? toTreeCommitSummary({ hash: output.lastCommit.hash, message: output.lastCommit.message, when: output.lastCommit.when, author: output.lastCommit.author }) : null; const [lastCommit = null] = summary ? await withAuthorHandles([summary], parent.publicConfig.bobbinUrl, fetch) : [];
return { ref, path, kind, sizeLabel: size === null ? null : formatBytes(size), lines: contents !== null ? countLines(contents) : null, contents, fileTooLarge, defaultView: hasRenderedView(kind) ? event.url.searchParams.has("code") ? "code" : "rendered" : "code", submodule: output.submodule ? { name: output.submodule.name, url: output.submodule.url } : null, lastCommit };};
export interface StringBlobSource { rkey: string; code: boolean;}
export const loadStringBlob = ( record: StringRecord, contents: string, { rkey, code }: StringBlobSource): RepoBlobView => { const filename = record.snippet.name; const stats = contentStats(contents); const fileTooLarge = stats.bytes > MAX_INLINE_SIZE; const kind = isMarkdownFile(filename) ? "markup" : "code";
return { ref: rkey, path: filename, kind, sizeLabel: stats.sizeLabel, lines: fileTooLarge ? null : stats.lines, contents: fileTooLarge ? null : contents, fileTooLarge, defaultView: kind === "markup" && !code ? "rendered" : "code", submodule: null, lastCommit: null };};