pretext-pdf 0.4.6 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CHANGELOG.md +351 -333
  2. package/README.md +3 -3
  3. package/dist/assets.d.ts +3 -0
  4. package/dist/assets.d.ts.map +1 -1
  5. package/dist/assets.js +119 -21
  6. package/dist/assets.js.map +1 -1
  7. package/dist/builder.d.ts +22 -1
  8. package/dist/builder.d.ts.map +1 -1
  9. package/dist/builder.js +38 -1
  10. package/dist/builder.js.map +1 -1
  11. package/dist/errors.d.ts +1 -1
  12. package/dist/errors.d.ts.map +1 -1
  13. package/dist/errors.js.map +1 -1
  14. package/dist/fonts.d.ts.map +1 -1
  15. package/dist/fonts.js +36 -1
  16. package/dist/fonts.js.map +1 -1
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +36 -15
  20. package/dist/index.js.map +1 -1
  21. package/dist/measure-blocks.d.ts +25 -0
  22. package/dist/measure-blocks.d.ts.map +1 -0
  23. package/dist/measure-blocks.js +1019 -0
  24. package/dist/measure-blocks.js.map +1 -0
  25. package/dist/measure-text.d.ts +53 -0
  26. package/dist/measure-text.d.ts.map +1 -0
  27. package/dist/measure-text.js +435 -0
  28. package/dist/measure-text.js.map +1 -0
  29. package/dist/measure.d.ts +15 -35
  30. package/dist/measure.d.ts.map +1 -1
  31. package/dist/measure.js +42 -1066
  32. package/dist/measure.js.map +1 -1
  33. package/dist/paginate.d.ts.map +1 -1
  34. package/dist/paginate.js +14 -12
  35. package/dist/paginate.js.map +1 -1
  36. package/dist/render-blocks.d.ts +24 -0
  37. package/dist/render-blocks.d.ts.map +1 -0
  38. package/dist/render-blocks.js +937 -0
  39. package/dist/render-blocks.js.map +1 -0
  40. package/dist/render-extras.d.ts +18 -0
  41. package/dist/render-extras.d.ts.map +1 -0
  42. package/dist/render-extras.js +325 -0
  43. package/dist/render-extras.js.map +1 -0
  44. package/dist/render-utils.d.ts +59 -0
  45. package/dist/render-utils.d.ts.map +1 -0
  46. package/dist/render-utils.js +219 -0
  47. package/dist/render-utils.js.map +1 -0
  48. package/dist/render.d.ts.map +1 -1
  49. package/dist/render.js +10 -1372
  50. package/dist/render.js.map +1 -1
  51. package/dist/rich-text.d.ts +4 -0
  52. package/dist/rich-text.d.ts.map +1 -1
  53. package/dist/rich-text.js +4 -0
  54. package/dist/rich-text.js.map +1 -1
  55. package/dist/types.d.ts +115 -5
  56. package/dist/types.d.ts.map +1 -1
  57. package/dist/validate.d.ts.map +1 -1
  58. package/dist/validate.js +195 -15
  59. package/dist/validate.js.map +1 -1
  60. package/docs/screenshots/showcase-invoice.png +0 -0
  61. package/docs/screenshots/showcase-report.png +0 -0
  62. package/docs/screenshots/showcase-resume.png +0 -0
  63. package/package.json +130 -128
