Ship file viewer, editor improvements, and private package releases
This commit is contained in:
1 parent
645914955c
commit
a4a31032b9
158 files changed
+10523
-137
No files matched your search
@@ -0,0 +1,68 @@
|
||||
import type { ResolveOptions, ViewerSource } from "./types.ts";
|
||||
|
||||
export function safeSourceUrl(src: string): string | undefined {
|
||||
try {
|
||||
const url = new URL(src, typeof location === "undefined" ? "http://localhost" : location.href);
|
||||
return ["http:", "https:", "blob:", "data:"].includes(url.protocol) ? url.href : undefined;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/** The source's own http(s) URL, when it has one that an element can load. */
|
||||
export function directUrl(source: ViewerSource): string | undefined {
|
||||
if (source.blob || !source.src) return undefined;
|
||||
const url = safeSourceUrl(source.src);
|
||||
return url && /^https?:/i.test(url) ? url : undefined;
|
||||
}
|
||||
|
||||
export async function readBounded(
|
||||
response: Response,
|
||||
cap: number,
|
||||
prefixOnly = false,
|
||||
): Promise<Uint8Array> {
|
||||
if (!response.ok || !response.body) throw new Error("File could not be read");
|
||||
const reader = response.body.getReader();
|
||||
const parts: Uint8Array[] = [];
|
||||
let length = 0;
|
||||
try {
|
||||
while (true) {
|
||||
const next = await reader.read();
|
||||
if (next.done) break;
|
||||
if (!prefixOnly && length + next.value.length > cap)
|
||||
throw new Error("File exceeds preview limit");
|
||||
const part = next.value.subarray(0, cap - length);
|
||||
parts.push(part);
|
||||
length += part.length;
|
||||
if (prefixOnly && length >= cap) break;
|
||||
}
|
||||
} finally {
|
||||
await reader.cancel().catch(() => {});
|
||||
reader.releaseLock();
|
||||
}
|
||||
const bytes = new Uint8Array(length);
|
||||
let offset = 0;
|
||||
for (const part of parts) {
|
||||
bytes.set(part, offset);
|
||||
offset += part.length;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
export async function readSource(
|
||||
source: ViewerSource,
|
||||
cap: number,
|
||||
options: ResolveOptions = {},
|
||||
): Promise<Blob> {
|
||||
if (source.blob) {
|
||||
if (source.blob.size > cap) throw new Error("File exceeds preview limit");
|
||||
return source.blob;
|
||||
}
|
||||
const url = source.src && safeSourceUrl(source.src);
|
||||
if (!url) throw new Error("No readable file source");
|
||||
const response = await (options.fetch ?? fetch)(url, { signal: options.signal });
|
||||
const bytes = await readBounded(response, cap);
|
||||
return new Blob([bytes as Uint8Array<ArrayBuffer>], {
|
||||
type: response.headers.get("content-type") ?? source.mime ?? "",
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user