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.
- package/CHANGELOG.md +351 -333
- package/README.md +3 -3
- package/dist/assets.d.ts +3 -0
- package/dist/assets.d.ts.map +1 -1
- package/dist/assets.js +119 -21
- package/dist/assets.js.map +1 -1
- package/dist/builder.d.ts +22 -1
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +38 -1
- package/dist/builder.js.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/fonts.d.ts.map +1 -1
- package/dist/fonts.js +36 -1
- package/dist/fonts.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +36 -15
- package/dist/index.js.map +1 -1
- package/dist/measure-blocks.d.ts +25 -0
- package/dist/measure-blocks.d.ts.map +1 -0
- package/dist/measure-blocks.js +1019 -0
- package/dist/measure-blocks.js.map +1 -0
- package/dist/measure-text.d.ts +53 -0
- package/dist/measure-text.d.ts.map +1 -0
- package/dist/measure-text.js +435 -0
- package/dist/measure-text.js.map +1 -0
- package/dist/measure.d.ts +15 -35
- package/dist/measure.d.ts.map +1 -1
- package/dist/measure.js +42 -1066
- package/dist/measure.js.map +1 -1
- package/dist/paginate.d.ts.map +1 -1
- package/dist/paginate.js +14 -12
- package/dist/paginate.js.map +1 -1
- package/dist/render-blocks.d.ts +24 -0
- package/dist/render-blocks.d.ts.map +1 -0
- package/dist/render-blocks.js +937 -0
- package/dist/render-blocks.js.map +1 -0
- package/dist/render-extras.d.ts +18 -0
- package/dist/render-extras.d.ts.map +1 -0
- package/dist/render-extras.js +325 -0
- package/dist/render-extras.js.map +1 -0
- package/dist/render-utils.d.ts +59 -0
- package/dist/render-utils.d.ts.map +1 -0
- package/dist/render-utils.js +219 -0
- package/dist/render-utils.js.map +1 -0
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +10 -1372
- package/dist/render.js.map +1 -1
- package/dist/rich-text.d.ts +4 -0
- package/dist/rich-text.d.ts.map +1 -1
- package/dist/rich-text.js +4 -0
- package/dist/rich-text.js.map +1 -1
- package/dist/types.d.ts +115 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +195 -15
- package/dist/validate.js.map +1 -1
- package/docs/screenshots/showcase-invoice.png +0 -0
- package/docs/screenshots/showcase-report.png +0 -0
- package/docs/screenshots/showcase-resume.png +0 -0
- 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.
|
|
19
|
-
|
|
20
|
-
###
|
|
21
|
-
|
|
22
|
-
- **`
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
- `
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
### Added (Phase
|
|
86
|
-
- `
|
|
87
|
-
-
|
|
88
|
-
-
|
|
89
|
-
- `
|
|
90
|
-
-
|
|
91
|
-
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
-
|
|
96
|
-
-
|
|
97
|
-
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
- `
|
|
105
|
-
-
|
|
106
|
-
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
- **
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
-
|
|
135
|
-
-
|
|
136
|
-
- `
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
- `
|
|
140
|
-
-
|
|
141
|
-
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
-
|
|
152
|
-
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
- `
|
|
158
|
-
-
|
|
159
|
-
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
-
|
|
167
|
-
-
|
|
168
|
-
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
-
|
|
174
|
-
-
|
|
175
|
-
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
-
|
|
181
|
-
-
|
|
182
|
-
-
|
|
183
|
-
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
- `
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
-
|
|
190
|
-
-
|
|
191
|
-
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
-
|
|
197
|
-
-
|
|
198
|
-
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
-
|
|
205
|
-
-
|
|
206
|
-
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
-
|
|
213
|
-
-
|
|
214
|
-
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
-
|
|
220
|
-
-
|
|
221
|
-
-
|
|
222
|
-
-
|
|
223
|
-
-
|
|
224
|
-
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
---
|
|
247
|
-
|
|
248
|
-
##
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
npm run
|
|
272
|
-
npm run
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
-
|
|
303
|
-
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
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 8D — Callout 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 8H — Inline 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.
|