pols-pdf
v1.0.1
Published
Extiende pdfkit (TypeScript) con tablas paginadas automáticamente, celdas de texto con alineación y fuentes mixtas, e imágenes y rectángulos con bordes y radios independientes por lado.
Readme
Pols-Pdf
Clase en TypeScript/JavaScript que encapsula pdfkit para agregar
primitivas de maquetado que pdfkit no ofrece de forma nativa: rectángulos con bordes y esquinas
redondeadas independientes por lado, tablas con paginación automática, celdas con texto
carácter-por-carácter (wrap, alineación, espaciado, fuentes mixtas) e imágenes con ajuste
proportional/cover/stretch.
Instalación
npm install pols-pdfInicio rápido
import fs from 'fs'
import { PPdf } from 'pols-pdf'
const pdf = new PPdf({ title: 'Reporte' })
pdf.cell({ text: 'Hola mundo', height: 20 })
pdf.build().pipe(fs.createWriteStream('output.pdf'))build() cierra el documento y devuelve el PDFDocument de pdfkit (que ya es un
stream.Readable), listo para ser canalizado (pipe) a un archivo, a la respuesta HTTP, etc.
Constructor
new PPdf(params?: {
title?: string
page?: Partial<PPage>
template?: () => void
addFirstPage?: boolean
})title: título del documento (metadato PDF). También accesible/editable luego víapdf.title.page: configuración de página por defecto (size,layout,margins), verPPage.template: función que se ejecuta automáticamente cada vez que se agrega una página (addPage), útil para dibujar encabezados/pies de página repetidos.addFirstPage: si esfalse, no agrega la primera página automáticamente (por defectotrue).
El cursor
PPdf mantiene internamente un cursor { left, top } que la mayoría de los métodos de dibujo
leen como posición por defecto y actualizan después de dibujar. Se puede leer y mover manualmente:
pdf.getCursorLeftPosition()
pdf.getCursorTopPosition()
pdf.getBottomSpaceQuantity() // espacio restante hasta el borde inferior de la página
pdf.getPageWidth()
pdf.setCursorLeftPosition('left') // vuelve al margen izquierdo
pdf.setCursorLeftPosition(50)
pdf.moveCursorLeft(20)
pdf.setCursorTopPosition('top') // vuelve al margen superior
pdf.setCursorTopPosition(100)
pdf.moveCursorTop(20) // si autoJump (por defecto true) y se pasa del margen inferior, agrega una página nuevaPáginas
pdf.addPage({ size: 'LETTER', layout: 'landscape', margins: 30 })margins (como todos los parámetros de tipo *BoundParams en esta librería) acepta un único
número para los cuatro lados, o un objeto parcial { top?, right?, bottom?, left? }.
Rectángulos
pdf.rectangle({
left: 20,
top: 20,
width: 200,
height: 80,
fillColor: '#eeeeee',
border: true, // o { left, right, top, bottom } individuales
radius: 8, // o { leftTop, rightTop, rightBottom, leftBottom }
stroke: { width: 1, color: '#333333' }
})rectangleTo(params) dibuja un rectángulo desde la posición actual del cursor hasta el punto
{ left, top } indicado (ancho/alto se calculan como la diferencia con el cursor).
Celdas de texto (cell)
pdf.cell({
text: 'Texto de la celda',
width: 200,
height: 40, // o autojump: true si no se conoce el alto de antemano
padding: 6,
hAlign: 'center',
vAlign: 'center',
font: { size: 12, bold: true, color: '#111111' },
border: true,
fillColor: '#f5f5f5'
})textaceptastring,number,null/undefined, un objeto{ chars, font? }, o un arreglo de estos últimos para mezclar fuentes/estilos dentro de una misma celda.- Una celda necesita o bien
height(alto fijo) o bienautojump: true(el alto se calcula según el contenido y, si no entra en la página actual, el texto restante continúa automáticamente en una página nueva). - Si el contenido no entra en la página,
cell()agrega una página nueva y continúa dibujando el resto automáticamente.
Filas y tablas (row / table)
pdf.table({
width: 'full', // 'full' | 'auto' | número
border: true,
padding: 4,
rows: [
{
fillColor: '#dddddd',
cells: [
{ text: 'Nombre', weight: 2 },
{ text: 'Edad', weight: 1 },
]
},
{
cells: [
{ text: 'Ana', weight: 2 },
{ text: '30', weight: 1 },
]
}
]
})- Cada celda de una fila define su ancho con
width(número fijo) oweight(proporción del ancho disponible restante), nunca ambos. table()va maquetando fila por fila; en cuanto una fila no entra en la página actual, dibuja el buffer acumulado, agrega una página nueva y continúa con el resto — una tabla puede así abarcar varias páginas sin que el llamador tenga que ocuparse de la paginación.row()expone el mismo mecanismo para dibujar una única fila suelta (fuera de una tabla).
Imágenes
pdf.image({ filePath: 'logo.png', left: 20, top: 20, width: 120 })
pdf.image({
filePath: 'foto.jpg',
left: 20,
top: 20,
width: 200,
height: 120,
fill: 'cover', // 'stretch' | 'proportional' | 'cover'
hAlign: 'center',
vAlign: 'center'
})Fuentes
pdf.setFont({ name: 'Helvetica', bold: true, size: 14, color: '#000000' })Cambia la fuente activa del documento; los métodos de texto (cell, row, table) también
aceptan font por llamada (y por fragmento de texto individual dentro de text), sin necesidad
de llamar a setFont explícitamente.
Tipos con forma abreviada (*Params)
Los parámetros de borde, radio y márgenes/padding aceptan una forma abreviada además del objeto completo:
| Tipo | Forma corta | Forma completa |
|---|---|---|
| PBoundParams (padding, margins) | number (aplica a los 4 lados) | { top?, right?, bottom?, left? } |
| PRadiusParams (radius) | number | { leftTop?, rightTop?, rightBottom?, leftBottom? } |
| PBorderParams (border) | boolean | { leftTop?, top?, rightTop?, right?, rightBottom?, bottom?, leftBottom?, left? } |
| PBorderColorParams (stroke.color) | string (color aplicado a los 4/8 lados) | { top?, rightTop?, right?, rightBottom?, bottom?, leftBottom?, left?, leftTop? } |
Convención de nombres
Todas las clases y tipos exportados llevan el prefijo P (PPdf, PCell, PRowParams, etc.),
siguiendo la convención usada en los paquetes hermanos de este ecosistema: pols-date (PDate)
y pols-utils (PRecord, PUtilsNumber).
