Генерация PDF-отчётов на TypeScript с библиотекой PDF-Lib
В современной веб-разработке часто возникает необходимость создавать сложные PDF-документы: отчёты, счета, сертификаты или аналитические дашборды. TypeScript, благодаря строгой типизации, делает этот процесс надёжным и предсказуемым. Среди множества библиотек для работы с PDF на платформе Node.js и в браузере выделяется PDF-Lib — легковесный, мощный и полностью написанный на TypeScript инструмент.
PDF-Lib не требует установки дополнительных нативных зависимостей (в отличие от тяжеловесных решений вроде Puppeteer или wkhtmltopdf), работает как в Node.js, так и в браузере, и поддерживает все современные возможности PDF: встраивание шрифтов, изображений, создание форм, аннотаций и многое другое.
Установка и первый документ
Для начала работы достаточно установить пакет через npm:
npm install pdf-lib
Создадим простейший PDF-документ с текстом:
import { PDFDocument, StandardFonts, rgb } from 'pdf-lib';
async function createSimplePdf() {
// Создаём новый PDF-документ
const pdfDoc = await PDFDocument.create();
// Добавляем страницу (формат A4)
const page = pdfDoc.addPage([595.28, 841.89]); // A4 в пунктах
// Встраиваем стандартный шрифт
const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
// Рисуем текст
page.drawText('Привет, мир!', {
x: 50,
y: 700,
size: 30,
font: font,
color: rgb(0.2, 0.4, 0.8),
});
// Сохраняем документ в байты
const pdfBytes = await pdfDoc.save();
return pdfBytes;
}
// Пример использования
createSimplePdf().then((bytes) => {
// В Node.js можно записать в файл
// require('fs').writeFileSync('hello.pdf', bytes);
console.log('PDF создан! Размер:', bytes.length, 'байт');
});
Работа с русским текстом и кастомными шрифтами
Одна из ключевых задач при генерации отчётов на русском языке — правильное отображение кириллицы. Стандартные шрифты PDF (Helvetica, Times, Courier) не содержат кириллических глифов. Решение — встроить TrueType-шрифт с поддержкой Unicode.
import { PDFDocument, rgb } from 'pdf-lib';
import fontkit from '@pdf-lib/fontkit';
import fs from 'fs';
async function createRussianPdf() {
const pdfDoc = await PDFDocument.create();
// Регистрируем fontkit для работы с кастомными шрифтами
pdfDoc.registerFontkit(fontkit);
// Загружаем шрифт с кириллицей (например, Roboto)
const fontBytes = fs.readFileSync('Roboto-Regular.ttf');
const customFont = await pdfDoc.embedFont(fontBytes);
const page = pdfDoc.addPage([595.28, 841.89]);
page.drawText('Генерация отчёта на TypeScript', {
x: 50,
y: 750,
size: 24,
font: customFont,
color: rgb(0, 0, 0),
});
page.drawText('Дата: 2024-01-15', {
x: 50,
y: 700,
size: 14,
font: customFont,
color: rgb(0.3, 0.3, 0.3),
});
return await pdfDoc.save();
}
Создание таблиц и структурированных отчётов
PDF-Lib не имеет встроенного модуля для таблиц, но их легко реализовать вручную через рисование линий и позиционирование текста. Для удобства можно создать вспомогательную функцию:
interface TableCell {
text: string;
width: number;
height?: number;
align?: 'left' | 'center' | 'right';
}
async function drawTable(
page: PDFPage,
headers: TableCell[],
rows: TableCell[][],
startX: number,
startY: number,
font: PDFFont,
fontSize: number = 12
) {
const cellPadding = 5;
const rowHeight = fontSize + 2 * cellPadding;
let currentY = startY;
// Рисуем заголовки
let currentX = startX;
for (const header of headers) {
page.drawRectangle({
x: currentX,
y: currentY - rowHeight,
width: header.width,
height: rowHeight,
color: rgb(0.9, 0.9, 0.9),
borderColor: rgb(0.7, 0.7, 0.7),
borderWidth: 1,
});
page.drawText(header.text, {
x: currentX + cellPadding,
y: currentY - rowHeight + cellPadding,
size: fontSize,
font: font,
color: rgb(0, 0, 0),
});
currentX += header.width;
}
currentY -= rowHeight;
// Рисуем строки данных
for (const row of rows) {
currentX = Также в библиотеке
Конфигурация приложений PHP: библиотеки и инструменты для гибкой настройки
Elasticsearch клиент для Node.js: @elastic/elasticsearch