Some checks failed
Validation applicative / TypeScript, tests et build (push) Failing after 1m54s
40 lines
1.8 KiB
TypeScript
40 lines
1.8 KiB
TypeScript
import pdfParse from "pdf-parse/lib/pdf-parse.js";
|
|
|
|
type PdfTextItem = { str?: string; transform?: number[] };
|
|
type PdfPageData = { getTextContent: (options: { normalizeWhitespace: boolean; disableCombineTextItems: boolean }) => Promise<{ items: PdfTextItem[] }> };
|
|
|
|
/**
|
|
* Reconstruit les lignes en ordonnant les fragments de texte par coordonnées.
|
|
* Cette étape évite que les valeurs de colonnes distinctes (adresse, IBAN, etc.)
|
|
* soient concaténées dans l'intitulé de poste par l'extracteur PDF standard.
|
|
*/
|
|
export async function renderPayrollPage(pageData: unknown): Promise<string> {
|
|
const pdfPage = pageData as PdfPageData;
|
|
const textContent = await pdfPage.getTextContent({ normalizeWhitespace: false, disableCombineTextItems: false });
|
|
const fragments = textContent.items
|
|
.filter((item) => item.str && item.transform && item.transform.length >= 6)
|
|
.map((item) => ({ text: item.str!.trim(), x: item.transform![4]!, y: item.transform![5]! }))
|
|
.filter((item) => item.text.length > 0)
|
|
.sort((a, b) => Math.abs(b.y - a.y) > 0.75 ? b.y - a.y : a.x - b.x);
|
|
|
|
const lines: Array<{ y: number; items: Array<{ text: string; x: number }> }> = [];
|
|
fragments.forEach((fragment) => {
|
|
const previous = lines[lines.length - 1];
|
|
if (previous && Math.abs(previous.y - fragment.y) <= 0.75) {
|
|
previous.items.push({ text: fragment.text, x: fragment.x });
|
|
} else {
|
|
lines.push({ y: fragment.y, items: [{ text: fragment.text, x: fragment.x }] });
|
|
}
|
|
});
|
|
|
|
return `${lines
|
|
.map((line) => line.items.sort((a, b) => a.x - b.x).map((item) => item.text).join(" "))
|
|
.join("\n")}\f`;
|
|
}
|
|
|
|
/** Extrait le texte d'une liasse en préservant les limites de pages. */
|
|
export async function extractPayrollPdfText(pdf: Buffer): Promise<string> {
|
|
const parsed = await pdfParse(pdf, { pagerender: renderPayrollPage });
|
|
return parsed.text;
|
|
}
|