pretext-pdf 0.1.1

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 (56) hide show
  1. package/CHANGELOG.md +242 -0
  2. package/LICENSE +21 -0
  3. package/README.md +402 -0
  4. package/dist/assets.d.ts +14 -0
  5. package/dist/assets.d.ts.map +1 -0
  6. package/dist/assets.js +182 -0
  7. package/dist/assets.js.map +1 -0
  8. package/dist/builder.d.ts +53 -0
  9. package/dist/builder.d.ts.map +1 -0
  10. package/dist/builder.js +129 -0
  11. package/dist/builder.js.map +1 -0
  12. package/dist/errors.d.ts +7 -0
  13. package/dist/errors.d.ts.map +1 -0
  14. package/dist/errors.js +13 -0
  15. package/dist/errors.js.map +1 -0
  16. package/dist/fonts.d.ts +21 -0
  17. package/dist/fonts.d.ts.map +1 -0
  18. package/dist/fonts.js +310 -0
  19. package/dist/fonts.js.map +1 -0
  20. package/dist/index.d.ts +29 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +154 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/measure.d.ts +53 -0
  25. package/dist/measure.d.ts.map +1 -0
  26. package/dist/measure.js +1029 -0
  27. package/dist/measure.js.map +1 -0
  28. package/dist/node-polyfill.d.ts +7 -0
  29. package/dist/node-polyfill.d.ts.map +1 -0
  30. package/dist/node-polyfill.js +82 -0
  31. package/dist/node-polyfill.js.map +1 -0
  32. package/dist/page-sizes.d.ts +13 -0
  33. package/dist/page-sizes.d.ts.map +1 -0
  34. package/dist/page-sizes.js +24 -0
  35. package/dist/page-sizes.js.map +1 -0
  36. package/dist/paginate.d.ts +15 -0
  37. package/dist/paginate.d.ts.map +1 -0
  38. package/dist/paginate.js +395 -0
  39. package/dist/paginate.js.map +1 -0
  40. package/dist/render.d.ts +12 -0
  41. package/dist/render.d.ts.map +1 -0
  42. package/dist/render.js +1028 -0
  43. package/dist/render.js.map +1 -0
  44. package/dist/rich-text.d.ts +14 -0
  45. package/dist/rich-text.d.ts.map +1 -0
  46. package/dist/rich-text.js +183 -0
  47. package/dist/rich-text.js.map +1 -0
  48. package/dist/types.d.ts +697 -0
  49. package/dist/types.d.ts.map +1 -0
  50. package/dist/types.js +2 -0
  51. package/dist/types.js.map +1 -0
  52. package/dist/validate.d.ts +3 -0
  53. package/dist/validate.d.ts.map +1 -0
  54. package/dist/validate.js +786 -0
  55. package/dist/validate.js.map +1 -0
  56. package/package.json +79 -0
