Files
bentopdf/src/tests/helpers/split-fixtures.ts
T
alam00000 aee3e0a65a test: cover the text editor engine and FreeText flattening
Adds a node-side harness that drives the engine wasm directly, fixtures
that build PDFs in-memory, and cases for font fallback and flattening.
The engine loader now tolerates a runtime without import.meta.resolve so
the suite can load it outside a browser.
2026-08-21 12:50:07 +05:30

122 lines
3.4 KiB
TypeScript

import { buildPdf, type PdfObject } from './pdf-builder';
const enc = new TextEncoder();
function grayImage(size: number, shade: number): Uint8Array {
const px = new Uint8Array(size * size);
px.fill(shade);
return px;
}
export function sharedResourcesPdf(pageCount = 8, imageSize = 96): Uint8Array {
const objects: PdfObject[] = [];
const kidRefs: string[] = [];
const pagesRef = 2;
const firstImage = 3;
const firstPage = firstImage + pageCount * 1;
objects.push({ body: '<< /Type /Catalog /Pages 2 0 R >>' });
const xobjects = Array.from(
{ length: pageCount },
(_, i) => `/Im${i} ${firstImage + i} 0 R`
).join(' ');
objects.push({ body: '' });
for (let i = 0; i < pageCount; i++) {
const data = grayImage(imageSize, 20 + i * 20);
objects.push({
body:
'<< /Type /XObject /Subtype /Image ' +
`/Width ${imageSize} /Height ${imageSize} ` +
`/ColorSpace /DeviceGray /BitsPerComponent 8 /Length ${data.length} >>`,
stream: data,
});
}
for (let i = 0; i < pageCount; i++) {
const contentRef = firstPage + pageCount + i;
kidRefs.push(`${firstPage + i} 0 R`);
objects.push({
body:
`<< /Type /Page /Parent ${pagesRef} 0 R /MediaBox [0 0 300 300] ` +
`/Contents ${contentRef} 0 R >>`,
});
}
for (let i = 0; i < pageCount; i++) {
const stream = enc.encode(`q 200 0 0 200 40 40 cm /Im${i} Do Q\n`);
objects.push({ body: `<< /Length ${stream.length} >>`, stream });
}
objects[pagesRef - 1] = {
body:
`<< /Type /Pages /Kids [${kidRefs.join(' ')}] /Count ${pageCount} ` +
`/Resources << /XObject << ${xobjects} >> >> >>`,
};
return buildPdf(objects);
}
export function bookmarkedPdf(pageCount = 4): Uint8Array {
const objects: PdfObject[] = [];
const pagesRef = 2;
const outlinesRef = 3;
const firstItem = 4;
const firstPage = firstItem + pageCount;
const firstContent = firstPage + pageCount;
const fontRef = firstContent + pageCount;
objects.push({
body: `<< /Type /Catalog /Pages ${pagesRef} 0 R /Outlines ${outlinesRef} 0 R /PageMode /UseOutlines >>`,
});
const kidRefs = Array.from(
{ length: pageCount },
(_, i) => `${firstPage + i} 0 R`
).join(' ');
objects.push({
body: `<< /Type /Pages /Kids [${kidRefs}] /Count ${pageCount} >>`,
});
objects.push({
body:
`<< /Type /Outlines /First ${firstItem} 0 R ` +
`/Last ${firstItem + pageCount - 1} 0 R /Count ${pageCount} >>`,
});
for (let i = 0; i < pageCount; i++) {
const parts = [
`/Title (Chapter ${i + 1})`,
`/Parent ${outlinesRef} 0 R`,
`/Dest [${firstPage + i} 0 R /Fit]`,
];
if (i > 0) parts.push(`/Prev ${firstItem + i - 1} 0 R`);
if (i < pageCount - 1) parts.push(`/Next ${firstItem + i + 1} 0 R`);
objects.push({ body: `<< ${parts.join(' ')} >>` });
}
for (let i = 0; i < pageCount; i++) {
objects.push({
body:
`<< /Type /Page /Parent ${pagesRef} 0 R /MediaBox [0 0 300 300] ` +
`/Resources << /Font << /F1 ${fontRef} 0 R >> >> ` +
`/Contents ${firstContent + i} 0 R >>`,
});
}
for (let i = 0; i < pageCount; i++) {
const stream = enc.encode(
`BT /F1 18 Tf 1 0 0 1 40 200 Tm (Chapter ${i + 1}) Tj ET\n`
);
objects.push({ body: `<< /Length ${stream.length} >>`, stream });
}
objects.push({
body: '<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>',
});
return buildPdf(objects);
}