feat: add semantic CSS stylesheets (#3274)

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
This commit is contained in:
Amruth Pillai
2026-07-30 12:39:15 +02:00
committed by GitHub
co-authored by Cursor Agent
parent 4ac19f81b3
commit d2ffbf9618
320 changed files with 78393 additions and 2915 deletions
@@ -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;
}