package/CHANGELOG.md CHANGED
@@ -1,333 +1,351 @@
1
- # Changelog
2
-
3
- All notable changes to pretext-pdf are documented here.
4
- Format: [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/)
5
-
6
- ---
7
-
8
- ## [Unreleased]
9
-
10
- ### Planned (Phase 9+)
11
-
12
- - Phase 9A: Digital signatures (cryptographic PKCS#7 via `@signpdf/signpdf`)
13
- - Phase 9B: Image floats (text flowing alongside images — requires paginator rewrite)
14
- - Phase 9C: Font subsetting pre-computation (explicit glyph hints for icon fonts)
15
-
16
- ---
17
-
18
- ## [0.4.0] — 2026-04-08
19
-
20
- ### Breaking Changes
21
- - **Migrated from `pdf-lib` to `@cantoo/pdf-lib`** — `@cantoo/pdf-lib` is now a direct `dependency` (always installed). Previously it was an optional peer dependency required only for encryption. This removes the `ENCRYPTION_NOT_AVAILABLE` error code and the separate `npm install @cantoo/pdf-lib` installation step. Encryption now works out of the box.
22
- - **`ENCRYPTION_NOT_AVAILABLE` error code removed**encryption is now always available. Update any `switch` statements that handled this code.
23
-
24
- ### Why this change
25
- `pdf-lib` (the original) has not received a meaningful commit since November 2021. `@cantoo/pdf-lib` is the actively maintained fork (v2.6.5, 107+ releases, MIT license). pretext-pdf was already using `@cantoo/pdf-lib` for encryption — this commit makes it the single source of truth for all PDF operations.
26
-
27
- ### Added
28
- - `test/pretext-api-contract.test.ts` canary test that asserts `@chenglou/pretext` exports the exact functions pretext-pdf depends on. Breaks loudly if pretext changes its API.
29
- - `docs/ROADMAP.md` public multi-phase development plan
30
-
31
- ### Changed
32
- - `@chenglou/pretext` version pinned to exact `0.0.3` (no caret) — prevents surprise breaking changes from upstream auto-updates
33
- - `test:contract` script added — runs the pretext API contract test before the full test suite
34
- - All internal comments updated from `pdf-lib` to `@cantoo/pdf-lib`
35
-
36
- ---
37
-
38
- ## [0.3.1] — 2026-04-08
39
-
40
- ### Fixed
41
- - **Critical: Font resolution when installed as npm package** — `@fontsource/inter` is now resolved via `createRequire(import.meta.url)` instead of a hardcoded relative path. Previously, `path.join(__dirname, '..', 'node_modules', '@fontsource', 'inter', ...)` failed when npm hoisted the dependency to the consumer's top-level `node_modules`, causing `FONT_LOAD_FAILED` on every install. Now resolves correctly regardless of npm hoisting behavior.
42
-
43
- ---
44
-
45
- ## [0.3.0] — 2026-04-08
46
-
47
- ### Added (Phase 8B Interactive Forms)
48
- - New `form-field` element type — creates interactive AcroForm fields in PDFs
49
- - `fieldType: 'text' | 'checkbox' | 'radio' | 'dropdown' | 'button'`
50
- - `label` renders above the field as static text
51
- - Text fields: `defaultValue`, `multiline`, `placeholder`, `maxLength`
52
- - Checkboxes: `checked` initial state
53
- - Radio groups and dropdowns: `options` array, `defaultSelected`
54
- - `doc.flattenForms: true` — bakes all fields into static content
55
- - Custom `borderColor`, `backgroundColor`, `width`, `height`, `fontSize` per field
56
- - New error codes: `FORM_FIELD_NAME_DUPLICATE` (duplicate `name` across fields), `FORM_FLATTEN_FAILED`
57
- - Post-render `form.updateFieldAppearances()` ensures proper display in all PDF readers
58
- - 10 comprehensive tests covering all form field types
59
-
60
- ### Added (Phase 8E — Signature Placeholder)
61
- - `doc.signature` — visual signature box drawn on a specified page
62
- - Fields: `signerName`, `reason`, `location`, `x`, `y`, `width`, `height`, `page`, `borderColor`, `fontSize`
63
- - Draws signature line, date line, and optional text inside a bordered rectangle
64
- - `page` is 0-indexed, defaults to last page, clamps gracefully if out of range
65
- - 6 comprehensive tests
66
-
67
- ### Added (Phase 8D Callout Boxes)
68
- - New `callout` element type styled highlight box with optional title
69
- - Preset styles: `style: 'info'` (blue), `'warning'` (amber), `'tip'` (green), `'note'` (gray)
70
- - Optional `title` rendered bold above content with left border accent
71
- - Fully customizable: `backgroundColor`, `borderColor`, `color`, `titleColor`, `padding`
72
- - Paginates correctly across pages (reuses blockquote pagination logic)
73
- - 8 comprehensive tests
74
-
75
- ### Added (Phase 8F Document Metadata Extensions)
76
- - `doc.metadata.language` sets PDF `/Lang` catalog entry (BCP47 tag e.g. `'en-US'`, `'hi'`)
77
- - `doc.metadata.producer` — sets PDF producer field (e.g. `'MyApp v2.1'`)
78
- - Both fields validate as non-empty strings
79
- - 5 comprehensive tests
80
-
81
- ---
82
-
83
- ## [0.2.0] 2026-04-08
84
-
85
- ### Added (Phase 8HInline Formatting)
86
- - `verticalAlign: 'superscript' | 'subscript'` on `InlineSpan` in rich-paragraphs
87
- - Superscript renders at 65% font size, baseline shifted up by 40% of font size
88
- - Subscript renders at 65% font size, baseline shifted down by 20% of font size
89
- - `letterSpacing?: number` on `ParagraphElement`, `HeadingElement`, `RichParagraphElement` — extra pt between characters
90
- - `smallCaps?: boolean` on those same three element types — simulated via uppercase + 80% fontSize
91
- - Character-by-character rendering for letterSpacing (pdf-lib has no native spacing param)
92
- - 8 comprehensive tests covering all inline formatting functionality
93
-
94
- ### Added (Phase 8A Annotations/Comments)
95
- - New `comment` element type sticky note annotation at position in document
96
- - `annotation?: AnnotationSpec` on `ParagraphElement` and `HeadingElement` — attach note to element
97
- - Supports: `contents`, `author`, `color` (hex), `open` (popup default state)
98
- - Uses PDF `Subtype: 'Text'` annotation (sticky note icon in PDF viewers)
99
- - 8 comprehensive tests covering all annotation functionality
100
-
101
- ### Added (Phase 8C Document Assembly)
102
- - New `merge(pdfs: Uint8Array[])` exported function — combine pre-rendered PDFs
103
- - New `assemble(parts: AssemblyPart[])` exported function mix rendered docs + existing PDFs
104
- - `AssemblyPart` interface: `{ doc?: PdfDocument, pdf?: Uint8Array }`
105
- - New error codes: `ASSEMBLY_EMPTY`, `ASSEMBLY_FAILED`
106
- - 8 comprehensive tests covering all assembly functionality
107
-
108
- ### Fixed
109
- - **CI case-sensitivity bug**: `test/phase-7-integration.test.ts` used `'en-US'` (uppercase) for hyphenation language. On Linux CI (case-sensitive filesystem) this failed with `UNSUPPORTED_LANGUAGE`. Changed to `'en-us'` to match package name `hyphenation.en-us`.
110
-
111
- ---
112
-
113
- ## [0.1.1]2026-04-08
114
-
115
- ### Added
116
- - **Phase 8G: Hyperlinks** Complete link annotation support:
117
- - `paragraph.url` for external URI links on paragraphs
118
- - `heading.url` for external URI links on headings
119
- - `heading.anchor` for named PDF destinations (internal cross-references)
120
- - `InlineSpan.href` for external and internal `#anchorId` links in rich-paragraphs
121
- - `mailto:` scheme support for email links
122
- - GoTo annotations for internal anchor references
123
- - 9 comprehensive tests covering all hyperlink functionality
124
-
125
- ### Fixed
126
- - **Memory leak in test suite**: Removed module-level `_hypherCache` in `src/measure.ts` that accumulated ~188KB per language across 255+ test runs. Changed from cached Hypher instances to fresh instances per call (negligible performance impact, massive memory savings).
127
- - **Node.js version compatibility**: Replaced `--experimental-strip-types` with `tsx` runner to support Node.js 18.x, 20.x, and 22.x in CI
128
- - **Broken CI examples**: Removed references to non-existent Phase 8 example scripts from GitHub Actions workflow
129
- - **README examples mismatch**: Updated Examples section to only list 5 existing Phase 7 examples (watermark, bookmarks, toc, rtl, encryption)
130
- - **Test suite OOM issues**: Split large test files (paginate.test.ts) into paginate-basic.test.ts to work around Node.js `--experimental-strip-types` heap exhaustion bug on files >17KB
131
-
132
- ### Changed
133
- - `test:unit` now runs only `test/paginate-basic.test.ts` (fast, no canvas overhead)
134
- - Reorganized test scripts: `test:unit`, `test:validate`, `test:e2e`, `test:phases` for better memory management
135
- - Moved internal planning documentation to archive (preserved, not published)
136
- - `devDependencies`: Added `@napi-rs/canvas` explicitly (was missing, causing CI failures)
137
-
138
- ### Added
139
- - `CONTRIBUTING.md`: Development setup, TDD workflow, PR process guide
140
- - `CHENG_LOU_EMAIL_DRAFT.md`: Template for requesting endorsement from pretext creator
141
- - `examples/comparison-pdfmake.ts`: pdfmake version of invoice for typography comparison
142
-
143
- ---
144
-
145
- ## [0.1.0] 2026-04-07
146
-
147
- ### Added (Phase 7G Encryption)
148
- - `doc.encryption` configuration for password-protecting PDFs
149
- - User password and owner password support
150
- - Granular permission restrictions: printing, copying, modifying, annotating
151
- - Lazy-loads `@cantoo/pdf-lib` (optional peer dependency) — zero cost when not used
152
- - Error code: `ENCRYPTION_NOT_AVAILABLE` when encryption is requested but dependency not installed
153
-
154
- ### Added (Phase 7F RTL Text Support)
155
- - Right-to-left text support for Arabic, Hebrew, and other RTL languages
156
- - Unicode bidirectional text algorithm via `bidi-js`
157
- - `dir` attribute on text elements: `'ltr'` | `'rtl'` | `'auto'` for per-element control
158
- - RTL text works with headings, paragraphs, lists, tables, and all text elements
159
- - Automatic detection of mixed LTR/RTL content
160
-
161
- ### Added (Phase 7E — SVG Support)
162
- - `{ type: 'svg', svg: '<...' }` element for embedding SVG graphics
163
- - SVG rasterization via `@napi-rs/canvas`
164
- - ViewBox auto-sizing: automatic height calculation from viewBox aspect ratio
165
- - Explicit sizing: `width` and `height` parameters for precise control
166
- - Alignment options: `align: 'left' | 'center' | 'right'`
167
- - Multi-page support: SVGs paginate correctly across page breaks
168
- - Error code: `SVG_RENDER_FAILED` for SVG rasterization errors
169
-
170
- ### Added (Phase 7D Table of Contents)
171
- - `{ type: 'toc' }` element for automatic TOC generation
172
- - Two-pass rendering pipeline ensures accurate page numbers
173
- - Configurable: `title`, `showTitle`, `minLevel`/`maxLevel`, dot leaders, level indentation
174
- - Auto-indexed from heading structure (H1, H2, H3, etc.)
175
- - Supports custom formatting via `fontSize`, `color`, `spaceAfter` parameters
176
-
177
- ### Added (Phase 7C Hyphenation)
178
- - Automatic word hyphenation for better justified text layout
179
- - `doc.hyphenation: { language: 'en-US' }` for document-level config
180
- - Liang's algorithm via `hypher` package for accurate break points
181
- - Configurable: `minWordLength`, `leftMin`, `rightMin`, per-element `hyphenate: false` opt-out
182
- - Language support: includes `hyphenation.en-us` (additional languages via npm packages)
183
- - Error code: `UNSUPPORTED_LANGUAGE` when language not available
184
-
185
- ### Added (Phase 7B Watermarks)
186
- - `doc.watermark` for text or image watermarks on every page
187
- - Text watermarks: `text`, `fontSize`, `fontWeight`, `color`, `opacity`, `rotation`
188
- - Image watermarks: `image` (Uint8Array), `opacity`, `rotation`, `color` (tint)
189
- - Watermarks render behind content (lower z-index)
190
- - Rotation bounds: -360 rotation 360 degrees
191
- - Validation: must provide either text or image, never both required
192
-
193
- ### Added (Phase 7A Bookmarks / PDF Outline)
194
- - PDF sidebar bookmarks auto-generated from heading structure
195
- - Enabled by default: `bookmarks: true` or `bookmarks: { minLevel: 1, maxLevel: 3 }`
196
- - Level filtering: include/exclude heading levels from outline
197
- - Per-heading opt-out: `bookmark: false` on heading elements
198
- - Keyboard navigation: Cmd/Ctrl+Opt/Alt+O in PDF readers to toggle bookmark sidebar
199
-
200
- ### Added (Phase 6 Advanced Features)
201
- - Header and footer support with {{pageNumber}} and {{totalPages}} tokens
202
- - Text decoration: strikethrough, underline
203
- - Text alignment: left, center, right, justify
204
- - Line height control: custom line-height multipliers
205
- - Column layout with multi-column content flow
206
- - Tables with colspan/rowspan support
207
-
208
- ### Added (Phase 5 Rich Text / Builder API)
209
- - Fluent builder API for programmatic document construction
210
- - Rich text element with nested formatting (bold, italic, links)
211
- - Inline code and code blocks with syntax highlighting
212
- - Block quotes with custom styling
213
- - Horizontal rules (hr element)
214
- - Numbered and bulleted lists with nesting
215
-
216
- ### Added (Phases 1–4 Core Engine)
217
- - Core PDF generation via `pdf-lib`
218
- - Element types: paragraph, heading, table, image, list, code, blockquote
219
- - Font support: Inter bundled, custom TTF embedding
220
- - Document metadata: title, author, subject, keywords, created date
221
- - Page sizing: A4, A3, A5, Letter, Legal, or custom dimensions
222
- - Margins: top, bottom, left, right per page
223
- - Multi-page pagination with orphan/widow control
224
- - Image formats: PNG, JPG, WebP
225
- - Table features: custom column widths, cell padding, borders, header styling
226
- - Colors: hex color codes throughout (text, backgrounds, borders)
227
-
228
- ---
229
-
230
- ## Features by Phase
231
-
232
- | Phase | Feature | Status | Tests | Version |
233
- |-------|---------|--------|-------|---------|
234
- | 7A | Bookmarks / PDF Outline | ✅ Complete | 8 | 0.1.0 |
235
- | 7B | Watermarks | ✅ Complete | 8 | 0.1.0 |
236
- | 7C | Hyphenation | Complete | 10 | 0.1.0 |
237
- | 7D | Table of Contents | ✅ Complete | 10 | 0.1.0 |
238
- | 7E | SVG Support | Complete | 8 | 0.1.0 |
239
- | 7F | RTL Text Support | Complete | 12 | 0.1.0 |
240
- | 7G | Encryption | Complete | 7 | 0.1.0 |
241
- | Integration | Feature Combinations | ✅ Complete | 6 | 0.1.0 |
242
- | 6 | Advanced Features | ✅ Complete | — | 0.1.0 |
243
- | 5 | Rich Text / Builder API | Complete | — | 0.1.0 |
244
- | 1–4 | Core Engine | Complete | — | 0.1.0 |
245
-
246
- ---
247
-
248
- ## How to Use Examples
249
-
250
- All Phase 7 features have working examples in the `examples/` directory. Run them with:
251
-
252
- ```bash
253
- npm run example:watermark # Phase 7B Watermarks
254
- npm run example:bookmarks # Phase 7A Bookmarks
255
- npm run example:toc # Phase 7D Table of Contents
256
- npm run example:rtl # Phase 7F RTL Text Support
257
- npm run example:encryption # Phase 7G Encryption
258
- ```
259
-
260
- PDF output is written to `output/phase7-*.pdf`.
261
-
262
- ---
263
-
264
- ## Test Coverage
265
-
266
- All phases include comprehensive test coverage:
267
-
268
- ```bash
269
- npm test # Run all 75+ tests
270
- npm run test:unit # Unit tests only
271
- npm run test:e2e # End-to-end tests
272
- npm run test:visual # Visual regression tests
273
- ```
274
-
275
- ---
276
-
277
- ## Dependencies
278
-
279
- ### Required
280
- - `@chenglou/pretext` — Pretext text layout engine
281
- - `pdf-lib` — PDF document manipulation
282
- - `@fontsource/inter` — Font: Inter (bundled)
283
- - `bidi-js` — Bidirectional text algorithm (Phase 7F)
284
- - `hypher` Hyphenation algorithm (Phase 7C)
285
- - `hyphenation.en-us` — English hyphenation patterns (Phase 7C)
286
-
287
- ### Optional (Peer)
288
- - `@napi-rs/canvas` SVG rasterization (Phase 7E)
289
- - `@cantoo/pdf-lib` PDF encryption (Phase 7G)
290
-
291
- ---
292
-
293
- ## Architecture
294
-
295
- pretext-pdf uses a modular, layered architecture:
296
-
297
- ```
298
- render(doc) validate layout → paginate → render-pages → PDF bytes
299
- ```
300
-
301
- Each phase adds features orthogonally:
302
- - Phase 1–4: Core engine, pagination, typography
303
- - Phase 5: Rich text and builder patterns
304
- - Phase 6: Advanced layout and formatting
305
- - Phase 7: Security, internationalization, accessibility
306
-
307
- ---
308
-
309
- ## Future Roadmap
310
-
311
- Potential Phase 8+ features (not yet implemented):
312
- - Hyperlinks and anchors
313
- - Justified text alignment
314
- - Enhanced text decorations
315
- - Font subsetting for file size reduction
316
- - Browser compatibility improvements
317
- - Performance optimizations
318
-
319
- ---
320
-
321
- ## Contributing
322
-
323
- pretext-pdf is actively maintained. To report issues, request features, or contribute:
324
-
325
- 1. Check existing issues on the project repo
326
- 2. Write failing tests first (TDD)
327
- 3. Submit pull requests with test coverage ≥80%
328
-
329
- ---
330
-
331
- ## License
332
-
333
- Check LICENSE file in repository root.
1
+ # Changelog
2
+
3
+ All notable changes to pretext-pdf are documented here.
4
+ Format: [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/)
5
+
6
+ ---
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Planned (Phase 9+)
11
+
12
+ - Phase 9A: Digital signatures (cryptographic PKCS#7 via `@signpdf/signpdf`)
13
+ - Phase 9B: Image floats (text flowing alongside images — requires paginator rewrite)
14
+ - Phase 9C: Font subsetting pre-computation (explicit glyph hints for icon fonts)
15
+
16
+ ---
17
+
18
+ ## [0.5.2] — 2026-04-13
19
+
20
+ ### Added
21
+
22
+ - **`onImageLoadError` callback on `PdfDocument`**gives callers control over image load failures. Return `'skip'` to silently omit the image (preserves existing default behavior). Return `'throw'` to abort rendering with the original error. Previously, all image failures were silently downgraded to `console.warn` with no way to detect them programmatically.
23
+
24
+ ```typescript
25
+ await render({
26
+ content: [...],
27
+ onImageLoadError: (src, error) => {
28
+ myLogger.warn('Image skipped', { src, error })
29
+ return 'skip' // or 'throw' to abort
30
+ }
31
+ })
32
+ ```
33
+
34
+ ---
35
+
36
+ ## [0.4.0] — 2026-04-08
37
+
38
+ ### Breaking Changes
39
+ - **Migrated from `pdf-lib` to `@cantoo/pdf-lib`** — `@cantoo/pdf-lib` is now a direct `dependency` (always installed). Previously it was an optional peer dependency required only for encryption. This removes the `ENCRYPTION_NOT_AVAILABLE` error code and the separate `npm install @cantoo/pdf-lib` installation step. Encryption now works out of the box.
40
+ - **`ENCRYPTION_NOT_AVAILABLE` error code removed** — encryption is now always available. Update any `switch` statements that handled this code.
41
+
42
+ ### Why this change
43
+ `pdf-lib` (the original) has not received a meaningful commit since November 2021. `@cantoo/pdf-lib` is the actively maintained fork (v2.6.5, 107+ releases, MIT license). pretext-pdf was already using `@cantoo/pdf-lib` for encryption — this commit makes it the single source of truth for all PDF operations.
44
+
45
+ ### Added
46
+ - `test/pretext-api-contract.test.ts` — canary test that asserts `@chenglou/pretext` exports the exact functions pretext-pdf depends on. Breaks loudly if pretext changes its API.
47
+ - `docs/ROADMAP.md` public multi-phase development plan
48
+
49
+ ### Changed
50
+ - `@chenglou/pretext` version pinned to exact `0.0.3` (no caret) prevents surprise breaking changes from upstream auto-updates
51
+ - `test:contract` script added — runs the pretext API contract test before the full test suite
52
+ - All internal comments updated from `pdf-lib` to `@cantoo/pdf-lib`
53
+
54
+ ---
55
+
56
+ ## [0.3.1] 2026-04-08
57
+
58
+ ### Fixed
59
+ - **Critical: Font resolution when installed as npm package** — `@fontsource/inter` is now resolved via `createRequire(import.meta.url)` instead of a hardcoded relative path. Previously, `path.join(__dirname, '..', 'node_modules', '@fontsource', 'inter', ...)` failed when npm hoisted the dependency to the consumer's top-level `node_modules`, causing `FONT_LOAD_FAILED` on every install. Now resolves correctly regardless of npm hoisting behavior.
60
+
61
+ ---
62
+
63
+ ## [0.3.0] 2026-04-08
64
+
65
+ ### Added (Phase 8B — Interactive Forms)
66
+ - New `form-field` element type — creates interactive AcroForm fields in PDFs
67
+ - `fieldType: 'text' | 'checkbox' | 'radio' | 'dropdown' | 'button'`
68
+ - `label` renders above the field as static text
69
+ - Text fields: `defaultValue`, `multiline`, `placeholder`, `maxLength`
70
+ - Checkboxes: `checked` initial state
71
+ - Radio groups and dropdowns: `options` array, `defaultSelected`
72
+ - `doc.flattenForms: true` bakes all fields into static content
73
+ - Custom `borderColor`, `backgroundColor`, `width`, `height`, `fontSize` per field
74
+ - New error codes: `FORM_FIELD_NAME_DUPLICATE` (duplicate `name` across fields), `FORM_FLATTEN_FAILED`
75
+ - Post-render `form.updateFieldAppearances()` ensures proper display in all PDF readers
76
+ - 10 comprehensive tests covering all form field types
77
+
78
+ ### Added (Phase 8E Signature Placeholder)
79
+ - `doc.signature` visual signature box drawn on a specified page
80
+ - Fields: `signerName`, `reason`, `location`, `x`, `y`, `width`, `height`, `page`, `borderColor`, `fontSize`
81
+ - Draws signature line, date line, and optional text inside a bordered rectangle
82
+ - `page` is 0-indexed, defaults to last page, clamps gracefully if out of range
83
+ - 6 comprehensive tests
84
+
85
+ ### Added (Phase 8DCallout Boxes)
86
+ - New `callout` element type styled highlight box with optional title
87
+ - Preset styles: `style: 'info'` (blue), `'warning'` (amber), `'tip'` (green), `'note'` (gray)
88
+ - Optional `title` rendered bold above content with left border accent
89
+ - Fully customizable: `backgroundColor`, `borderColor`, `color`, `titleColor`, `padding`
90
+ - Paginates correctly across pages (reuses blockquote pagination logic)
91
+ - 8 comprehensive tests
92
+
93
+ ### Added (Phase 8F — Document Metadata Extensions)
94
+ - `doc.metadata.language` — sets PDF `/Lang` catalog entry (BCP47 tag e.g. `'en-US'`, `'hi'`)
95
+ - `doc.metadata.producer` — sets PDF producer field (e.g. `'MyApp v2.1'`)
96
+ - Both fields validate as non-empty strings
97
+ - 5 comprehensive tests
98
+
99
+ ---
100
+
101
+ ## [0.2.0]2026-04-08
102
+
103
+ ### Added (Phase 8HInline Formatting)
104
+ - `verticalAlign: 'superscript' | 'subscript'` on `InlineSpan` in rich-paragraphs
105
+ - Superscript renders at 65% font size, baseline shifted up by 40% of font size
106
+ - Subscript renders at 65% font size, baseline shifted down by 20% of font size
107
+ - `letterSpacing?: number` on `ParagraphElement`, `HeadingElement`, `RichParagraphElement` — extra pt between characters
108
+ - `smallCaps?: boolean` on those same three element types — simulated via uppercase + 80% fontSize
109
+ - Character-by-character rendering for letterSpacing (pdf-lib has no native spacing param)
110
+ - 8 comprehensive tests covering all inline formatting functionality
111
+
112
+ ### Added (Phase 8A — Annotations/Comments)
113
+ - New `comment` element type sticky note annotation at position in document
114
+ - `annotation?: AnnotationSpec` on `ParagraphElement` and `HeadingElement` — attach note to element
115
+ - Supports: `contents`, `author`, `color` (hex), `open` (popup default state)
116
+ - Uses PDF `Subtype: 'Text'` annotation (sticky note icon in PDF viewers)
117
+ - 8 comprehensive tests covering all annotation functionality
118
+
119
+ ### Added (Phase 8C Document Assembly)
120
+ - New `merge(pdfs: Uint8Array[])` exported function combine pre-rendered PDFs
121
+ - New `assemble(parts: AssemblyPart[])` exported function mix rendered docs + existing PDFs
122
+ - `AssemblyPart` interface: `{ doc?: PdfDocument, pdf?: Uint8Array }`
123
+ - New error codes: `ASSEMBLY_EMPTY`, `ASSEMBLY_FAILED`
124
+ - 8 comprehensive tests covering all assembly functionality
125
+
126
+ ### Fixed
127
+ - **CI case-sensitivity bug**: `test/phase-7-integration.test.ts` used `'en-US'` (uppercase) for hyphenation language. On Linux CI (case-sensitive filesystem) this failed with `UNSUPPORTED_LANGUAGE`. Changed to `'en-us'` to match package name `hyphenation.en-us`.
128
+
129
+ ---
130
+
131
+ ## [0.1.1] — 2026-04-08
132
+
133
+ ### Added
134
+ - **Phase 8G: Hyperlinks** Complete link annotation support:
135
+ - `paragraph.url` for external URI links on paragraphs
136
+ - `heading.url` for external URI links on headings
137
+ - `heading.anchor` for named PDF destinations (internal cross-references)
138
+ - `InlineSpan.href` for external and internal `#anchorId` links in rich-paragraphs
139
+ - `mailto:` scheme support for email links
140
+ - GoTo annotations for internal anchor references
141
+ - 9 comprehensive tests covering all hyperlink functionality
142
+
143
+ ### Fixed
144
+ - **Memory leak in test suite**: Removed module-level `_hypherCache` in `src/measure.ts` that accumulated ~188KB per language across 255+ test runs. Changed from cached Hypher instances to fresh instances per call (negligible performance impact, massive memory savings).
145
+ - **Node.js version compatibility**: Replaced `--experimental-strip-types` with `tsx` runner to support Node.js 18.x, 20.x, and 22.x in CI
146
+ - **Broken CI examples**: Removed references to non-existent Phase 8 example scripts from GitHub Actions workflow
147
+ - **README examples mismatch**: Updated Examples section to only list 5 existing Phase 7 examples (watermark, bookmarks, toc, rtl, encryption)
148
+ - **Test suite OOM issues**: Split large test files (paginate.test.ts) into paginate-basic.test.ts to work around Node.js `--experimental-strip-types` heap exhaustion bug on files >17KB
149
+
150
+ ### Changed
151
+ - `test:unit` now runs only `test/paginate-basic.test.ts` (fast, no canvas overhead)
152
+ - Reorganized test scripts: `test:unit`, `test:validate`, `test:e2e`, `test:phases` for better memory management
153
+ - Moved internal planning documentation to archive (preserved, not published)
154
+ - `devDependencies`: Added `@napi-rs/canvas` explicitly (was missing, causing CI failures)
155
+
156
+ ### Added
157
+ - `CONTRIBUTING.md`: Development setup, TDD workflow, PR process guide
158
+ - `CHENG_LOU_EMAIL_DRAFT.md`: Template for requesting endorsement from pretext creator
159
+ - `examples/comparison-pdfmake.ts`: pdfmake version of invoice for typography comparison
160
+
161
+ ---
162
+
163
+ ## [0.1.0] 2026-04-07
164
+
165
+ ### Added (Phase 7G Encryption)
166
+ - `doc.encryption` configuration for password-protecting PDFs
167
+ - User password and owner password support
168
+ - Granular permission restrictions: printing, copying, modifying, annotating
169
+ - Lazy-loads `@cantoo/pdf-lib` (optional peer dependency) — zero cost when not used
170
+ - Error code: `ENCRYPTION_NOT_AVAILABLE` when encryption is requested but dependency not installed
171
+
172
+ ### Added (Phase 7F RTL Text Support)
173
+ - Right-to-left text support for Arabic, Hebrew, and other RTL languages
174
+ - Unicode bidirectional text algorithm via `bidi-js`
175
+ - `dir` attribute on text elements: `'ltr'` | `'rtl'` | `'auto'` for per-element control
176
+ - RTL text works with headings, paragraphs, lists, tables, and all text elements
177
+ - Automatic detection of mixed LTR/RTL content
178
+
179
+ ### Added (Phase 7E SVG Support)
180
+ - `{ type: 'svg', svg: '<...' }` element for embedding SVG graphics
181
+ - SVG rasterization via `@napi-rs/canvas`
182
+ - ViewBox auto-sizing: automatic height calculation from viewBox aspect ratio
183
+ - Explicit sizing: `width` and `height` parameters for precise control
184
+ - Alignment options: `align: 'left' | 'center' | 'right'`
185
+ - Multi-page support: SVGs paginate correctly across page breaks
186
+ - Error code: `SVG_RENDER_FAILED` for SVG rasterization errors
187
+
188
+ ### Added (Phase 7D Table of Contents)
189
+ - `{ type: 'toc' }` element for automatic TOC generation
190
+ - Two-pass rendering pipeline ensures accurate page numbers
191
+ - Configurable: `title`, `showTitle`, `minLevel`/`maxLevel`, dot leaders, level indentation
192
+ - Auto-indexed from heading structure (H1, H2, H3, etc.)
193
+ - Supports custom formatting via `fontSize`, `color`, `spaceAfter` parameters
194
+
195
+ ### Added (Phase 7C Hyphenation)
196
+ - Automatic word hyphenation for better justified text layout
197
+ - `doc.hyphenation: { language: 'en-US' }` for document-level config
198
+ - Liang's algorithm via `hypher` package for accurate break points
199
+ - Configurable: `minWordLength`, `leftMin`, `rightMin`, per-element `hyphenate: false` opt-out
200
+ - Language support: includes `hyphenation.en-us` (additional languages via npm packages)
201
+ - Error code: `UNSUPPORTED_LANGUAGE` when language not available
202
+
203
+ ### Added (Phase 7B Watermarks)
204
+ - `doc.watermark` for text or image watermarks on every page
205
+ - Text watermarks: `text`, `fontSize`, `fontWeight`, `color`, `opacity`, `rotation`
206
+ - Image watermarks: `image` (Uint8Array), `opacity`, `rotation`, `color` (tint)
207
+ - Watermarks render behind content (lower z-index)
208
+ - Rotation bounds: -360 rotation 360 degrees
209
+ - Validation: must provide either text or image, never both required
210
+
211
+ ### Added (Phase 7A Bookmarks / PDF Outline)
212
+ - PDF sidebar bookmarks auto-generated from heading structure
213
+ - Enabled by default: `bookmarks: true` or `bookmarks: { minLevel: 1, maxLevel: 3 }`
214
+ - Level filtering: include/exclude heading levels from outline
215
+ - Per-heading opt-out: `bookmark: false` on heading elements
216
+ - Keyboard navigation: Cmd/Ctrl+Opt/Alt+O in PDF readers to toggle bookmark sidebar
217
+
218
+ ### Added (Phase 6 Advanced Features)
219
+ - Header and footer support with {{pageNumber}} and {{totalPages}} tokens
220
+ - Text decoration: strikethrough, underline
221
+ - Text alignment: left, center, right, justify
222
+ - Line height control: custom line-height multipliers
223
+ - Column layout with multi-column content flow
224
+ - Tables with colspan/rowspan support
225
+
226
+ ### Added (Phase 5 Rich Text / Builder API)
227
+ - Fluent builder API for programmatic document construction
228
+ - Rich text element with nested formatting (bold, italic, links)
229
+ - Inline code and code blocks with syntax highlighting
230
+ - Block quotes with custom styling
231
+ - Horizontal rules (hr element)
232
+ - Numbered and bulleted lists with nesting
233
+
234
+ ### Added (Phases 1–4 Core Engine)
235
+ - Core PDF generation via `pdf-lib`
236
+ - Element types: paragraph, heading, table, image, list, code, blockquote
237
+ - Font support: Inter bundled, custom TTF embedding
238
+ - Document metadata: title, author, subject, keywords, created date
239
+ - Page sizing: A4, A3, A5, Letter, Legal, or custom dimensions
240
+ - Margins: top, bottom, left, right per page
241
+ - Multi-page pagination with orphan/widow control
242
+ - Image formats: PNG, JPG, WebP
243
+ - Table features: custom column widths, cell padding, borders, header styling
244
+ - Colors: hex color codes throughout (text, backgrounds, borders)
245
+
246
+ ---
247
+
248
+ ## Features by Phase
249
+
250
+ | Phase | Feature | Status | Tests | Version |
251
+ |-------|---------|--------|-------|---------|
252
+ | 7A | Bookmarks / PDF Outline | ✅ Complete | 8 | 0.1.0 |
253
+ | 7B | Watermarks | Complete | 8 | 0.1.0 |
254
+ | 7C | Hyphenation | Complete | 10 | 0.1.0 |
255
+ | 7D | Table of Contents | ✅ Complete | 10 | 0.1.0 |
256
+ | 7E | SVG Support | Complete | 8 | 0.1.0 |
257
+ | 7F | RTL Text Support | ✅ Complete | 12 | 0.1.0 |
258
+ | 7G | Encryption | ✅ Complete | 7 | 0.1.0 |
259
+ | Integration | Feature Combinations | ✅ Complete | 6 | 0.1.0 |
260
+ | 6 | Advanced Features | ✅ Complete | — | 0.1.0 |
261
+ | 5 | Rich Text / Builder API | ✅ Complete | — | 0.1.0 |
262
+ | 1–4 | Core Engine | ✅ Complete | — | 0.1.0 |
263
+
264
+ ---
265
+
266
+ ## How to Use Examples
267
+
268
+ All Phase 7 features have working examples in the `examples/` directory. Run them with:
269
+
270
+ ```bash
271
+ npm run example:watermark # Phase 7B — Watermarks
272
+ npm run example:bookmarks # Phase 7A — Bookmarks
273
+ npm run example:toc # Phase 7D — Table of Contents
274
+ npm run example:rtl # Phase 7F — RTL Text Support
275
+ npm run example:encryption # Phase 7G — Encryption
276
+ ```
277
+
278
+ PDF output is written to `output/phase7-*.pdf`.
279
+
280
+ ---
281
+
282
+ ## Test Coverage
283
+
284
+ All phases include comprehensive test coverage:
285
+
286
+ ```bash
287
+ npm test # Run all 75+ tests
288
+ npm run test:unit # Unit tests only
289
+ npm run test:e2e # End-to-end tests
290
+ npm run test:visual # Visual regression tests
291
+ ```
292
+
293
+ ---
294
+
295
+ ## Dependencies
296
+
297
+ ### Required
298
+ - `@chenglou/pretext` Pretext text layout engine
299
+ - `pdf-lib` — PDF document manipulation
300
+ - `@fontsource/inter` — Font: Inter (bundled)
301
+ - `bidi-js` Bidirectional text algorithm (Phase 7F)
302
+ - `hypher` Hyphenation algorithm (Phase 7C)
303
+ - `hyphenation.en-us` English hyphenation patterns (Phase 7C)
304
+
305
+ ### Optional (Peer)
306
+ - `@napi-rs/canvas` — SVG rasterization (Phase 7E)
307
+ - `@cantoo/pdf-lib` — PDF encryption (Phase 7G)
308
+
309
+ ---
310
+
311
+ ## Architecture
312
+
313
+ pretext-pdf uses a modular, layered architecture:
314
+
315
+ ```
316
+ render(doc) → validate → layout → paginate → render-pages PDF bytes
317
+ ```
318
+
319
+ Each phase adds features orthogonally:
320
+ - Phase 1–4: Core engine, pagination, typography
321
+ - Phase 5: Rich text and builder patterns
322
+ - Phase 6: Advanced layout and formatting
323
+ - Phase 7: Security, internationalization, accessibility
324
+
325
+ ---
326
+
327
+ ## Future Roadmap
328
+
329
+ Potential Phase 8+ features (not yet implemented):
330
+ - Hyperlinks and anchors
331
+ - Justified text alignment
332
+ - Enhanced text decorations
333
+ - Font subsetting for file size reduction
334
+ - Browser compatibility improvements
335
+ - Performance optimizations
336
+
337
+ ---
338
+
339
+ ## Contributing
340
+
341
+ pretext-pdf is actively maintained. To report issues, request features, or contribute:
342
+
343
+ 1. Check existing issues on the project repo
344
+ 2. Write failing tests first (TDD)
345
+ 3. Submit pull requests with test coverage ≥80%
346
+
347
+ ---
348
+
349
+ ## License
350
+
351
+ Check LICENSE file in repository root.