renderpdf-js 0.2.0 → 0.3.0

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/API.md ADDED
@@ -0,0 +1,204 @@
1
+ # Document API
2
+
3
+ RenderPDF.js provides three ways to create a PDF: `renderPDF()` for supported HTML,
4
+ `imageToPDF()` for image files, and `createDocument()` for programmatic drawing.
5
+ All return or finalize into the same immutable `RenderPDFResult` with `pageCount`,
6
+ `warnings`, `toBlob()`, `toUint8Array()` and `download()`.
7
+
8
+ ## Documents and fonts
9
+
10
+ ```ts
11
+ import { createDocument } from 'renderpdf-js';
12
+
13
+ const response = await fetch('/fonts/ReportSans-Regular.ttf');
14
+ if (!response.ok) throw new Error('The font could not be loaded.');
15
+
16
+ const document = await createDocument({
17
+ unit: 'mm',
18
+ format: 'A4',
19
+ fonts: [{ family: 'Report Sans', data: await response.arrayBuffer() }],
20
+ metadata: { title: 'Report' },
21
+ });
22
+ const page = document.addPage();
23
+ page.drawText('Příliš žluťoučký kůň', {
24
+ x: 15,
25
+ y: 25,
26
+ font: 'Report Sans',
27
+ fontSize: 12,
28
+ });
29
+ await (await document.toResult()).download('report.pdf');
30
+ ```
31
+
32
+ `createDocument()` is asynchronous because it prepares fonts. Drawing and
33
+ measurement are synchronous afterwards, except `drawImage()` and `appendPDF()`,
34
+ which must be awaited. The document API does not require a browser or font
35
+ registration in the DOM. Use `registerFont()` separately for HTML exports.
36
+
37
+ | Setting | Default | Meaning |
38
+ | ------------- | ----------------------- | ----------------------------------------------------------------------------- |
39
+ | `unit` | `'pt'` | `'pt'`, `'mm'` or `'px'` for coordinates and dimensions. |
40
+ | `format` | `'A4'` | `'A4'`, `'A3'`, `'Letter'` or `{ width, height }` in document units. |
41
+ | `orientation` | `'portrait'` | Landscape swaps the supplied base axes. |
42
+ | `fonts` | Standard PDF fonts | Static TTF/OTF programs with `family`, `data`, optional `weight` and `style`. |
43
+ | `metadata` | Title: `'RenderPDF.js'` | Unicode title, author, subject and keyword strings. |
44
+ | `signal` | — | Cooperative cancellation via `AbortSignal`. |
45
+
46
+ Coordinates start at the top-left. Text `y` is a **baseline**, while rectangle and
47
+ image `y` is a top edge. Font sizes always use **points**, independent of `unit`.
48
+ `1 mm = 72/25.4 pt`; `1 px = 0.75 pt`. Rotation uses clockwise degrees.
49
+
50
+ Helvetica, Times and Courier include regular, bold, italic and bold-italic faces.
51
+ Their character sets are limited. For Czech and other Unicode text, provide an
52
+ appropriate font program. Select an exact face using `font`, `fontWeight` and
53
+ `fontStyle`; missing fonts and glyphs fail explicitly. Fonts are not substituted.
54
+
55
+ ## Page management
56
+
57
+ `addPage(options?)` returns a page handle. It inherits document defaults; each page
58
+ can override its format and orientation. Documents start without an implicit page.
59
+
60
+ - `getPage(number)` and `getPages()` return existing handles in document order.
61
+ - `pageCount` reports the number of physical pages.
62
+ - `insertPage(number, options?)` inserts before a one-based position.
63
+ - `movePage(from, to)` reorders an existing page.
64
+ - `removePage(number)` removes an unreferenced page. Bookmark/link targets and
65
+ pages containing interactive fields cannot be removed; flatten fields first.
66
+ - `appendPDF(source, pageNumbers?)` imports supported native pages asynchronously.
67
+ - `addBookmark(title, { pageNumber, parent? })` creates a hierarchical page bookmark.
68
+ - `flattenForms()` replaces prepared form appearances with ordinary page content.
69
+ - `toResult()` finalizes once and reuses the completed result on later calls.
70
+
71
+ Page handles expose `width`, `height`, `rotation` and `setRotation(degrees)`.
72
+ Drawing coordinates are relative to the unrotated MediaBox; imported page origins
73
+ and `UserUnit` are normalized into physical document units. Crop boxes and view
74
+ rotation remain part of the page.
75
+ Page numbers are one-based. Removed handles cannot be drawn into. Bookmarks remain
76
+ attached to the same page when pages move. A finalized document cannot be edited.
77
+
78
+ ## Text, graphics and images
79
+
80
+ `document.measureText(text, options?)` returns `width`, `height`, `ascent` and
81
+ `descent` in document units, using the same exact font as drawing.
82
+
83
+ | Page method | Input |
84
+ | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
85
+ | `drawText(text, options)` | `x`, baseline `y`; optional font face, `fontSize`, `color`, `align`, `lineHeight`, `rotation`, `maxWidth`, `opacity` and `link`. |
86
+ | `drawLine(options)` | `x1`, `y1`, `x2`, `y2`; optional `color`, `width`, `opacity`. |
87
+ | `drawRectangle(options)` | `x`, `y`, `width`, `height` and paint settings. |
88
+ | `drawEllipse(options)` | Bounding rectangle and paint settings. |
89
+ | `drawCircle(options)` | Center `x`, `y`, `radius` and paint settings. |
90
+ | `drawSvgPath(path, options)` | SVG path data, `x`, `y`, optional `scale`, `rotation` and paint settings. |
91
+ | `drawImage(source, options)` | PNG/JPEG bytes, Blob, data URL, browser canvas/image; rectangle and optional rotation/opacity. **Await this call.** |
92
+
93
+ Paint settings are `fill`, `stroke`, `strokeWidth` and `opacity`. Colors accept
94
+ hexadecimal, `rgb()`/`rgba()` and common named colors. Unsupported colors fail
95
+ explicitly. Text line spacing defaults to `1.15` times the point size.
96
+ `drawSvgPath` draws native vector geometry; it does not interpret full SVG files.
97
+ Image placement uses the supplied rectangle and applies image orientation. For
98
+ multipage TIFF, use `imageToPDF()` and append its PDF result.
99
+
100
+ Paths use `moveTo()`, `lineTo()`, `curveTo()` and `closePath()`, followed by
101
+ `stroke()`, `fill()` or `fillAndStroke()`. `clip()` intersects the clip with the
102
+ current path; `discardPath()` ends the path afterwards. `clipRectangle()` combines
103
+ these steps. Use `saveGraphicsState()` and `restoreGraphicsState()` to bound
104
+ clipping and `transform([a,b,c,d,e,f])` changes.
105
+
106
+ Pending images, unfinished paths and unmatched graphics states prevent
107
+ finalization. Await each asynchronous image before further drawing on that page.
108
+
109
+ ## Links, notes and forms
110
+
111
+ ```ts
112
+ page.addLink('https://example.com/report', { x: 15, y: 10, width: 100, height: 20 });
113
+ page.addNote('Please review this value.', { x: 150, y: 30, width: 8, height: 8 });
114
+ page.addTextField(
115
+ 'name',
116
+ { x: 15, y: 50, width: 100, height: 12 },
117
+ {
118
+ value: 'Český text',
119
+ font: 'Report Sans',
120
+ fontSize: 12,
121
+ },
122
+ );
123
+ page.addCheckBox('approved', { x: 15, y: 70, width: 6, height: 6 }, { checked: true });
124
+ page.addDropdown('status', { x: 15, y: 90, width: 60, height: 12 }, ['Draft', 'Approved'], {
125
+ value: 'Draft',
126
+ });
127
+ ```
128
+
129
+ Field options include font face, `fontSize`, `textColor`, `borderColor`,
130
+ `backgroundColor`, `borderWidth`, `readOnly` and `required`. Text fields support
131
+ `multiline` and `maxLength`; dropdowns support `editable` and `multiselect`.
132
+ Field names must be unique. Supply a suitable font for Unicode appearances.
133
+ Fields are axis-aligned and reject nonidentity graphics transforms.
134
+ Field appearance colors must be opaque.
135
+ Links accept HTTP, HTTPS, mailto and telephone URLs; executable schemes are rejected.
136
+
137
+ For a left/right footer, draw independent text objects after the page count is known:
138
+
139
+ ```ts
140
+ for (const [index, output] of document.getPages().entries()) {
141
+ output.drawText('Printed by: Example', { x: 15, y: output.height - 8, fontSize: 8 });
142
+ output.drawText(`Page ${index + 1} of ${document.pageCount}`, {
143
+ x: output.width - 15,
144
+ y: output.height - 8,
145
+ fontSize: 8,
146
+ align: 'right',
147
+ });
148
+ }
149
+ ```
150
+
151
+ ## PDF composition
152
+
153
+ `mergePDFs(sources, options?)` creates one PDF in source/page order.
154
+ `extractPDFPages(source, pageNumbers, options?)` preserves the requested one-based
155
+ order, including repeats. `splitPDF(source, options?)` returns one result per page.
156
+ Inputs accept `File`/`Blob`, `ArrayBuffer`, `Uint8Array` and completed export results;
157
+ the application fetches URLs itself. Options support `metadata`, `signal` and
158
+ `onProgress` with stage-local counters.
159
+
160
+ Pages retain text, vectors, image resources, sizes, crop boxes and rotation.
161
+ Explicit internal page links are remapped to the new page references. Named
162
+ destinations, links to omitted pages, encrypted/malformed PDFs and interactive
163
+ AcroForm/XFA inputs fail explicitly. Flatten fields before composition.
164
+ Document-level outlines, signatures, attachments and original metadata are not copied.
165
+ Composition is limited to 1,000 pages, 128 MiB per input and 256 MiB total input.
166
+
167
+ ## DevExtreme adapter
168
+
169
+ ```ts
170
+ import { createJsPDFAdapter } from 'renderpdf-js';
171
+ import { exportDataGrid } from 'devextreme/pdf_exporter';
172
+
173
+ const doc = await createJsPDFAdapter({
174
+ unit: 'mm',
175
+ format: 'A4',
176
+ orientation: 'landscape',
177
+ fonts: [{ family: 'Report Sans', data: fontBytes }],
178
+ });
179
+ doc.setFont('Report Sans');
180
+ await exportDataGrid({ jsPDFDocument: doc, component: grid, selectedRowsOnly: true });
181
+ await doc.save('grid.pdf');
182
+ ```
183
+
184
+ The adapter is verified with DevExtreme 25.1.5. Its default unit is
185
+ `'mm'`, and it creates an initial page. Font metrics and drawing methods are
186
+ synchronous; ordered operations are flushed during asynchronous finalization.
187
+ Use `await doc.output('blob')`, `await doc.toBlob()` or `await doc.save(name)`.
188
+ Synchronous jsPDF output is not emulated. Fonts must be supplied to the factory;
189
+ VFS/runtime font registration and arbitrary jsPDF plugins are unsupported.
190
+
191
+ Supported methods include page selection/addition, font and color state, text
192
+ measurement/wrapping, text/line/rectangle/image drawing, clipping, graphics-state
193
+ save/restore and the exporter's unit/color compatibility properties. The adapter
194
+ does not expose all jsPDF APIs or its advanced scripting features.
195
+
196
+ Run the optional integration against your separately installed DevExtreme:
197
+
198
+ ```sh
199
+ # Set RENDERPDF_DEVEXTREME_DIR to the absolute installed devextreme package directory.
200
+ npm run test:devextreme
201
+ ```
202
+
203
+ The regular checks do not require DevExtreme. Its implementation is not copied
204
+ into RenderPDF.js, and it is not a runtime or development dependency of the package.