@@ -0,0 +1,697 @@
1
+ /**
2
+ * pretext-pdf — Public and internal TypeScript types
3
+ */
4
+ import type { NamedPageSize } from './page-sizes.js';
5
+ /** Top-level document descriptor. Named PdfDocument to avoid clash with browser window.Document */
6
+ export interface PdfDocument {
7
+ /** Page size. Default: 'A4' (595×842 pt). Custom: [width, height] in pt. */
8
+ pageSize?: NamedPageSize | [number, number];
9
+ /** Page margins in pt. Default: all 72pt (1 inch). */
10
+ margins?: Partial<Margins>;
11
+ /** Default font family for body text. Default: 'Inter' */
12
+ defaultFont?: string;
13
+ /** Default font size in pt. Default: 12 */
14
+ defaultFontSize?: number;
15
+ /** Default line height in pt. Default: fontSize * 1.5 */
16
+ defaultLineHeight?: number;
17
+ /** Custom fonts to load and embed. Inter 400 is always available without specifying. */
18
+ fonts?: FontSpec[];
19
+ /** Header rendered at top of every page. Supports {{pageNumber}} and {{totalPages}}. */
20
+ header?: HeaderFooterSpec;
21
+ /** Footer rendered at bottom of every page. Supports {{pageNumber}} and {{totalPages}}. */
22
+ footer?: HeaderFooterSpec;
23
+ /** Watermark overlay rendered on every page behind content. Text or image. */
24
+ watermark?: WatermarkSpec;
25
+ /** Password protection and permission control for the output PDF. */
26
+ encryption?: EncryptionSpec;
27
+ /** PDF bookmark outline (sidebar navigation). Defaults to enabled. Set to false to disable bookmarks entirely. */
28
+ bookmarks?: false | BookmarkConfig;
29
+ /** Automatic word hyphenation using Liang's algorithm. Requires installing the matching `hyphenation.XX` npm package. */
30
+ hyphenation?: HyphenationConfig;
31
+ /** PDF document metadata written into the file's properties. */
32
+ metadata?: DocumentMetadata;
33
+ /** Document content elements, rendered top-to-bottom. */
34
+ content: ContentElement[];
35
+ }
36
+ export interface DocumentMetadata {
37
+ /** Document title shown in PDF viewer title bar. */
38
+ title?: string;
39
+ /** Author name. */
40
+ author?: string;
41
+ /** Subject / description. */
42
+ subject?: string;
43
+ /** Searchable keywords. */
44
+ keywords?: string[];
45
+ /** Producing application name. Default: 'pretext-pdf' */
46
+ creator?: string;
47
+ }
48
+ export interface Margins {
49
+ top: number;
50
+ bottom: number;
51
+ left: number;
52
+ right: number;
53
+ }
54
+ export interface FontSpec {
55
+ /** Font family name, e.g. 'Roboto'. Used in fontFamily fields. */
56
+ family: string;
57
+ /** Font weight. Default: 400 */
58
+ weight?: 400 | 700;
59
+ /** Font style. Default: 'normal' */
60
+ style?: 'normal' | 'italic';
61
+ /** Absolute file path (Node.js) or font bytes (browser). */
62
+ src: string | Uint8Array;
63
+ }
64
+ export interface HeaderFooterSpec {
65
+ /** Text content. Use {{pageNumber}} and {{totalPages}} as tokens. */
66
+ text: string;
67
+ /** Font size in pt. Default: 10 */
68
+ fontSize?: number;
69
+ /** Alignment. Default: 'center' */
70
+ align?: 'left' | 'center' | 'right';
71
+ /** Font family. Default: document.defaultFont */
72
+ fontFamily?: string;
73
+ /** Font weight. Default: 400 */
74
+ fontWeight?: 400 | 700;
75
+ /** Text color as 6-digit hex. Default: '#666666' */
76
+ color?: string;
77
+ }
78
+ export interface WatermarkSpec {
79
+ /** Text to render as watermark. Either text or image required. */
80
+ text?: string;
81
+ /** Absolute path or Uint8Array of a PNG/JPG image. Either text or image required. */
82
+ image?: string | Uint8Array;
83
+ /** Font family for text watermark. Default: document.defaultFont */
84
+ fontFamily?: string;
85
+ /** Font weight. Default: 400 */
86
+ fontWeight?: 400 | 700;
87
+ /** Font size in pt. Default: auto-computed from page diagonal */
88
+ fontSize?: number;
89
+ /** Color as 6-digit hex. Default: '#CCCCCC' */
90
+ color?: string;
91
+ /** Opacity 0.0–1.0. Default: 0.3 */
92
+ opacity?: number;
93
+ /** Rotation in degrees (counter-clockwise). Default: -45 */
94
+ rotation?: number;
95
+ }
96
+ export interface EncryptionSpec {
97
+ /** Password required to OPEN the document. If omitted, document opens without a password
98
+ * but permissions still apply. */
99
+ userPassword?: string;
100
+ /** Password for full unrestricted access. If omitted, a random owner password is generated
101
+ * (preventing tools from bypassing permissions). */
102
+ ownerPassword?: string;
103
+ /** Permissions granted to anyone who opens the document (with or without user password).
104
+ * Only applied when encryption is active. */
105
+ permissions?: {
106
+ /** Allow printing. Default: true */
107
+ printing?: boolean;
108
+ /** Allow copying text/graphics. Default: true */
109
+ copying?: boolean;
110
+ /** Allow modifying content. Default: false */
111
+ modifying?: boolean;
112
+ /** Allow adding/editing annotations and forms. Default: true */
113
+ annotating?: boolean;
114
+ };
115
+ }
116
+ export interface BookmarkConfig {
117
+ /** Minimum heading level to include in outline. Default: 1 */
118
+ minLevel?: 1 | 2 | 3 | 4;
119
+ /** Maximum heading level to include in outline. Default: 4 */
120
+ maxLevel?: 1 | 2 | 3 | 4;
121
+ }
122
+ export interface HyphenationConfig {
123
+ /** Language code matching the `hyphenation.XX` npm package. e.g. 'en-us', 'de', 'fr'. Required. */
124
+ language: string;
125
+ /** Minimum word length to attempt hyphenation. Default: 6 */
126
+ minWordLength?: number;
127
+ /** Minimum characters before the hyphen. Default: 2 */
128
+ leftMin?: number;
129
+ /** Minimum characters after the hyphen. Default: 3 */
130
+ rightMin?: number;
131
+ }
132
+ export type ContentElement = ParagraphElement | HeadingElement | SpacerElement | TableElement | ImageElement | SvgElement | ListElement | HorizontalRuleElement | PageBreakElement | CodeBlockElement | RichParagraphElement | BlockquoteElement | TocElement | TocEntryElement;
133
+ export interface ParagraphElement {
134
+ type: 'paragraph';
135
+ text: string;
136
+ /** Text direction: 'ltr' = left-to-right, 'rtl' = right-to-left, 'auto' = detect from character dominance. Default: 'auto' */
137
+ dir?: 'ltr' | 'rtl' | 'auto';
138
+ /** Font size in pt. Default: document.defaultFontSize */
139
+ fontSize?: number;
140
+ /** Line height in pt. Default: fontSize * 1.5 */
141
+ lineHeight?: number;
142
+ /** Font family name. Default: document.defaultFont */
143
+ fontFamily?: string;
144
+ /** Font weight. Default: 400 */
145
+ fontWeight?: 400 | 700;
146
+ /** Text color as 6-digit hex. Default: '#000000' */
147
+ color?: string;
148
+ /** Text alignment. Default: 'left' for LTR, 'right' for RTL (auto-detected) */
149
+ align?: 'left' | 'center' | 'right' | 'justify';
150
+ /** Background color as 6-digit hex. Drawn behind the text block. Default: none */
151
+ bgColor?: string;
152
+ /** Extra space below this element in pt. Default: 0 */
153
+ spaceAfter?: number;
154
+ /** Extra space above this element in pt. Default: 0 */
155
+ spaceBefore?: number;
156
+ /** If true, never break this block across pages. Default: false */
157
+ keepTogether?: boolean;
158
+ /** Underline all text in this element. Default: false */
159
+ underline?: boolean;
160
+ /** Strikethrough all text in this element. Default: false */
161
+ strikethrough?: boolean;
162
+ /** Clickable URL for the entire paragraph. Opens in browser when clicked. */
163
+ url?: string;
164
+ /** Number of columns for multi-column layout. Default: 1 (single column) */
165
+ columns?: number;
166
+ /** Gap between columns in pt. Default: 24 */
167
+ columnGap?: number;
168
+ /** Set to false to disable hyphenation for this element. Default: inherits from doc.hyphenation. */
169
+ hyphenate?: false;
170
+ }
171
+ export interface HeadingElement {
172
+ type: 'heading';
173
+ level: 1 | 2 | 3 | 4;
174
+ text: string;
175
+ /** Text direction: 'ltr' = left-to-right, 'rtl' = right-to-left, 'auto' = detect from character dominance. Default: 'auto' */
176
+ dir?: 'ltr' | 'rtl' | 'auto';
177
+ /** Font family override. Default: document.defaultFont */
178
+ fontFamily?: string;
179
+ /** Font weight override. Default: 700 */
180
+ fontWeight?: 400 | 700;
181
+ /** Font size override in pt. Default: per-level default (h1=28, h2=22, h3=18, h4=15) */
182
+ fontSize?: number;
183
+ /** Line height override in pt. Default: fontSize * 1.3 */
184
+ lineHeight?: number;
185
+ /** Text alignment. Default: 'left' for LTR, 'right' for RTL (auto-detected) */
186
+ align?: 'left' | 'center' | 'right' | 'justify';
187
+ /** Text color as 6-digit hex. Default: '#000000' */
188
+ color?: string;
189
+ /** Background color as 6-digit hex. Drawn behind the text block. Default: none */
190
+ bgColor?: string;
191
+ /** Extra space above this element in pt. Default: 0 */
192
+ spaceBefore?: number;
193
+ /** Extra space below this element in pt. Default: per-level default */
194
+ spaceAfter?: number;
195
+ /** If true, never break this block across pages. Default: true */
196
+ keepTogether?: boolean;
197
+ /** Underline all text in this element. Default: false */
198
+ underline?: boolean;
199
+ /** Strikethrough all text in this element. Default: false */
200
+ strikethrough?: boolean;
201
+ /** Set to false to exclude this heading from the PDF bookmark outline. Default: included. */
202
+ bookmark?: false;
203
+ /** Set to false to disable hyphenation for this element. Default: inherits from doc.hyphenation. */
204
+ hyphenate?: false;
205
+ /** Clickable URL for the entire heading. Opens in browser when clicked. */
206
+ url?: string;
207
+ /** Named anchor destination for internal links. Allows other spans to link to this heading via href: '#anchorId'. */
208
+ anchor?: string;
209
+ }
210
+ export interface SpacerElement {
211
+ type: 'spacer';
212
+ /** Height in pt */
213
+ height: number;
214
+ }
215
+ export interface TableElement {
216
+ type: 'table';
217
+ columns: ColumnDef[];
218
+ rows: TableRow[];
219
+ /** Number of rows treated as headers (repeated on continuation pages). Default: auto-detect rows with isHeader: true */
220
+ headerRows?: number;
221
+ /** Border color (hex). Default: '#cccccc' */
222
+ borderColor?: string;
223
+ /** Border thickness in pt. Default: 0.5 */
224
+ borderWidth?: number;
225
+ /** Background color for header rows (hex). Default: '#f5f5f5' */
226
+ headerBgColor?: string;
227
+ /** Cell font size in pt. Default: document.defaultFontSize */
228
+ fontSize?: number;
229
+ /** Horizontal cell padding in pt. Default: 8 */
230
+ cellPaddingH?: number;
231
+ /** Vertical cell padding in pt. Default: 6 */
232
+ cellPaddingV?: number;
233
+ /** Space below table in pt. Default: 0 */
234
+ spaceAfter?: number;
235
+ /** Space above table in pt. Default: 0 */
236
+ spaceBefore?: number;
237
+ }
238
+ export interface ColumnDef {
239
+ /** Fixed pt (e.g. 80), proportional fraction (e.g. '2*' or '*'), or 'auto' (shrink-to-content). */
240
+ width: number | string;
241
+ /** Column default text alignment. Default: 'left' */
242
+ align?: 'left' | 'center' | 'right';
243
+ }
244
+ export interface TableRow {
245
+ cells: TableCell[];
246
+ /** Mark row as a header (styled + repeated on continuation pages). Default: false */
247
+ isHeader?: boolean;
248
+ }
249
+ export interface TableCell {
250
+ text: string;
251
+ /** Text direction: 'ltr', 'rtl', or 'auto'. Default: 'auto' */
252
+ dir?: 'ltr' | 'rtl' | 'auto';
253
+ /** Overrides column alignment for this cell */
254
+ align?: 'left' | 'center' | 'right';
255
+ fontWeight?: 400 | 700;
256
+ /** Font family override for this cell. Default: document.defaultFont */
257
+ fontFamily?: string;
258
+ /** Font size override for this cell in pt. Default: table.fontSize ?? document.defaultFontSize */
259
+ fontSize?: number;
260
+ /** Text color (hex). Default: '#000000' */
261
+ color?: string;
262
+ /** Cell background color (hex). Optional — overrides row/table default. */
263
+ bgColor?: string;
264
+ /** Number of columns this cell spans. Default: 1 */
265
+ colspan?: number;
266
+ }
267
+ export interface ImageElement {
268
+ type: 'image';
269
+ /** Absolute file path (Node.js) or raw bytes (browser/Node) */
270
+ src: string | Uint8Array;
271
+ /** Image format. Default: 'auto' (detected from magic bytes, then file extension). */
272
+ format?: 'png' | 'jpg' | 'auto';
273
+ /** Render width in pt. Omit to auto-size to contentWidth. */
274
+ width?: number;
275
+ /** Render height in pt. Omit to preserve aspect ratio. */
276
+ height?: number;
277
+ /** Horizontal alignment within content area. Default: 'left' */
278
+ align?: 'left' | 'center' | 'right';
279
+ /** Space below image in pt. Default: 0 */
280
+ spaceAfter?: number;
281
+ /** Space above image in pt. Default: 0 */
282
+ spaceBefore?: number;
283
+ }
284
+ export interface SvgElement {
285
+ type: 'svg';
286
+ /** SVG content string. Must be a valid SVG document. */
287
+ svg: string;
288
+ /** Rendered width in pt. Default: available content width */
289
+ width?: number;
290
+ /** Rendered height in pt. Auto-computed from SVG viewBox if not set */
291
+ height?: number;
292
+ /** Alignment within content area. Default: 'left' */
293
+ align?: 'left' | 'center' | 'right';
294
+ /** Space above element in pt. Default: 8 */
295
+ spaceBefore?: number;
296
+ /** Space below element in pt. Default: 8 */
297
+ spaceAfter?: number;
298
+ }
299
+ export interface ListElement {
300
+ type: 'list';
301
+ /** 'ordered' = "1. 2. 3.", 'unordered' = bullet point */
302
+ style: 'ordered' | 'unordered';
303
+ items: ListItem[];
304
+ /** Custom marker for unordered lists. Default: '•' */
305
+ marker?: string;
306
+ /** Left indent in pt. Default: 20 */
307
+ indent?: number;
308
+ /** Width reserved for marker column in pt. Default: 20 */
309
+ markerWidth?: number;
310
+ /** Font size in pt. Default: document.defaultFontSize */
311
+ fontSize?: number;
312
+ /** Line height in pt. Default: fontSize * 1.5 */
313
+ lineHeight?: number;
314
+ /** Space between list items in pt. Default: 4 */
315
+ itemSpaceAfter?: number;
316
+ /** Space below the entire list in pt. Default: 0 */
317
+ spaceAfter?: number;
318
+ /** Space above the entire list in pt. Default: 0 */
319
+ spaceBefore?: number;
320
+ /** Text color for all list items (hex). Default: '#000000' */
321
+ color?: string;
322
+ /**
323
+ * For ordered lists with nested items: how nested item counters behave.
324
+ * 'continue' — nested items continue the parent counter (1, 2, 3, 4...).
325
+ * 'restart' — nested items restart at 1, parent counter is unaffected.
326
+ * Default: 'continue'
327
+ */
328
+ nestedNumberingStyle?: 'continue' | 'restart';
329
+ }
330
+ export interface ListItem {
331
+ text: string;
332
+ /** Text direction: 'ltr', 'rtl', or 'auto'. Default: 'auto' */
333
+ dir?: 'ltr' | 'rtl' | 'auto';
334
+ /** Font weight for this item. Default: 400 */
335
+ fontWeight?: 400 | 700;
336
+ /** Nested items — 1 level deep maximum in Phase 2 */
337
+ items?: ListItem[];
338
+ }
339
+ export interface HorizontalRuleElement {
340
+ type: 'hr';
341
+ /** Line thickness in pt. Default: 0.5 */
342
+ thickness?: number;
343
+ /** Line color (hex). Default: '#cccccc' */
344
+ color?: string;
345
+ /** Space above line in pt. Default: 12 */
346
+ spaceAbove?: number;
347
+ /** Space below line in pt. Default: 12 */
348
+ spaceBelow?: number;
349
+ }
350
+ /** Forces a page break at this position. No-op if already at the top of a page. */
351
+ export interface PageBreakElement {
352
+ type: 'page-break';
353
+ }
354
+ export interface CodeBlockElement {
355
+ type: 'code';
356
+ /** Preformatted source code. Newlines and indentation are preserved. */
357
+ text: string;
358
+ /** Text direction. Code blocks should always be 'ltr' (logical order). Default: 'ltr' */
359
+ dir?: 'ltr' | 'rtl' | 'auto';
360
+ /**
361
+ * Font family for code text. Must be loaded in doc.fonts as a monospace TTF.
362
+ * There is no default — a font MUST be provided for code blocks.
363
+ * Recommended: JetBrains Mono, Fira Code, Courier Prime, etc.
364
+ */
365
+ fontFamily: string;
366
+ /** Font size in pt. Default: doc.defaultFontSize - 2 (slightly smaller than body text) */
367
+ fontSize?: number;
368
+ /** Line height in pt. Default: fontSize * 1.4 */
369
+ lineHeight?: number;
370
+ /** Background box color (hex). Default: '#f6f8fa' */
371
+ bgColor?: string;
372
+ /** Text color (hex). Default: '#24292f' */
373
+ color?: string;
374
+ /** Padding inside the background box on all 4 sides in pt. Default: 8 */
375
+ padding?: number;
376
+ /** Space below element in pt. Default: 12 */
377
+ spaceAfter?: number;
378
+ /** Space above element in pt. Default: 12 */
379
+ spaceBefore?: number;
380
+ /** If true, never break this block across pages. Default: false */
381
+ keepTogether?: boolean;
382
+ }
383
+ /**
384
+ * A paragraph composed of inline spans with mixed formatting (bold, italic, color).
385
+ * All spans must use the same fontSize — cross-size spans (subscript etc.) are Phase 4.
386
+ */
387
+ export interface RichParagraphElement {
388
+ type: 'rich-paragraph';
389
+ spans: InlineSpan[];
390
+ /** Text direction: 'ltr', 'rtl', or 'auto'. Default: 'auto' */
391
+ dir?: 'ltr' | 'rtl' | 'auto';
392
+ /** Font size in pt for all spans. Default: doc.defaultFontSize */
393
+ fontSize?: number;
394
+ /** Line height in pt. Default: fontSize * 1.5 */
395
+ lineHeight?: number;
396
+ /** Text alignment. Default: 'left' for LTR, 'right' for RTL (auto-detected) */
397
+ align?: 'left' | 'center' | 'right' | 'justify';
398
+ /** Background color as 6-digit hex. Drawn behind the text block. Default: none */
399
+ bgColor?: string;
400
+ /** Extra space above this element in pt. Default: 0 */
401
+ spaceBefore?: number;
402
+ /** Extra space below this element in pt. Default: 0 */
403
+ spaceAfter?: number;
404
+ /** If true, never break this block across pages. Default: false */
405
+ keepTogether?: boolean;
406
+ /** Number of columns for multi-column layout. Default: 1 (single column) */
407
+ columns?: number;
408
+ /** Gap between columns in pt. Default: 24 */
409
+ columnGap?: number;
410
+ }
411
+ export interface InlineSpan {
412
+ text: string;
413
+ /** Text direction for this span: 'ltr', 'rtl', or 'auto'. Default: 'auto' */
414
+ dir?: 'ltr' | 'rtl' | 'auto';
415
+ /** Font family. Default: doc.defaultFont */
416
+ fontFamily?: string;
417
+ /** Font weight. Default: 400 */
418
+ fontWeight?: 400 | 700;
419
+ /** Font style. Default: 'normal'. Requires italic variant in doc.fonts. */
420
+ fontStyle?: 'normal' | 'italic';
421
+ /** Text color (hex). Default: '#000000' */
422
+ color?: string;
423
+ /** Font size override in pt. When set, overrides the element-level fontSize for this span. Default: element fontSize */
424
+ fontSize?: number;
425
+ /** Underline the span text. Default: false */
426
+ underline?: boolean;
427
+ /** Draw a line through the middle of the span text. Default: false */
428
+ strikethrough?: boolean;
429
+ /** Clickable URL. Opens in browser when clicked in PDF viewer. Auto-applies blue color and underline. */
430
+ url?: string;
431
+ /** Internal anchor link: '#anchorId' to jump to a heading with matching anchor. Or external URL. Alias for url. */
432
+ href?: string;
433
+ }
434
+ /** A composed line from the rich-text compositor — contains multiple styled fragments */
435
+ export interface RichLine {
436
+ fragments: RichFragment[];
437
+ /** Total line content width in pt */
438
+ totalWidth: number;
439
+ /** Height of this line in pt. Computed as max(fragment.fontSize) * lineHeightRatio (Phase 5B.4) */
440
+ lineHeight: number;
441
+ }
442
+ /** A single styled run within a RichLine */
443
+ export interface RichFragment {
444
+ text: string;
445
+ fontKey: string;
446
+ fontSize: number;
447
+ color: string;
448
+ /** x-offset from the left edge of the text area in pt */
449
+ x: number;
450
+ /** Fragment width in pt */
451
+ width: number;
452
+ underline?: boolean;
453
+ strikethrough?: boolean;
454
+ url?: string;
455
+ href?: string;
456
+ }
457
+ export interface BlockquoteElement {
458
+ type: 'blockquote';
459
+ text: string;
460
+ /** Text direction: 'ltr', 'rtl', or 'auto'. Default: 'auto' */
461
+ dir?: 'ltr' | 'rtl' | 'auto';
462
+ /** Left border color (hex). Default: '#0070f3' */
463
+ borderColor?: string;
464
+ /** Left border width in pt. Default: 3 */
465
+ borderWidth?: number;
466
+ /** Background fill color (hex). Default: '#f8f9fa' */
467
+ bgColor?: string;
468
+ /** Text color (hex). Default: '#333333' */
469
+ color?: string;
470
+ /** Font family. Default: document.defaultFont */
471
+ fontFamily?: string;
472
+ /** Font weight. Default: 400 */
473
+ fontWeight?: 400 | 700;
474
+ /** Font style. Default: 'normal'. Requires italic variant in doc.fonts if set to 'italic'. */
475
+ fontStyle?: 'normal' | 'italic';
476
+ /** Font size in pt. Default: document.defaultFontSize */
477
+ fontSize?: number;
478
+ /** Line height in pt. Default: fontSize * 1.5 */
479
+ lineHeight?: number;
480
+ /** Shorthand for paddingH and paddingV. Sets both when they are not individually specified. Per-axis overrides take precedence. */
481
+ padding?: number;
482
+ /** Horizontal padding (left + right) inside the box in pt. Default: padding ?? 16 */
483
+ paddingH?: number;
484
+ /** Vertical padding (top + bottom) inside the box in pt. Default: padding ?? 10 */
485
+ paddingV?: number;
486
+ /** Text alignment. Default: 'left' */
487
+ align?: 'left' | 'center' | 'right' | 'justify';
488
+ /** Space above this element in pt. Default: 0 */
489
+ spaceBefore?: number;
490
+ /** Space below this element in pt. Default: 12 */
491
+ spaceAfter?: number;
492
+ /** If true, never break this block across pages. Default: false */
493
+ keepTogether?: boolean;
494
+ /** Underline all text in this element. Default: false */
495
+ underline?: boolean;
496
+ /** Strikethrough all text in this element. Default: false */
497
+ strikethrough?: boolean;
498
+ }
499
+ export interface TocElement {
500
+ type: 'toc';
501
+ /** TOC title. Default: 'Table of Contents' */
502
+ title?: string;
503
+ /** Whether to show the title. Default: true */
504
+ showTitle?: boolean;
505
+ /** Minimum heading level to include. Default: 1 */
506
+ minLevel?: 1 | 2 | 3 | 4;
507
+ /** Maximum heading level to include. Default: 3 */
508
+ maxLevel?: 1 | 2 | 3 | 4;
509
+ /** Font size for TOC entries. Default: doc.defaultFontSize */
510
+ fontSize?: number;
511
+ /** Font size for TOC title. Default: fontSize + 4 */
512
+ titleFontSize?: number;
513
+ /** Indentation per level in pt. Default: 16 */
514
+ levelIndent?: number;
515
+ /** Leader character between entry text and page number. Default: '.' */
516
+ leader?: string;
517
+ /** Space after each entry line in pt. Default: 4 */
518
+ entrySpacing?: number;
519
+ /** Font family for TOC. Default: doc.defaultFont */
520
+ fontFamily?: string;
521
+ /** Space before the entire TOC section. Default: 0 */
522
+ spaceBefore?: number;
523
+ /** Space after the entire TOC section. Default: 0 */
524
+ spaceAfter?: number;
525
+ }
526
+ /** Internal: used as element type for measured TOC entry rows */
527
+ export interface TocEntryElement {
528
+ type: 'toc-entry';
529
+ text: string;
530
+ pageNumber: number;
531
+ level: 1 | 2 | 3 | 4;
532
+ levelIndent: number;
533
+ leader: string;
534
+ fontFamily: string;
535
+ fontWeight: number;
536
+ }
537
+ /** Resolved per-element measurement result from Stage 3 */
538
+ export interface MeasuredBlock {
539
+ element: ContentElement;
540
+ /** Total height in pt (lineCount * lineHeight, spacer.height, table sum, image height, hr height) */
541
+ height: number;
542
+ /** Lines from Pretext layoutWithLines(). Empty array for spacers, tables, images, hr. */
543
+ lines: PretextLine[];
544
+ /** Resolved font size in pt. 0 for non-text elements. */
545
+ fontSize: number;
546
+ /** Resolved line height in pt. 0 for non-text elements. */
547
+ lineHeight: number;
548
+ /** Key into FontMap, e.g. "Inter-400-normal". '' for non-text elements. */
549
+ fontKey: string;
550
+ /** Resolved space after in pt */
551
+ spaceAfter: number;
552
+ /** Resolved space before in pt (headings, lists, tables, images) */
553
+ spaceBefore: number;
554
+ /** Only set when element.type === 'table' */
555
+ tableData?: MeasuredTableData;
556
+ /** Only set when element.type === 'image' */
557
+ imageData?: MeasuredImageData;
558
+ /** Only set for list item blocks (flattened from ListElement) */
559
+ listItemData?: ListItemData;
560
+ /** Only set when element.type === 'code'. Resolved padding in pt. */
561
+ codePadding?: number;
562
+ /** Only set when element.type === 'rich-paragraph'. Mixed-font composed lines. */
563
+ richLines?: RichLine[];
564
+ /** Only set when element.type === 'blockquote'. Resolved vertical padding in pt. */
565
+ blockquotePaddingV?: number;
566
+ /** Only set when element.type === 'blockquote'. Resolved horizontal padding in pt. */
567
+ blockquotePaddingH?: number;
568
+ /** Only set when element.type === 'blockquote'. Resolved left border width in pt. */
569
+ blockquoteBorderWidth?: number;
570
+ /** Only set when element has columns > 1. Multi-column layout metadata. */
571
+ columnData?: {
572
+ columnCount: number;
573
+ columnGap: number;
574
+ columnWidth: number;
575
+ linesPerColumn: number;
576
+ };
577
+ /** Set to true if this block is RTL (right-to-left text). Used to apply right-align default in render.ts. */
578
+ isRTL?: boolean;
579
+ /** Original logical-order text (for debugging / reference). Only set when isRTL=true. */
580
+ logicalText?: string;
581
+ /** Only set when element.type === 'toc-entry'. Rendering metadata for TOC entries. */
582
+ tocEntryData?: {
583
+ entryX: number;
584
+ pageStr: string;
585
+ leaderChar: string;
586
+ };
587
+ }
588
+ /** A single line from Pretext's layoutWithLines() */
589
+ export interface PretextLine {
590
+ text: string;
591
+ width: number;
592
+ }
593
+ /** A block sliced for a specific page */
594
+ export interface PagedBlock {
595
+ measuredBlock: MeasuredBlock;
596
+ /** Inclusive start index into measuredBlock.lines[] — for text elements */
597
+ startLine: number;
598
+ /** Exclusive end index into measuredBlock.lines[] — for text elements */
599
+ endLine: number;
600
+ /** Inclusive index into body rows (non-header rows) — for table elements */
601
+ startRow?: number;
602
+ /** Exclusive index into body rows — for table elements */
603
+ endRow?: number;
604
+ /** Y offset from top of the page content area in pt */
605
+ yFromTop: number;
606
+ }
607
+ /** One page's worth of content */
608
+ export interface RenderedPage {
609
+ pageIndex: number;
610
+ blocks: PagedBlock[];
611
+ }
612
+ /** Output of Stage 4 paginate() */
613
+ export interface PaginatedDocument {
614
+ pages: RenderedPage[];
615
+ totalPages: number;
616
+ /** Headings collected during pagination for bookmark generation. */
617
+ headings: Array<{
618
+ text: string;
619
+ level: 1 | 2 | 3 | 4;
620
+ pageIndex: number;
621
+ }>;
622
+ }
623
+ /** Resolved page geometry passed between stages */
624
+ export interface PageGeometry {
625
+ pageWidth: number;
626
+ pageHeight: number;
627
+ margins: Margins;
628
+ contentWidth: number;
629
+ contentHeight: number;
630
+ headerHeight: number;
631
+ footerHeight: number;
632
+ }
633
+ /** Maps font key → embedded PDFFont reference */
634
+ export type FontMap = Map<string, import('pdf-lib').PDFFont>;
635
+ /** Maps image key → embedded PDFImage reference */
636
+ export type ImageMap = Map<string, import('pdf-lib').PDFImage>;
637
+ export interface MeasuredTableData {
638
+ /** Resolved column widths in pt */
639
+ columnWidths: number[];
640
+ /** All rows including headers */
641
+ rows: MeasuredTableRow[];
642
+ /** How many rows at the top are header rows */
643
+ headerRowCount: number;
644
+ /** Sum of header row heights — used to reserve space on continuation pages */
645
+ headerRowHeight: number;
646
+ cellPaddingH: number;
647
+ cellPaddingV: number;
648
+ borderWidth: number;
649
+ borderColor: string;
650
+ headerBgColor: string;
651
+ }
652
+ export interface MeasuredTableRow {
653
+ cells: MeasuredTableCell[];
654
+ /** Max cell content height + 2*cellPaddingV */
655
+ height: number;
656
+ isHeader: boolean;
657
+ /** Column gap indices (0..colCount-2) where vertical lines should be drawn. Gaps spanned by merged cells are excluded. */
658
+ activeBoundaries: number[];
659
+ }
660
+ export interface MeasuredTableCell {
661
+ lines: PretextLine[];
662
+ fontSize: number;
663
+ lineHeight: number;
664
+ fontKey: string;
665
+ fontFamily: string;
666
+ align: 'left' | 'center' | 'right';
667
+ color: string;
668
+ bgColor?: string;
669
+ /** Number of columns this cell spans */
670
+ colspan: number;
671
+ /** Total width in pt after colspan expansion, including border-width between spanned columns */
672
+ mergedWidth: number;
673
+ /** RTL text detected in this cell (for alignment defaults) */
674
+ isRTL?: boolean;
675
+ }
676
+ export interface MeasuredImageData {
677
+ /** Key into ImageMap, e.g. 'img-3' */
678
+ imageKey: string;
679
+ /** Final render width in pt */
680
+ renderWidth: number;
681
+ /** Final render height in pt */
682
+ renderHeight: number;
683
+ align: 'left' | 'center' | 'right';
684
+ }
685
+ export interface ListItemData {
686
+ /** Marker string, e.g. "•" or "1." */
687
+ marker: string;
688
+ /** Left indent in pt before the marker */
689
+ indent: number;
690
+ /** Width of marker column in pt — body text starts after this */
691
+ markerWidth: number;
692
+ /** Resolved text color (hex) for this item */
693
+ color: string;
694
+ /** Resolved font weight for this item */
695
+ fontWeight: 400 | 700;
696
+ }
697
+ //# sourceMappingURL=types.d.ts.map