# PDF Core

Building blocks for creating PDF documents in TypeScript/JavaScript.

No native dependencies — works in any JavaScript environment.

## Installation

```sh
npm install @ralfstx/pdf-core
```

## Quick Start

```ts
import { writeFile } from 'node:fs/promises';
import { PDFDocument, PDFPage, PDFStandardFont } from '@ralfstx/pdf-core';

// Create a font
const font = new PDFStandardFont('Helvetica');

// Create an A4 page and add text
const page = new PDFPage(595.28, 841.89);
page.contentStream
  .beginText()
  .setFontAndSize(font, 24)
  .moveTextPosition(50, page.height - 70)
  .showText('Hello, PDF!')
  .endText();

// Build the document and write to file
const doc = new PDFDocument();
doc.addPage(page);
await writeFile('output.pdf', doc.write());
```

## Features

- **Text** — Standard PDF fonts and embedded TrueType fonts with OpenType shaping, text measurement
- **Images** — JPEG and PNG embedding, including PNG transparency
- **Graphics** — Lines, rectangles, Bézier curves, fill/stroke, clipping paths
- **Colors** — RGB, grayscale, CMYK, and ICC color profiles with output intents
- **Graphics state** — Opacity, blend modes, line styles, transformations
- **Document metadata** — Title, author, dates, and XMP metadata with custom fragments
- **File attachments** — Embed arbitrary files in the PDF
- **Navigation** — Clickable links and named destinations
- **Compression** — Deflate compression, object streams, and cross-reference streams

## Usage

### Embedded Fonts

Use `PDFEmbeddedFont` to embed a TrueType font with full Unicode support and
OpenType text shaping:

```ts
import { readFile } from 'node:fs/promises';
import { PDFEmbeddedFont } from '@ralfstx/pdf-core';

const fontData = await readFile('MyFont.ttf');
const font = new PDFEmbeddedFont(fontData);

page.contentStream
  .beginText()
  .setFontAndSize(font, 16)
  .moveTextPosition(50, 750)
  .showPositionedText(font.shapeText('Difficult Waffles', { scriptTag: 'latn' }))
  .endText();
```

### Images

Embed JPEG and PNG images:

```ts
import { PDFImage } from '@ralfstx/pdf-core';

const jpeg = PDFImage.fromJpeg(await readFile('photo.jpg'));
const png = PDFImage.fromPng(await readFile('icon.png'));

page.contentStream.drawImageAt(jpeg, 50, 500, 200, 150);
page.contentStream.drawImageAt(png, 50, 300, 100, 100);
```

### Graphics

Draw shapes using the content stream's path operations:

```ts
const c = page.contentStream;

c.saveGraphicsState()
  .setLineWidth(2)
  .setStrokeRGB(0.2, 0.4, 0.8)
  .setFillRGB(0.9, 0.95, 1.0)
  .rect(50, 600, 200, 100)
  .fillAndStroke()
  .restoreGraphicsState();
```

### Document Metadata

```ts
const doc = new PDFDocument();
doc.setInfo({
  title: 'My Document',
  author: 'Jane Doe',
  creationDate: new Date(),
});
```

XMP metadata is generated automatically from the Info dictionary. To add
custom XMP properties, use `addXMPFragment()`:

```ts
doc.addXMPFragment({
  namespaceUri: 'http://ns.adobe.com/pdfx/1.3/',
  prefix: 'pdfx',
  unsafeInnerXML: '<pdfx:Company>Acme Corp</pdfx:Company>',
});
```

### File Attachments

```ts
doc.addEmbeddedFile({
  content: new TextEncoder().encode('Hello, World!'),
  fileName: 'note.txt',
  mimeType: 'text/plain',
});
```

## Examples

Runnable examples are in `examples/`.

```sh
npm run examples
```

## License

[MIT](LICENSE.txt)

## References

- [PDF 1.7 Reference](https://archive.org/details/pdf1.7/mode/1up)
