Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
11 KiB
@suaveplan/pdf - Server-tier PDF 1.4 generation toolkit (Chunks A–D): typed PDF error registry, Zod boundary schemas, OpenTelemetry counters + histograms, unit conversion, hex/RGB colour utilities, page-size + margin types, hand-rolled PDF 1.4 binary writer (with FlateDecode + AbortSignal + injectable Clock), chainable content-stream encoder, document elements (text / table / image / divider) with Zod boundaries and AbortSignal propagation, style cascade with default theme, block-flow layout engine with header/footer slots, fluent DocumentBuilder, and orchestrating renderDocument entry point round-trippable via pdf-parse.
Server-tier PDF 1.4 generation toolkit. Chunk A foundation — pure
utilities + cross-cutting wiring (typed error registry, Zod boundary
schemas, OpenTelemetry counters + histograms, unit + colour utilities,
page-size + margin types). The low-level writer, element primitives,
layout engine, document builder, renderer, templates, and React preview
component land in subsequent chunks (B–E). See
enterprise-pdf/tasks.md
for the chunk roadmap.
Documentation tree
- colors — Colour utilities for
@suaveplan/pdf. The PDF specification stores colours as three floats in the0-1range (consu…- colors — Colour utilities for
@suaveplan/pdf. The PDF specification stores colours as three floats in the0-1range (consu…
- colors — Colour utilities for
- content-stream —
ContentStreamEncoderis the chainable builder for PDF 1.4 content streams used by every page emitted by `@suaveplan/p…- content-stream —
ContentStreamEncoderis the chainable builder for PDF 1.4 content streams used by every page emitted by `@suaveplan/p…
- content-stream —
- divider-element —
DividerElementrenders a horizontal or vertical rule into a PDF content stream. It is the lightweight separator primi…- divider-element —
DividerElementrenders a horizontal or vertical rule into a PDF content stream. It is the lightweight separator primi…
- divider-element —
- document-builder — The
DocumentBuilderprovides a chainable, deterministic API for assembling a PDF document tree without touching the l…- document-builder — The
DocumentBuilderprovides a chainable, deterministic API for assembling a PDF document tree without touching the l…
- document-builder — The
- error-codes — Declares the stable
PDF.*error-code registry and thePdfErrorclass used by every public function in `@suaveplan/p…- error-codes — Declares the stable
PDF.*error-code registry and thePdfErrorclass used by every public function in `@suaveplan/p…
- error-codes — Declares the stable
- image-element —
ImageElementis the bitmap primitive of@suaveplan/pdf. It accepts raw JPEG or PNG bytes, decodes them at construct…- image-element —
ImageElementis the bitmap primitive of@suaveplan/pdf. It accepts raw JPEG or PNG bytes, decodes them at construct…
- image-element —
- image-registry — The
ImageRegistryallocates and reuses PDF Image XObjects across the lifetime of a singlerenderDocumentcall. Each…- image-registry — The
ImageRegistryallocates and reuses PDF Image XObjects across the lifetime of a singlerenderDocumentcall. Each…
- image-registry — The
- layout-engine — The
LayoutEngineowns the block-flow geometry the renderer walks to position each element on the page. It computes ef…- layout-engine — The
LayoutEngineowns the block-flow geometry the renderer walks to position each element on the page. It computes ef…
- layout-engine — The
- pdf-writer —
PdfWriteris the low-level binary writer that emits valid PDF 1.4 byte streams. It manages indirect-object allocation…- pdf-writer —
PdfWriteris the low-level binary writer that emits valid PDF 1.4 byte streams. It manages indirect-object allocation…
- pdf-writer —
- render-pipeline — Internal pipeline helpers that the top-level
renderDocumentorchestrator delegates to. Splitting placement and slot-r…- render-pipeline — Internal pipeline helpers that the top-level
renderDocumentorchestrator delegates to. Splitting placement and slot-r…
- render-pipeline — Internal pipeline helpers that the top-level
- renderer —
renderDocumentis the top-level orchestrator that turns aDocumentAST (produced byDocumentBuilder) into a real…- renderer —
renderDocumentis the top-level orchestrator that turns aDocumentAST (produced byDocumentBuilder) into a real…
- renderer —
- schemas — Zod boundary schemas for the public surface of
@suaveplan/pdf. Every value crossing the package boundary from untrust…- schemas — Zod boundary schemas for the public surface of
@suaveplan/pdf. Every value crossing the package boundary from untrust…
- schemas — Zod boundary schemas for the public surface of
- style-resolver — The
StyleResolverresolves a fully-populatedPdfStylefrom the package defaults, an active theme, an optional base…- style-resolver — The
StyleResolverresolves a fully-populatedPdfStylefrom the package defaults, an active theme, an optional base…
- style-resolver — The
- table-element —
TableElementis the tabular-data primitive of@suaveplan/pdf. It accepts a typed column definition + row array and…- table-element —
TableElementis the tabular-data primitive of@suaveplan/pdf. It accepts a typed column definition + row array and…
- table-element —
- telemetry — OpenTelemetry surface for
@suaveplan/pdf. PDF generation is a load-bearing primitive in any system that emits invoice…- telemetry — OpenTelemetry surface for
@suaveplan/pdf. PDF generation is a load-bearing primitive in any system that emits invoice…
- telemetry — OpenTelemetry surface for
- invoice-template —
createInvoiceTemplate(data, options?)converts a typedInvoiceDatapayload into a renderer-readyDocumentfor pro…- invoice-template —
createInvoiceTemplate(data, options?)converts a typedInvoiceDatapayload into a renderer-readyDocumentfor pro…
- invoice-template —
- receipt-template —
createReceiptTemplate(data, options?)converts a typedReceiptDatapayload into a renderer-readyDocumentfor com…- receipt-template —
createReceiptTemplate(data, options?)converts a typedReceiptDatapayload into a renderer-readyDocumentfor com…
- receipt-template —
- report-template —
createReportTemplate(data, options?)converts a typedReportDatapayload into a renderer-readyDocumentfor multi…- report-template —
createReportTemplate(data, options?)converts a typedReportDatapayload into a renderer-readyDocumentfor multi…
- report-template —
- text-element —
TextElementis the flowed-text primitive of@suaveplan/pdf. It accepts a content string plus typography options (fo…- text-element —
TextElementis the flowed-text primitive of@suaveplan/pdf. It accepts a content string plus typography options (fo…
- text-element —
- types — Defines the page-size + page-config primitives used across every other module in
@suaveplan/pdf. PDF measurements are…- page-size — Defines the page-size + page-config primitives used across every other module in
@suaveplan/pdf. PDF measurements are…
- page-size — Defines the page-size + page-config primitives used across every other module in
- units — Unit-conversion utilities for
@suaveplan/pdf. PDF's native measurement is the point (1pt = 1/72 inch); every co…- units — Unit-conversion utilities for
@suaveplan/pdf. PDF's native measurement is the point (1pt = 1/72 inch); every co…
- units — Unit-conversion utilities for
Install
bun add @suaveplan/pdf
Surface (Chunk A)
| Subpath | Symbols |
|---|---|
@suaveplan/pdf/error-codes |
PDF_CODES, PdfError, asPdfError, PdfErrorCode |
@suaveplan/pdf/schemas |
UnitSchema, HexColorSchema, RgbColorSchema, MarginsSchema, PageConfigSchema, DocumentMetadataSchema, parseOrThrow, parseHexColor |
@suaveplan/pdf/telemetry |
createPdfObservability, six record* helpers, PdfObservability |
@suaveplan/pdf/units |
Unit, toPoints, fromPoints, convert, parseUnit, formatUnit |
@suaveplan/pdf/colors |
RgbColor, PdfColor, hexToRgb, rgbToPdfColor, hexToPdfColor, rgbToHex, lighten, darken, COLORS, isTransparent |
@suaveplan/pdf/types |
PageSize, PAGE_DIMENSIONS, Margins, DEFAULT_MARGINS, DocumentMetadata, PageConfig, DEFAULT_PAGE_CONFIG, DocumentDefinition, PageDefinition, ElementNode |
The package barrel @suaveplan/pdf re-exports every symbol above.
Example
import {
convert,
hexToPdfColor,
parseOrThrow,
PageConfigSchema,
PAGE_DIMENSIONS,
PageSize,
PDF_CODES,
} from "@suaveplan/pdf";
const a4 = PAGE_DIMENSIONS[PageSize.A4];
const inchInMm = convert(1, "in", "mm"); // ≈ 25.4
const accent = hexToPdfColor("#3366cc"); // PDF-native 0-1 triple
const page = parseOrThrow(
PageConfigSchema,
requestBody.page,
PDF_CODES.INVALID_PAGE_CONFIG,
"bad page config"
);
Dependencies
@suaveplan/error— typed-error base.@suaveplan/opentelemetry— counter / histogram helpers.@suaveplan/types— sharedClocketc. for later chunks.@opentelemetry/api— meter / tracer global API.zod— boundary validation.tslib— runtime helpers.
No third-party PDF dependency. Chunk B will keep the hand-rolled PDF 1.4
writer the upstream package ships with — the spec is small enough that
shipping a custom 200 LOC implementation is preferable to pulling in
pdfkit (~600 KB unpacked, CommonJS-only, includes unrelated PNG and
font subsystems).
Roadmap
- Chunk B —
pdf-writer/,content-stream/(low-level binary writer + content stream encoder). - Chunk C —
text-element/,table-element/,image-element/,divider-element/. - Chunk D —
layout-engine/,style-resolver/,document-builder/,renderer/. - Chunk E —
invoice-template/,receipt-template/,report-template/,pdf-preview/(React).
Quality gate
bunx turbo lint typecheck test build --filter=@suaveplan/pdf
bunx turbo test:coverage --filter=@suaveplan/pdf
100 / 100 / 100 / 100 Istanbul coverage on every Chunk A module.