mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-08-25 15:52:21 +10:00
feat: add semantic CSS stylesheets (#3274)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor Agent
parent
4ac19f81b3
commit
d2ffbf9618
@@ -0,0 +1,28 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { rasterizePdf } from "./rasterize-pdf";
|
||||
|
||||
describe("rasterizePdf cleanup", () => {
|
||||
it("destroys the loading task when loading rejects", async () => {
|
||||
const destroy = vi.fn().mockResolvedValue(undefined);
|
||||
const loadDocument = vi.fn(() => ({ promise: Promise.reject(new Error("load failed")), destroy }));
|
||||
|
||||
await expect(rasterizePdf(new Uint8Array(), { loadDocument })).rejects.toThrow("load failed");
|
||||
expect(destroy).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("cleans up the page and destroys the loading task when rendering rejects", async () => {
|
||||
const cleanup = vi.fn();
|
||||
const destroy = vi.fn().mockResolvedValue(undefined);
|
||||
const page = {
|
||||
getViewport: vi.fn(() => ({ width: 10, height: 10 })),
|
||||
render: vi.fn(() => ({ promise: Promise.reject(new Error("render failed")) })),
|
||||
cleanup,
|
||||
};
|
||||
const document = { numPages: 1, getPage: vi.fn().mockResolvedValue(page) };
|
||||
const loadDocument = vi.fn(() => ({ promise: Promise.resolve(document), destroy }));
|
||||
|
||||
await expect(rasterizePdf(new Uint8Array(), { loadDocument })).rejects.toThrow("render failed");
|
||||
expect(cleanup).toHaveBeenCalledOnce();
|
||||
expect(destroy).toHaveBeenCalledOnce();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,70 @@
|
||||
import { createCanvas } from "@napi-rs/canvas";
|
||||
import { getDocument } from "pdfjs-dist/legacy/build/pdf.mjs";
|
||||
|
||||
export type RasterizedPdfPage = {
|
||||
width: number;
|
||||
height: number;
|
||||
data: Uint8Array;
|
||||
};
|
||||
|
||||
type RasterPage = {
|
||||
getViewport(input: { scale: number }): { width: number; height: number };
|
||||
render(input: unknown): { promise: Promise<unknown> };
|
||||
cleanup(): void;
|
||||
};
|
||||
|
||||
type RasterDocument = {
|
||||
numPages: number;
|
||||
getPage(pageNumber: number): Promise<RasterPage>;
|
||||
};
|
||||
|
||||
type RasterLoadingTask = {
|
||||
promise: Promise<RasterDocument>;
|
||||
destroy(): Promise<void>;
|
||||
};
|
||||
|
||||
export type RasterizePdfDependencies = {
|
||||
loadDocument?: (bytes: Uint8Array) => RasterLoadingTask;
|
||||
};
|
||||
|
||||
const loadPdfDocument = (bytes: Uint8Array): RasterLoadingTask =>
|
||||
getDocument({ data: bytes }) as unknown as RasterLoadingTask;
|
||||
|
||||
export async function rasterizePdf(
|
||||
bytes: Uint8Array,
|
||||
dependencies: RasterizePdfDependencies = {},
|
||||
): Promise<readonly RasterizedPdfPage[]> {
|
||||
const loadingTask = (dependencies.loadDocument ?? loadPdfDocument)(bytes);
|
||||
const pages: RasterizedPdfPage[] = [];
|
||||
|
||||
try {
|
||||
const document = await loadingTask.promise;
|
||||
for (let pageNumber = 1; pageNumber <= document.numPages; pageNumber += 1) {
|
||||
const page = await document.getPage(pageNumber);
|
||||
try {
|
||||
const viewport = page.getViewport({ scale: 1.5 });
|
||||
const width = Math.ceil(viewport.width);
|
||||
const height = Math.ceil(viewport.height);
|
||||
const canvas = createCanvas(width, height);
|
||||
const context = canvas.getContext("2d");
|
||||
|
||||
await page.render({
|
||||
canvas: canvas as unknown as HTMLCanvasElement,
|
||||
canvasContext: context as unknown as CanvasRenderingContext2D,
|
||||
viewport,
|
||||
}).promise;
|
||||
pages.push({
|
||||
width,
|
||||
height,
|
||||
data: Uint8Array.from(context.getImageData(0, 0, width, height).data),
|
||||
});
|
||||
} finally {
|
||||
page.cleanup();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
await loadingTask.destroy();
|
||||
}
|
||||
|
||||
return pages;
|
||||
}
|
||||
Reference in New Issue
Block a user