@nemu-ai/pdf 1.0.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/LICENSE +21 -0
- package/README.md +678 -0
- package/dist/document/constants.d.ts +11 -0
- package/dist/document/document.d.ts +112 -0
- package/dist/document/style.d.ts +25 -0
- package/dist/document/theme.d.ts +55 -0
- package/dist/document/types.d.ts +119 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +155478 -0
- package/dist/index.mjs +155459 -0
- package/dist/lib/vector.d.ts +55 -0
- package/package.json +49 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 nemu
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,678 @@
|
|
|
1
|
+
# @nemu-ai/pdf
|
|
2
|
+
|
|
3
|
+
A modern PDF generation library with vector-based positioning and theming support.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add @nemu-ai/pdf
|
|
9
|
+
# or
|
|
10
|
+
npm install @nemu-ai/pdf
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { Document, Theme, create_theme, vector } from "@nemu-ai/pdf";
|
|
17
|
+
|
|
18
|
+
const pdf = new Document({
|
|
19
|
+
page_size: "A4",
|
|
20
|
+
margin: 50,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// Load custom fonts
|
|
24
|
+
await pdf.load_font("Satoshi", "./fonts/satoshi.ttf");
|
|
25
|
+
|
|
26
|
+
// Create theme
|
|
27
|
+
const theme = create_theme("custom", {
|
|
28
|
+
colors: {
|
|
29
|
+
primary: "#1a365d",
|
|
30
|
+
text: "#1f2937",
|
|
31
|
+
background: "#ffffff",
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
pdf.set_theme(theme);
|
|
36
|
+
|
|
37
|
+
// Create page
|
|
38
|
+
const page = pdf.create_page(theme);
|
|
39
|
+
|
|
40
|
+
// Add text with vector position
|
|
41
|
+
page.text({
|
|
42
|
+
content: "Hello World",
|
|
43
|
+
position: vector(50, 100),
|
|
44
|
+
style: {
|
|
45
|
+
font_family: "Satoshi",
|
|
46
|
+
font_size: 24,
|
|
47
|
+
color: theme.get_color("primary"),
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Draw shapes with vectors
|
|
52
|
+
page.rect(
|
|
53
|
+
vector(50, 150), // position
|
|
54
|
+
vector(200, 100), // size
|
|
55
|
+
{ fill_color: "#f8fafc" }
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
// Save PDF
|
|
59
|
+
await pdf.build("output.pdf");
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Complete API Reference
|
|
63
|
+
|
|
64
|
+
### Document
|
|
65
|
+
|
|
66
|
+
The main PDF document class.
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
const doc = new Document(options?: DocumentOptions)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**DocumentOptions:**
|
|
73
|
+
```typescript
|
|
74
|
+
{
|
|
75
|
+
page_size?: "A4" | "Letter" | "Legal" | "Custom"
|
|
76
|
+
custom_dimensions?: { width: number; height: number }
|
|
77
|
+
margin?: number | { top: number; right: number; bottom: number; left: number }
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Methods:**
|
|
82
|
+
|
|
83
|
+
#### `load_font(name: string, path: string): Promise<void>`
|
|
84
|
+
Load a custom TrueType font.
|
|
85
|
+
```typescript
|
|
86
|
+
await doc.load_font("Satoshi", "./fonts/satoshi.ttf");
|
|
87
|
+
await doc.load_font("Roboto", "./fonts/roboto.ttf");
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
#### `load_font_sync(name: string, path: string): void`
|
|
91
|
+
Synchronous version of load_font.
|
|
92
|
+
```typescript
|
|
93
|
+
doc.load_font_sync("Satoshi", "./fonts/satoshi.ttf");
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
#### `load_image(name: string, path: string): Promise<void>`
|
|
97
|
+
Load an image for later use.
|
|
98
|
+
```typescript
|
|
99
|
+
await doc.load_image("logo", "./images/logo.png");
|
|
100
|
+
await doc.load_image("photo", "./images/photo.jpg");
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
#### `set_theme(theme: Theme): void`
|
|
104
|
+
Set the default theme for all pages.
|
|
105
|
+
```typescript
|
|
106
|
+
const theme = create_theme("my-theme", { colors: { primary: "#000" } });
|
|
107
|
+
doc.set_theme(theme);
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
#### `create_page(theme?: Theme): Page`
|
|
111
|
+
Create a new page. Uses default theme if none provided.
|
|
112
|
+
```typescript
|
|
113
|
+
const page1 = doc.create_page(); // Uses default theme
|
|
114
|
+
const page2 = doc.create_page(customTheme); // Uses specific theme
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
#### `build(path: string): Promise<void>`
|
|
118
|
+
Save the PDF to a file.
|
|
119
|
+
```typescript
|
|
120
|
+
await doc.build("output.pdf");
|
|
121
|
+
await doc.build("./documents/report.pdf");
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
### Page
|
|
127
|
+
|
|
128
|
+
Represents a single page in the PDF.
|
|
129
|
+
|
|
130
|
+
#### `text(options: TextOptions): void`
|
|
131
|
+
Add text to the page.
|
|
132
|
+
|
|
133
|
+
**TextOptions:**
|
|
134
|
+
```typescript
|
|
135
|
+
{
|
|
136
|
+
content: string // Required: text content
|
|
137
|
+
position?: Vector // Optional: position vector
|
|
138
|
+
style?: StyleProperties // Optional: inline styles
|
|
139
|
+
classname?: string // Optional: theme classname
|
|
140
|
+
width?: number // Optional: max width for wrapping
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Examples:**
|
|
145
|
+
```typescript
|
|
146
|
+
// Simple text at cursor position
|
|
147
|
+
page.text({ content: "Hello World" });
|
|
148
|
+
|
|
149
|
+
// Text at specific position
|
|
150
|
+
page.text({
|
|
151
|
+
content: "Title",
|
|
152
|
+
position: vector(50, 100)
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// Text with styling
|
|
156
|
+
page.text({
|
|
157
|
+
content: "Styled Text",
|
|
158
|
+
position: vector(50, 150),
|
|
159
|
+
style: {
|
|
160
|
+
font_family: "Satoshi",
|
|
161
|
+
font_size: 24,
|
|
162
|
+
color: "#1a365d",
|
|
163
|
+
font_weight: "bold"
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// Text using classname from theme
|
|
168
|
+
page.text({
|
|
169
|
+
content: "Body Text",
|
|
170
|
+
position: vector(50, 200),
|
|
171
|
+
classname: "body-text",
|
|
172
|
+
width: 400 // Wraps text to 400px width
|
|
173
|
+
});
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
#### `header(options: HeaderOptions): void`
|
|
177
|
+
Add a header (same as text but with larger default font).
|
|
178
|
+
|
|
179
|
+
**HeaderOptions:**
|
|
180
|
+
```typescript
|
|
181
|
+
{
|
|
182
|
+
text: string // Required: header text
|
|
183
|
+
position?: Vector // Optional: position vector
|
|
184
|
+
style?: StyleProperties // Optional: inline styles
|
|
185
|
+
classname?: string // Optional: theme classname
|
|
186
|
+
width?: number // Optional: max width
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**Examples:**
|
|
191
|
+
```typescript
|
|
192
|
+
page.header({ text: "Document Title" });
|
|
193
|
+
|
|
194
|
+
page.header({
|
|
195
|
+
text: "Chapter 1",
|
|
196
|
+
position: vector(50, 50),
|
|
197
|
+
style: { font_size: 32, color: theme.get_color("primary") }
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
#### `rect(position: Vector, size: Vector, style?: ShapeStyle): void`
|
|
202
|
+
Draw a rectangle.
|
|
203
|
+
|
|
204
|
+
**Examples:**
|
|
205
|
+
```typescript
|
|
206
|
+
// Simple rectangle
|
|
207
|
+
page.rect(vector(50, 100), vector(200, 100));
|
|
208
|
+
|
|
209
|
+
// Filled rectangle
|
|
210
|
+
page.rect(
|
|
211
|
+
vector(50, 100),
|
|
212
|
+
vector(200, 100),
|
|
213
|
+
{ fill_color: "#f8fafc" }
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
// Bordered rectangle
|
|
217
|
+
page.rect(
|
|
218
|
+
vector(50, 100),
|
|
219
|
+
vector(200, 100),
|
|
220
|
+
{
|
|
221
|
+
stroke_color: "#e2e8f0",
|
|
222
|
+
stroke_width: 2
|
|
223
|
+
}
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
// Rounded rectangle
|
|
227
|
+
page.rect(
|
|
228
|
+
vector(50, 100),
|
|
229
|
+
vector(200, 100),
|
|
230
|
+
{
|
|
231
|
+
fill_color: "#f8fafc",
|
|
232
|
+
border_radius: 10
|
|
233
|
+
}
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
// Semi-transparent
|
|
237
|
+
page.rect(
|
|
238
|
+
vector(50, 100),
|
|
239
|
+
vector(200, 100),
|
|
240
|
+
{
|
|
241
|
+
fill_color: "#000000",
|
|
242
|
+
opacity: 0.1
|
|
243
|
+
}
|
|
244
|
+
);
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
#### `image(options: ImageOptions): void`
|
|
248
|
+
Add an image.
|
|
249
|
+
|
|
250
|
+
**ImageOptions:**
|
|
251
|
+
```typescript
|
|
252
|
+
{
|
|
253
|
+
name: string // Required: image name (from load_image)
|
|
254
|
+
position?: Vector // Optional: position vector
|
|
255
|
+
width?: number // Optional: width in pixels
|
|
256
|
+
height?: number // Optional: height in pixels
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
**Examples:**
|
|
261
|
+
```typescript
|
|
262
|
+
await doc.load_image("logo", "./logo.png");
|
|
263
|
+
|
|
264
|
+
// Image at position
|
|
265
|
+
page.image({
|
|
266
|
+
name: "logo",
|
|
267
|
+
position: vector(50, 100),
|
|
268
|
+
width: 200
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
// Image at cursor
|
|
272
|
+
page.image({ name: "logo", width: 150 });
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
#### `container(position?: Vector): Container`
|
|
276
|
+
Create a container for grouping elements.
|
|
277
|
+
|
|
278
|
+
**Examples:**
|
|
279
|
+
```typescript
|
|
280
|
+
// Container at position
|
|
281
|
+
const container = page.container(vector(50, 100));
|
|
282
|
+
container.rect(vector(0, 0), vector(200, 100));
|
|
283
|
+
container.text({
|
|
284
|
+
content: "Inside container",
|
|
285
|
+
position: vector(10, 10)
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
// Container at cursor
|
|
289
|
+
const container = page.container();
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
#### `move_down(amount: number = 1): void`
|
|
293
|
+
Move cursor down by amount (1 unit = line height).
|
|
294
|
+
|
|
295
|
+
**Examples:**
|
|
296
|
+
```typescript
|
|
297
|
+
page.move_down(); // Move 1 line
|
|
298
|
+
page.move_down(2); // Move 2 lines
|
|
299
|
+
page.move_down(0.5); // Move half line
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
#### Cursor Methods
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
305
|
+
// Get cursor position
|
|
306
|
+
const cursor: Vector = page.get_cursor();
|
|
307
|
+
const x: number = page.get_cursor_x();
|
|
308
|
+
const y: number = page.get_cursor_y();
|
|
309
|
+
|
|
310
|
+
// Set cursor position
|
|
311
|
+
page.set_cursor(vector(100, 200));
|
|
312
|
+
page.set_cursor({ x: 100, y: 200 });
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
#### Dimension Methods
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
const width: number = page.get_width(); // Page width
|
|
319
|
+
const height: number = page.get_height(); // Page height
|
|
320
|
+
const contentWidth: number = page.get_content_width(); // Width minus margins
|
|
321
|
+
const contentHeight: number = page.get_content_height(); // Height minus margins
|
|
322
|
+
const marginLeft: number = page.get_margin_left();
|
|
323
|
+
const marginRight: number = page.get_margin_right();
|
|
324
|
+
const marginTop: number = page.get_margin_top();
|
|
325
|
+
const marginBottom: number = page.get_margin_bottom();
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
#### Text Measurement
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
const measurement = page.measure_text("Hello World", {
|
|
332
|
+
font_size: 14,
|
|
333
|
+
line_height: 1.5
|
|
334
|
+
});
|
|
335
|
+
// Returns: { width: number, height: number }
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
### Container
|
|
341
|
+
|
|
342
|
+
Groups elements with relative positioning.
|
|
343
|
+
|
|
344
|
+
#### `rect(position: Vector, size: Vector, style?: ShapeStyle): void`
|
|
345
|
+
Draw rectangle relative to container position.
|
|
346
|
+
|
|
347
|
+
```typescript
|
|
348
|
+
const container = page.container(vector(50, 50));
|
|
349
|
+
container.rect(vector(0, 0), vector(200, 100)); // At container origin
|
|
350
|
+
container.rect(vector(10, 10), vector(180, 80)); // Offset 10px
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
#### `text(options: TextOptions): void`
|
|
354
|
+
Add text relative to container position.
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
const container = page.container(vector(50, 50));
|
|
358
|
+
container.text({
|
|
359
|
+
content: "Title",
|
|
360
|
+
position: vector(10, 10) // 10px from container edge
|
|
361
|
+
});
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
#### `header(options: HeaderOptions): void`
|
|
365
|
+
Add header relative to container position.
|
|
366
|
+
|
|
367
|
+
```typescript
|
|
368
|
+
container.header({
|
|
369
|
+
text: "Card Title",
|
|
370
|
+
position: vector(10, 10)
|
|
371
|
+
});
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
#### `move_down(amount: number = 1): void`
|
|
375
|
+
Move cursor within container.
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
### Vector
|
|
380
|
+
|
|
381
|
+
2D vector for positioning.
|
|
382
|
+
|
|
383
|
+
#### Creation
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
import { vector, Vector } from "@nemu-ai/pdf";
|
|
387
|
+
|
|
388
|
+
// From coordinates
|
|
389
|
+
const v1 = vector(100, 200);
|
|
390
|
+
|
|
391
|
+
// From object
|
|
392
|
+
const v2 = vector({ x: 100, y: 200 });
|
|
393
|
+
const v3 = new Vector(100, 200);
|
|
394
|
+
const v4 = new Vector({ x: 100, y: 200 });
|
|
395
|
+
|
|
396
|
+
// Copy
|
|
397
|
+
const v5 = v1.copy();
|
|
398
|
+
|
|
399
|
+
// Static factory methods
|
|
400
|
+
const zero = Vector.zero(); // (0, 0)
|
|
401
|
+
const one = Vector.one(); // (1, 1)
|
|
402
|
+
const up = Vector.up(); // (0, -1)
|
|
403
|
+
const down = Vector.down(); // (0, 1)
|
|
404
|
+
const left = Vector.left(); // (-1, 0)
|
|
405
|
+
const right = Vector.right(); // (1, 0)
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
#### Operations
|
|
409
|
+
|
|
410
|
+
```typescript
|
|
411
|
+
const a = vector(10, 20);
|
|
412
|
+
const b = vector(5, 5);
|
|
413
|
+
|
|
414
|
+
// Addition
|
|
415
|
+
const c = a.add(b); // (15, 25)
|
|
416
|
+
|
|
417
|
+
// Subtraction
|
|
418
|
+
const d = a.subtract(b); // (5, 15)
|
|
419
|
+
|
|
420
|
+
// Multiplication
|
|
421
|
+
const e = a.multiply(2); // (20, 40)
|
|
422
|
+
|
|
423
|
+
// Division
|
|
424
|
+
const f = a.divide(2); // (5, 10)
|
|
425
|
+
|
|
426
|
+
// Distance
|
|
427
|
+
const dist = a.dist_to(b); // Distance between vectors
|
|
428
|
+
|
|
429
|
+
// Magnitude
|
|
430
|
+
const mag = a.magnitude(); // Vector length
|
|
431
|
+
|
|
432
|
+
// Normalization
|
|
433
|
+
const norm = a.normalize(); // Unit vector
|
|
434
|
+
|
|
435
|
+
// Rotation
|
|
436
|
+
const rotated = a.rotate(Math.PI / 2); // Rotate 90 degrees
|
|
437
|
+
|
|
438
|
+
// Lerp (interpolation)
|
|
439
|
+
const between = a.lerp(b, 0.5); // Halfway between a and b
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
#### Common Patterns
|
|
443
|
+
|
|
444
|
+
```typescript
|
|
445
|
+
// Center a rectangle
|
|
446
|
+
const pageCenter = vector(
|
|
447
|
+
page.get_content_width() / 2,
|
|
448
|
+
page.get_content_height() / 2
|
|
449
|
+
);
|
|
450
|
+
const boxSize = vector(200, 100);
|
|
451
|
+
const boxPos = pageCenter.subtract(boxSize.divide(2));
|
|
452
|
+
page.rect(boxPos, boxSize);
|
|
453
|
+
|
|
454
|
+
// Grid layout
|
|
455
|
+
const start = vector(50, 50);
|
|
456
|
+
const gap = vector(10, 10);
|
|
457
|
+
const itemSize = vector(100, 50);
|
|
458
|
+
|
|
459
|
+
for (let row = 0; row < 3; row++) {
|
|
460
|
+
for (let col = 0; col < 3; col++) {
|
|
461
|
+
const pos = start.add(
|
|
462
|
+
vector(col, row).multiply(itemSize.add(gap))
|
|
463
|
+
);
|
|
464
|
+
page.rect(pos, itemSize);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
---
|
|
470
|
+
|
|
471
|
+
### Theme
|
|
472
|
+
|
|
473
|
+
Centralized styling system.
|
|
474
|
+
|
|
475
|
+
#### `create_theme(name: string, definition: ThemeDefinition): Theme`
|
|
476
|
+
|
|
477
|
+
```typescript
|
|
478
|
+
const theme = create_theme("my-theme", {
|
|
479
|
+
colors: {
|
|
480
|
+
primary: "#1a365d",
|
|
481
|
+
secondary: "#2563eb",
|
|
482
|
+
accent: "#d97706",
|
|
483
|
+
background: "#ffffff",
|
|
484
|
+
text: "#1f2937",
|
|
485
|
+
text_secondary: "#4b5563",
|
|
486
|
+
border: "#e2e8f0",
|
|
487
|
+
// Any custom colors
|
|
488
|
+
brand_pink: "#ff69b4",
|
|
489
|
+
custom_color: "#123456"
|
|
490
|
+
},
|
|
491
|
+
fonts: {
|
|
492
|
+
heading: "Satoshi",
|
|
493
|
+
body: "Helvetica",
|
|
494
|
+
mono: "Courier"
|
|
495
|
+
},
|
|
496
|
+
spacing: {
|
|
497
|
+
xs: 5,
|
|
498
|
+
sm: 10,
|
|
499
|
+
md: 20,
|
|
500
|
+
lg: 30,
|
|
501
|
+
xl: 50
|
|
502
|
+
},
|
|
503
|
+
border_radius: {
|
|
504
|
+
sm: 5,
|
|
505
|
+
md: 10,
|
|
506
|
+
lg: 20
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
#### `define_classname(name: string, style: StyleProperties): void`
|
|
512
|
+
#### `define_classname(definitions: Array<string | StyleProperties>): void`
|
|
513
|
+
|
|
514
|
+
```typescript
|
|
515
|
+
// Single definition
|
|
516
|
+
theme.define_classname("title", {
|
|
517
|
+
font_family: "Satoshi",
|
|
518
|
+
font_size: 32,
|
|
519
|
+
color: theme.get_color("primary"),
|
|
520
|
+
font_weight: "bold"
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
// Multiple definitions
|
|
524
|
+
theme.define_classname([
|
|
525
|
+
"title", {
|
|
526
|
+
font_family: "Satoshi",
|
|
527
|
+
font_size: 32,
|
|
528
|
+
color: theme.get_color("primary"),
|
|
529
|
+
font_weight: "bold"
|
|
530
|
+
},
|
|
531
|
+
"subtitle", {
|
|
532
|
+
font_family: "Satoshi",
|
|
533
|
+
font_size: 24,
|
|
534
|
+
color: theme.get_color("text_secondary")
|
|
535
|
+
},
|
|
536
|
+
"body", {
|
|
537
|
+
font_family: "Helvetica",
|
|
538
|
+
font_size: 14,
|
|
539
|
+
color: theme.get_color("text"),
|
|
540
|
+
line_height: 1.6
|
|
541
|
+
},
|
|
542
|
+
"caption", {
|
|
543
|
+
font_family: "Helvetica",
|
|
544
|
+
font_size: 12,
|
|
545
|
+
color: theme.get_color("text_secondary"),
|
|
546
|
+
font_style: "italic"
|
|
547
|
+
}
|
|
548
|
+
]);
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
#### `get_color(key: string): string`
|
|
552
|
+
|
|
553
|
+
```typescript
|
|
554
|
+
const primary = theme.get_color("primary");
|
|
555
|
+
const custom = theme.get_color("brand_pink");
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
---
|
|
559
|
+
|
|
560
|
+
### StyleProperties
|
|
561
|
+
|
|
562
|
+
All style options available.
|
|
563
|
+
|
|
564
|
+
```typescript
|
|
565
|
+
interface StyleProperties {
|
|
566
|
+
// Font
|
|
567
|
+
font_family?: string
|
|
568
|
+
font_size?: number
|
|
569
|
+
font_weight?: "normal" | "bold" | number
|
|
570
|
+
font_style?: "normal" | "italic" | "oblique"
|
|
571
|
+
|
|
572
|
+
// Text
|
|
573
|
+
color?: string
|
|
574
|
+
text_align?: "left" | "center" | "right" | "justify"
|
|
575
|
+
text_transform?: "none" | "capitalize" | "uppercase" | "lowercase"
|
|
576
|
+
text_decoration?: "none" | "underline" | "line-through" | "overline"
|
|
577
|
+
line_height?: number
|
|
578
|
+
letter_spacing?: number
|
|
579
|
+
|
|
580
|
+
// Spacing
|
|
581
|
+
margin?: number | string
|
|
582
|
+
margin_top?: number | string
|
|
583
|
+
margin_right?: number | string
|
|
584
|
+
margin_bottom?: number | string
|
|
585
|
+
margin_left?: number | string
|
|
586
|
+
padding?: number | string
|
|
587
|
+
padding_top?: number | string
|
|
588
|
+
padding_right?: number | string
|
|
589
|
+
padding_bottom?: number | string
|
|
590
|
+
padding_left?: number | string
|
|
591
|
+
|
|
592
|
+
// Layout
|
|
593
|
+
width?: number | string
|
|
594
|
+
height?: number | string
|
|
595
|
+
display?: "block" | "inline" | "none"
|
|
596
|
+
position?: "static" | "relative" | "absolute"
|
|
597
|
+
top?: number | string
|
|
598
|
+
right?: number | string
|
|
599
|
+
bottom?: number | string
|
|
600
|
+
left?: number | string
|
|
601
|
+
|
|
602
|
+
// Appearance
|
|
603
|
+
background_color?: string
|
|
604
|
+
border?: string
|
|
605
|
+
opacity?: number
|
|
606
|
+
|
|
607
|
+
// Advanced
|
|
608
|
+
overflow?: "visible" | "hidden" | "scroll" | "auto"
|
|
609
|
+
white_space?: "normal" | "nowrap" | "pre" | "pre-wrap" | "pre-line"
|
|
610
|
+
word_break?: "normal" | "break-all" | "keep-all"
|
|
611
|
+
text_overflow?: "clip" | "ellipsis"
|
|
612
|
+
vertical_align?: "baseline" | "top" | "middle" | "bottom" | string
|
|
613
|
+
}
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
---
|
|
617
|
+
|
|
618
|
+
### ShapeStyle
|
|
619
|
+
|
|
620
|
+
Styling for shapes.
|
|
621
|
+
|
|
622
|
+
```typescript
|
|
623
|
+
interface ShapeStyle {
|
|
624
|
+
fill_color?: string // Fill color (hex)
|
|
625
|
+
stroke_color?: string // Border color (hex)
|
|
626
|
+
stroke_width?: number // Border width
|
|
627
|
+
opacity?: number // Opacity 0-1
|
|
628
|
+
border_radius?: number // Corner radius
|
|
629
|
+
}
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
## Complete Example
|
|
633
|
+
|
|
634
|
+
```typescript
|
|
635
|
+
import { Document, create_theme, vector } from "@nemu-ai/pdf";
|
|
636
|
+
|
|
637
|
+
const pdf = new Document({ page_size: "A4", margin: 50 });
|
|
638
|
+
|
|
639
|
+
const theme = create_theme("doc", {
|
|
640
|
+
colors: {
|
|
641
|
+
primary: "#1a365d",
|
|
642
|
+
background: "#f8fafc",
|
|
643
|
+
border: "#e2e8f0"
|
|
644
|
+
}
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
pdf.set_theme(theme);
|
|
648
|
+
const page = pdf.create_page(theme);
|
|
649
|
+
|
|
650
|
+
// Header
|
|
651
|
+
page.header({
|
|
652
|
+
text: "Document Title",
|
|
653
|
+
position: vector(50, 50),
|
|
654
|
+
style: { font_size: 24, color: theme.get_color("primary") }
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
// Card with content
|
|
658
|
+
const card_pos = vector(50, 100);
|
|
659
|
+
const card_size = vector(400, 200);
|
|
660
|
+
|
|
661
|
+
page.rect(card_pos, card_size, {
|
|
662
|
+
fill_color: theme.get_color("background"),
|
|
663
|
+
stroke_color: theme.get_color("border"),
|
|
664
|
+
stroke_width: 1
|
|
665
|
+
});
|
|
666
|
+
|
|
667
|
+
page.text({
|
|
668
|
+
content: "Card content here",
|
|
669
|
+
position: card_pos.add(vector(20, 20)),
|
|
670
|
+
style: { font_size: 14 }
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
await pdf.build("output.pdf");
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
## License
|
|
677
|
+
|
|
678
|
+
MIT
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const PAGE_DIMENSIONS: Record<string, {
|
|
2
|
+
width: number;
|
|
3
|
+
height: number;
|
|
4
|
+
}>;
|
|
5
|
+
export declare const DEFAULT_MARGIN = 72;
|
|
6
|
+
export declare const DEFAULT_FONT_SIZE = 12;
|
|
7
|
+
export declare const DEFAULT_LINE_HEIGHT = 1.2;
|
|
8
|
+
export declare const DEFAULT_FONT_FAMILY = "Helvetica";
|
|
9
|
+
export declare const PDF_VERSION = "1.4";
|
|
10
|
+
export declare const PDF_CREATOR = "PDF Generator";
|
|
11
|
+
export declare const STANDARD_FONTS: string[];
|