توليد تقارير PDF باستخدام TypeScript مع مكتبة pdf-lib
في تطوير الويب الحديث، غالبًا ما تنشأ الحاجة إلى إنشاء مستندات بصيغة PDF — من الإيصالات والفواتير البسيطة إلى التقارير التحليلية المعقدة مع الرسوم البيانية. TypeScript، كامتداد JavaScript ذو الكتابة الصارمة، يوفر إمكانيات ممتازة للعمل مع PDF. من بين العديد من المكتبات، تبرز pdf-lib — أداة قوية تعمل بالكامل من جانب العميل ولا تتطلب تبعيات خادم.
في هذه المقالة، سنشرح بالتفصيل كيفية استخدام pdf-lib لتوليد تقارير PDF باستخدام TypeScript، بما في ذلك التثبيت والعمليات الأساسية والتقنيات المتقدمة.
ما هي pdf-lib؟
pdf-lib هي مكتبة مفتوحة المصدر مكتوبة بلغة TypeScript، تتيح إنشاء وتحرير مستندات PDF مباشرة في المتصفح أو في بيئة Node.js. مزاياها الرئيسية:
- دعم كامل لـ TypeScript (جميع الأنواع مضمنة)
- العمل بدون تبعيات خارجية (لا حاجة لـ Puppeteer أو wkhtmltopdf)
- إمكانية العمل مع ملفات PDF الموجودة (دمج، إدراج صفحات)
- دعم السيريلية وأي خطوط
- تضمين الصور (PNG, JPG, SVG)
- إنشاء النماذج والتعليقات التوضيحية
التثبيت والإعداد
يتم التثبيت باستخدام مدير الحزم القياسي:
npm install pdf-lib# أوyarn add pdf-libللعمل مع TypeScript، لا حاجة لإجراءات إضافية — جميع الأنواع مضمنة بالفعل في الحزمة.
مثال أساسي: إنشاء تقرير بسيط
لننظر في إنشاء مستند PDF بسيط يحتوي على عنوان ونص:
import { PDFDocument, StandardFonts, rgb } from 'pdf-lib';
async function createSimpleReport() { // 1. إنشاء مستند PDF جديد const pdfDoc = await PDFDocument.create(); // 2. إضافة صفحة (حجم A4: 595.28 × 841.89 نقطة) const page = pdfDoc.addPage([595.28, 841.89]); // 3. تضمين الخط القياسي const font = await pdfDoc.embedFont(StandardFonts.Helvetica); // 4. رسم العنوان page.drawText('تقرير المبيعات للربع الأول 2025', { x: 50, y: 800, size: 24, font: font, color: rgb(0, 0.2, 0.6), }); // 5. رسم النص الرئيسي page.drawText('إجمالي الإيرادات: 1,234,567 روبل', { x: 50, y: 760, size: 14, font: font, color: rgb(0, 0, 0), }); // 6. حفظ المستند في Uint8Array const pdfBytes = await pdfDoc.save(); return pdfBytes;}العمل مع الجداول والبيانات
لإنشاء تقارير جدولية، ستحتاج إلى منطق أكثر قليلاً. إليك مثال لتوليد جدول بالبيانات:
import { PDFDocument, StandardFonts, rgb } from 'pdf-lib';
interface SaleRecord { product: string; quantity: number; price: number;}
async function createTableReport(data: SaleRecord[]) { const pdfDoc = await PDFDocument.create(); const page = pdfDoc.addPage([595.28, 841.89]); const font = await pdfDoc.embedFont(StandardFonts.Helvetica); const boldFont = await pdfDoc.embedFont(StandardFonts.HelveticaBold); const startX = 50; let startY = 800; const rowHeight = 25; const colWidths = [200, 100, 100, 100]; // الاسم، الكمية، السعر، الإجمالي // رأس الجدول const headers = ['الاسم', 'الكمية', 'السعر', 'الإجمالي']; page.drawText(headers[0], { x: startX, y: startY, size: 12, font: boldFont }); page.drawText(headers[1], { x: startX + colWidths[0], y: startY, size: 12, font: boldFont }); page.drawText(headers[2], { x: startX + colWidths[0] + colWidths[1], y: startY, size: 12, font: boldFont }); page.drawText(headers[3], { x: startX + colWidths[0] + colWidths[1] + colWidths[2], y: startY, size: 12, font: boldFont }); startY -= rowHeight; // صفوف البيانات for (const record of data) { const total = reco