Files
worst_web/src/lib/cbz.ts
T
renato97 25449aa5df feat: worst-scan fansub web — initial release
Posts engine (SQLite + auto-publisher via poller), public feed with
clickable tags, reader, admin panel, submit/search/queue tools.
BFF proxy to pipeline API. Clean dark design. Docker-ready.
2026-07-23 15:58:28 -03:00

42 lines
1.1 KiB
TypeScript

import JSZip from "jszip"
const imageExts = new Set([".jpg", ".jpeg", ".png", ".webp", ".gif", ".bmp"])
export async function loadPagesFromCbz(
url: string,
signal?: AbortSignal,
): Promise<{ pages: string[]; pageCount: number }> {
const response = await fetch(url, { signal })
if (!response.ok) throw new Error(`Failed to fetch CBZ: ${response.status}`)
const blob = await response.blob()
const zip = await JSZip.loadAsync(blob)
const imageEntries = Object.entries(zip.files)
.filter(([name, file]) => {
const ext = name.toLowerCase().slice(name.lastIndexOf("."))
return !file.dir && imageExts.has(ext)
})
.sort(([a], [b]) => {
const numA = parseInt(a.match(/(\d+)/)?.[1] || "0", 10)
const numB = parseInt(b.match(/(\d+)/)?.[1] || "0", 10)
return numA - numB
})
const pageCount = imageEntries.length
const pages: string[] = []
for (const [, file] of imageEntries) {
const blob = await file.async("blob")
pages.push(URL.createObjectURL(blob))
}
return { pages, pageCount }
}
export function revokePageUrls(urls: string[]) {
for (const url of urls) {
URL.revokeObjectURL(url)
}
}