{"id":49060595,"url":"https://github.com/ShipItAndPray/pretext-pdf","last_synced_at":"2026-05-06T06:01:36.794Z","repository":{"id":348053011,"uuid":"1196303426","full_name":"ShipItAndPray/pretext-pdf","owner":"ShipItAndPray","description":"PDF generation with proper text wrapping using Pretext + pdf-lib.","archived":false,"fork":false,"pushed_at":"2026-04-02T06:17:08.000Z","size":61,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-04-04T17:14:24.311Z","etag":null,"topics":["pretext","text-layout","typescript","typography"],"latest_commit_sha":null,"homepage":"https://shipitandpray.github.io/pretext-pdf/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ShipItAndPray.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-30T15:10:02.000Z","updated_at":"2026-04-02T06:17:13.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ShipItAndPray/pretext-pdf","commit_stats":null,"previous_names":["shipitandpray/pretext-pdf"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ShipItAndPray/pretext-pdf","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ShipItAndPray%2Fpretext-pdf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ShipItAndPray%2Fpretext-pdf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ShipItAndPray%2Fpretext-pdf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ShipItAndPray%2Fpretext-pdf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ShipItAndPray","download_url":"https://codeload.github.com/ShipItAndPray/pretext-pdf/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ShipItAndPray%2Fpretext-pdf/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32680890,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-06T02:33:58.958Z","status":"ssl_error","status_checked_at":"2026-05-06T02:33:39.611Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["pretext","text-layout","typescript","typography"],"created_at":"2026-04-20T02:00:28.099Z","updated_at":"2026-05-06T06:01:36.161Z","avatar_url":"https://github.com/ShipItAndPray.png","language":"TypeScript","funding_links":[],"categories":["Flagship Ecosystem Packages"],"sub_categories":[],"readme":"# @shipitandpray/pretext-pdf\n\n[![Live Demo](https://img.shields.io/badge/demo-live-brightgreen)](https://shipitandpray.github.io/pretext-pdf/) [![GitHub](https://img.shields.io/github/stars/ShipItAndPray/pretext-pdf?style=social)](https://github.com/ShipItAndPray/pretext-pdf)\n\n\u003e **[View Live Demo](https://shipitandpray.github.io/pretext-pdf/)**\n\nGenerate multi-page PDFs with proper text wrapping, pagination, and layout using [Pretext](https://github.com/chenglou/pretext) for measurement + [pdf-lib](https://github.com/Hopding/pdf-lib) for rendering.\n\n## The Problem\n\npdf-lib (the most popular JS PDF library) has **no text wrapping**. You call `page.drawText()` and it draws a single line. Multi-line text requires manual line breaking.\n\nPretext provides accurate, internationalized line breaking. **pretext-pdf** combines them for proper PDF generation.\n\n**Before (pdf-lib alone):**\n```\npage.drawText(longParagraph) // =\u003e one line that overflows off the page\n```\n\n**After (pretext-pdf):**\n```\ndoc.addText(longParagraph) // =\u003e wrapped, paginated, beautiful\n```\n\n## Install\n\n```bash\nnpm install @shipitandpray/pretext-pdf\n```\n\n## Quick Start\n\n```typescript\nimport { createPdf } from '@shipitandpray/pretext-pdf'\n\nconst doc = createPdf({\n  pageSize: 'A4',\n  margins: { top: 72, right: 72, bottom: 72, left: 72 },\n  defaultFont: 'Helvetica',\n  defaultFontSize: 12,\n  defaultLineHeight: 16,\n})\n\n// Title\nawait doc.addText('My Document', { fontSize: 24, bold: true, marginBottom: 12 })\n\n// Body text - auto-wraps and paginates\nawait doc.addText(longParagraph)\n\n// Multi-column layout\nawait doc.addText(anotherParagraph, { columns: 2, columnGap: 24 })\n\n// Table with auto-sized columns\nawait doc.addTable({\n  headers: ['Name', 'Description', 'Price'],\n  rows: data.map(d =\u003e [d.name, d.description, `$${d.price}`]),\n  columnWidths: 'auto',\n})\n\n// Image\nawait doc.addImage(pngBytes, { width: 200, align: 'center' })\n\n// Generate\nconst pdfBytes = await doc.build()\n```\n\n## API Reference\n\n### `createPdf(options?)`\n\nCreate a new PDF document builder.\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `pageSize` | `'A4' \\| 'Letter' \\| 'Legal' \\| 'A3' \\| 'A5' \\| 'Tabloid' \\| { width, height }` | `'Letter'` | Page dimensions in points |\n| `margins` | `{ top, right, bottom, left }` | `72` (1 inch) all sides | Page margins in points |\n| `defaultFont` | `StandardFont` | `'Helvetica'` | Default font |\n| `defaultFontSize` | `number` | `12` | Default font size in points |\n| `defaultLineHeight` | `number` | `16` | Default line height in points |\n\n### `doc.addText(text, options?)`\n\nAdd a text block with automatic word wrapping and pagination.\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `fontSize` | `number` | Document default | Font size in points |\n| `lineHeight` | `number` | Document default | Line height in points |\n| `font` | `StandardFont` | Document default | Font name |\n| `bold` | `boolean` | `false` | Use bold variant |\n| `italic` | `boolean` | `false` | Use italic variant |\n| `color` | `{ r, g, b }` | `{ r: 0, g: 0, b: 0 }` | Text color (0-255) |\n| `align` | `'left' \\| 'center' \\| 'right'` | `'left'` | Text alignment |\n| `marginTop` | `number` | `0` | Space above block |\n| `marginBottom` | `number` | `0` | Space below block |\n| `columns` | `number` | `1` | Number of columns |\n| `columnGap` | `number` | `24` | Gap between columns |\n\n### `doc.addTable(options)`\n\nAdd a table with optional auto-sized columns. Headers repeat on page breaks.\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `headers` | `string[]` | - | Header row cells |\n| `rows` | `string[][]` | **required** | Data rows |\n| `columnWidths` | `'auto' \\| number[]` | `'auto'` | Column widths |\n| `headerFont` | `StandardFont` | Cell font | Header font |\n| `headerFontSize` | `number` | Cell size | Header font size |\n| `cellFont` | `StandardFont` | Document default | Cell font |\n| `cellFontSize` | `number` | Document default | Cell font size |\n| `cellPadding` | `number` | `8` | Cell padding in points |\n| `borderWidth` | `number` | `0.5` | Border line width |\n| `borderColor` | `{ r, g, b }` | Black | Border color |\n| `headerBackground` | `{ r, g, b }` | - | Header row background |\n\n### `doc.addImage(imageBytes, options?)`\n\nAdd a PNG or JPEG image.\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `width` | `number` | Original width | Display width in points |\n| `height` | `number` | Proportional | Display height in points |\n| `align` | `'left' \\| 'center' \\| 'right'` | `'left'` | Horizontal alignment |\n| `type` | `'png' \\| 'jpg'` | Auto-detected | Image format |\n| `marginTop` | `number` | `0` | Space above image |\n| `marginBottom` | `number` | `0` | Space below image |\n\n### `doc.addPageBreak()`\n\nForce a new page.\n\n### `doc.build()`\n\nReturns `Promise\u003cUint8Array\u003e` of the PDF file bytes.\n\n## Page Sizes\n\n| Name | Width | Height | Notes |\n|------|-------|--------|-------|\n| Letter | 612pt | 792pt | 8.5 x 11 in |\n| A4 | 595pt | 842pt | 210 x 297 mm |\n| Legal | 612pt | 1008pt | 8.5 x 14 in |\n| A3 | 842pt | 1191pt | 297 x 420 mm |\n| A5 | 420pt | 595pt | 148 x 210 mm |\n| Tabloid | 792pt | 1224pt | 11 x 17 in |\n\nCustom sizes: `{ width: 612, height: 792 }` (in points, 72pt = 1 inch).\n\n## Available Fonts\n\n`Helvetica`, `HelveticaBold`, `HelveticaBoldOblique`, `HelveticaOblique`, `Courier`, `CourierBold`, `CourierBoldOblique`, `CourierOblique`, `TimesRoman`, `TimesRomanBold`, `TimesRomanBoldItalic`, `TimesRomanItalic`\n\n## Font Metrics: CSS px to PDF Points\n\nPretext measures text in CSS pixels (96 DPI). PDF uses points (72 DPI). The conversion:\n\n```\n1 CSS px = 0.75 PDF points\nScale factor: 72 / 96 = 0.75\n```\n\nThis is handled internally. You work in PDF points throughout the API.\n\n## Architecture\n\n```\nsrc/\n  PdfDocument.ts       -- Fluent document builder (createPdf)\n  PdfPage.ts           -- Page wrapper with layout helpers\n  TextBlock.ts         -- Text measurement via Pretext + rendering\n  TableBlock.ts        -- Table layout with auto-sized columns\n  ImageBlock.ts        -- Image embedding and placement\n  layout/\n    FlowLayout.ts      -- Vertical stacking + auto-pagination\n    ColumnLayout.ts    -- Multi-column text distribution\n    Paginator.ts       -- Page break calculation\n  fonts/\n    FontLoader.ts      -- PDF font loading + caching\n    fontMetrics.ts     -- px/pt conversion utilities\n  types.ts             -- All TypeScript types\n```\n\n## Demo\n\nOpen `demo/index.html` in a browser. Type text on the left, see a live PDF preview on the right. Download the generated PDF with one click.\n\n## Development\n\n```bash\nnpm install\nnpm run build    # Build ESM + CJS with tsup\nnpm test         # Run vitest tests\nnpm run dev      # Watch mode\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FShipItAndPray%2Fpretext-pdf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FShipItAndPray%2Fpretext-pdf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FShipItAndPray%2Fpretext-pdf/lists"}