podpdf 1.0.1 → 1.2.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/README.md +144 -33
- package/dist/browser.d.ts +93 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +3 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/plus.d.ts +84 -0
- package/dist/plus.d.ts.map +1 -0
- package/dist/plus.js +3 -0
- package/package.json +17 -4
package/README.md
CHANGED
|
@@ -1,49 +1,57 @@
|
|
|
1
1
|
# podpdf
|
|
2
2
|
|
|
3
|
-
**Ultra-fast, zero-dependency PDF generation for Node.js &
|
|
3
|
+
**Ultra-fast, zero-dependency PDF generation for Node.js, Bun & Browser**
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/podpdf)
|
|
6
6
|
[](https://bundlephobia.com/package/podpdf)
|
|
7
7
|
[](https://www.npmjs.com/package/podpdf)
|
|
8
|
+
[](https://buymeacoffee.com/herostack)
|
|
8
9
|
|
|
9
10
|
```
|
|
10
|
-
|
|
11
|
+
~9 KB minified • Zero dependencies • 5x faster than jsPDF • TypeScript native
|
|
11
12
|
```
|
|
12
13
|
|
|
13
14
|
## Why podpdf?
|
|
14
15
|
|
|
15
|
-
| Library | Size | Dependencies | Speed |
|
|
16
|
-
|
|
17
|
-
| **podpdf** |
|
|
18
|
-
|
|
|
19
|
-
|
|
|
16
|
+
| Library | Size | Dependencies | Speed | Environment |
|
|
17
|
+
|---------|------|--------------|-------|-------------|
|
|
18
|
+
| **podpdf** | **~9 KB** | **0** | **5.5x** | Node.js/Bun |
|
|
19
|
+
| **podpdf/plus** | **~13 KB** | **0** | **5x** | Node.js/Bun |
|
|
20
|
+
| **podpdf/browser** | **~9 KB** | **0** | **5.5x** | **Browser** ✨ |
|
|
21
|
+
| jsPDF | 290 KB | 2+ | 1x | Browser/Node |
|
|
22
|
+
| pdfkit | 1 MB | 10+ | 0.8x | Node.js only |
|
|
20
23
|
|
|
21
24
|
## Feature Comparison
|
|
22
25
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
|
26
|
-
|
|
27
|
-
|
|
|
28
|
-
|
|
|
29
|
-
|
|
|
30
|
-
|
|
|
31
|
-
|
|
|
32
|
-
|
|
|
33
|
-
|
|
|
34
|
-
|
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
|
42
|
-
|
|
43
|
-
|
|
|
44
|
-
|
|
|
45
|
-
|
|
46
|
-
|
|
26
|
+
### Core Features
|
|
27
|
+
|
|
28
|
+
| Feature | podpdf | podpdf/plus | podpdf/browser |
|
|
29
|
+
|---------|:------:|:-----------:|:--------------:|
|
|
30
|
+
| Text & Styling | ✅ | ✅ | ✅ |
|
|
31
|
+
| Text Wrap & Alignment | ✅ | ✅ | ✅ |
|
|
32
|
+
| Shapes (rect, circle, line) | ✅ | ✅ | ✅ |
|
|
33
|
+
| Tables | ✅ | ✅ | ✅ |
|
|
34
|
+
| Images (JPEG) | ✅ | ✅ | ✅ |
|
|
35
|
+
| Images (PNG) | ❌ | ✅ | ❌ |
|
|
36
|
+
| Links/URLs | ✅ | ✅ | ✅ |
|
|
37
|
+
| Multi-page | ✅ | ✅ | ✅ |
|
|
38
|
+
| Document Metadata | ✅ | ✅ | ✅ |
|
|
39
|
+
| Custom Fonts (TTF) | ❌ | ✅ | ❌ |
|
|
40
|
+
| TypeScript Native | ✅ | ✅ | ✅ |
|
|
41
|
+
|
|
42
|
+
### Environment Support
|
|
43
|
+
|
|
44
|
+
| Platform | podpdf | podpdf/plus | podpdf/browser |
|
|
45
|
+
|----------|:------:|:-----------:|:--------------:|
|
|
46
|
+
| Node.js / Bun | ✅ | ✅ | ❌ |
|
|
47
|
+
| Browser | Manual | Manual | ✅ Native |
|
|
48
|
+
| File System (.save) | ✅ | ✅ | ❌ |
|
|
49
|
+
| Browser Download (.download) | ❌ | ❌ | ✅ |
|
|
50
|
+
|
|
51
|
+
**Choose the right variant:**
|
|
52
|
+
- `podpdf` - Node.js/Bun for invoices, reports, tables
|
|
53
|
+
- `podpdf/plus` - Need PNG images or custom fonts
|
|
54
|
+
- `podpdf/browser` - Browser-native PDF generation
|
|
47
55
|
|
|
48
56
|
## Installation
|
|
49
57
|
|
|
@@ -57,8 +65,20 @@ pnpm add podpdf
|
|
|
57
65
|
bun add podpdf
|
|
58
66
|
```
|
|
59
67
|
|
|
68
|
+
## Package Variants
|
|
69
|
+
|
|
70
|
+
podpdf provides **3 specialized exports** for different use cases:
|
|
71
|
+
|
|
72
|
+
| Import | Use Case | Key Features |
|
|
73
|
+
|--------|----------|--------------|
|
|
74
|
+
| `podpdf` | Node.js/Bun | Core features, `.save()` to file |
|
|
75
|
+
| `podpdf/plus` | Node.js/Bun | PNG images + custom TTF fonts |
|
|
76
|
+
| `podpdf/browser` | Browser | Browser-native, `.download()` method |
|
|
77
|
+
|
|
60
78
|
## Quick Start
|
|
61
79
|
|
|
80
|
+
### Node.js / Bun
|
|
81
|
+
|
|
62
82
|
```typescript
|
|
63
83
|
import { pdf } from 'podpdf'
|
|
64
84
|
|
|
@@ -68,16 +88,48 @@ await pdf('A4')
|
|
|
68
88
|
.save('hello.pdf')
|
|
69
89
|
```
|
|
70
90
|
|
|
91
|
+
### Browser
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
import { pdf } from 'podpdf/browser'
|
|
95
|
+
|
|
96
|
+
pdf('A4')
|
|
97
|
+
.text('Hello Browser!', 50, 50, { size: 24, weight: 'bold' })
|
|
98
|
+
.rect(50, 80, 200, 100, { fill: '#3498db', radius: 10 })
|
|
99
|
+
.download('hello.pdf') // Triggers browser download
|
|
100
|
+
```
|
|
101
|
+
|
|
71
102
|
## Features
|
|
72
103
|
|
|
73
104
|
- **Text** - Multiple fonts, sizes, colors, alignment, text wrapping
|
|
74
105
|
- **Shapes** - Rectangle, rounded rectangle, circle, line (solid & dashed)
|
|
75
106
|
- **Tables** - Easy table creation with headers, styling, alignment
|
|
76
|
-
- **Images** - JPEG
|
|
107
|
+
- **Images** - JPEG support (PNG via podpdf/plus)
|
|
77
108
|
- **Links** - Clickable URLs with optional underline
|
|
78
109
|
- **Multi-page** - Multiple pages with different sizes
|
|
110
|
+
- **Metadata** - Document title, author, subject, keywords
|
|
79
111
|
- **Fluent API** - Chainable methods for clean code
|
|
80
112
|
|
|
113
|
+
### podpdf/plus (Extended)
|
|
114
|
+
|
|
115
|
+
For PNG images and custom fonts, use `podpdf/plus`:
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
import { pdfPlus } from 'podpdf/plus'
|
|
119
|
+
|
|
120
|
+
// Load custom font
|
|
121
|
+
const fontData = await Bun.file('custom-font.ttf').bytes()
|
|
122
|
+
|
|
123
|
+
// Load PNG image
|
|
124
|
+
const pngData = await Bun.file('logo.png').bytes()
|
|
125
|
+
|
|
126
|
+
await pdfPlus('A4')
|
|
127
|
+
.registerFont('custom', fontData)
|
|
128
|
+
.text('Custom Font Text', 50, 50, { font: 'custom' })
|
|
129
|
+
.imagePng(pngData, 50, 100, { width: 200 }) // async method
|
|
130
|
+
.save('output.pdf')
|
|
131
|
+
```
|
|
132
|
+
|
|
81
133
|
## API Reference
|
|
82
134
|
|
|
83
135
|
### Create Document
|
|
@@ -190,6 +242,24 @@ const imageData = await Bun.file('photo.jpg').bytes()
|
|
|
190
242
|
.page({ width: 500, height: 700 }) // Custom
|
|
191
243
|
```
|
|
192
244
|
|
|
245
|
+
### Metadata
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
.metadata({ title?, author?, subject?, keywords?, creator? })
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
```typescript
|
|
252
|
+
pdf('A4')
|
|
253
|
+
.metadata({
|
|
254
|
+
title: 'Invoice #123',
|
|
255
|
+
author: 'Company Name',
|
|
256
|
+
subject: 'Monthly Invoice',
|
|
257
|
+
keywords: 'invoice, billing'
|
|
258
|
+
})
|
|
259
|
+
.text('...', 50, 50)
|
|
260
|
+
.save('invoice.pdf')
|
|
261
|
+
```
|
|
262
|
+
|
|
193
263
|
### Output
|
|
194
264
|
|
|
195
265
|
```typescript
|
|
@@ -362,6 +432,7 @@ import type {
|
|
|
362
432
|
Align, // 'left' | 'center' | 'right'
|
|
363
433
|
Weight, // 'normal' | 'bold' | 'italic' | 'bolditalic'
|
|
364
434
|
Size, // { width, height }
|
|
435
|
+
PDFMetadata, // { title?, author?, subject?, keywords?, creator? }
|
|
365
436
|
TextOpts,
|
|
366
437
|
RectOpts,
|
|
367
438
|
LineOpts,
|
|
@@ -389,12 +460,52 @@ Tested with 1000 document generations:
|
|
|
389
460
|
|
|
390
461
|
## Browser Support
|
|
391
462
|
|
|
392
|
-
podpdf
|
|
463
|
+
### podpdf/browser (Recommended for Browser)
|
|
464
|
+
|
|
465
|
+
For browser environments, use the dedicated `podpdf/browser` module with built-in download support:
|
|
466
|
+
|
|
467
|
+
```typescript
|
|
468
|
+
import { pdf } from 'podpdf/browser'
|
|
469
|
+
|
|
470
|
+
// Create and download PDF directly in browser
|
|
471
|
+
pdf('A4')
|
|
472
|
+
.text('Hello from Browser!', 50, 50, { size: 24, weight: 'bold' })
|
|
473
|
+
.rect(50, 80, 200, 100, { fill: '#3498db', radius: 10 })
|
|
474
|
+
.download('document.pdf') // Triggers browser download
|
|
475
|
+
|
|
476
|
+
// Or get as Blob for custom handling
|
|
477
|
+
const blob = doc.toBlob()
|
|
478
|
+
|
|
479
|
+
// Or get data URL for iframe preview
|
|
480
|
+
const dataURL = doc.toDataURL()
|
|
481
|
+
const iframe = document.createElement('iframe')
|
|
482
|
+
iframe.src = dataURL
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
**Key differences in `podpdf/browser`:**
|
|
486
|
+
- ✅ No Node.js dependencies (fully browser-compatible)
|
|
487
|
+
- ✅ `download(filename)` - Directly triggers browser download
|
|
488
|
+
- ✅ `toBlob()` - Returns Blob object
|
|
489
|
+
- ✅ `toDataURL()` - Returns object URL for preview
|
|
490
|
+
- ❌ No `save()` method (use `download()` instead)
|
|
491
|
+
- ✅ Same API for text, shapes, tables, images, etc.
|
|
492
|
+
|
|
493
|
+
### Using Core podpdf in Browser
|
|
494
|
+
|
|
495
|
+
The main `podpdf` module can also work in browsers using the `build()` method:
|
|
393
496
|
|
|
394
497
|
```typescript
|
|
498
|
+
import { pdf } from 'podpdf'
|
|
499
|
+
|
|
395
500
|
const bytes = doc.build()
|
|
396
501
|
const blob = new Blob([bytes], { type: 'application/pdf' })
|
|
397
502
|
const url = URL.createObjectURL(blob)
|
|
503
|
+
|
|
504
|
+
// Trigger download
|
|
505
|
+
const a = document.createElement('a')
|
|
506
|
+
a.href = url
|
|
507
|
+
a.download = 'document.pdf'
|
|
508
|
+
a.click()
|
|
398
509
|
```
|
|
399
510
|
|
|
400
511
|
## License
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
export type Color = string | [number, number, number];
|
|
2
|
+
export type Align = 'left' | 'center' | 'right';
|
|
3
|
+
export type Weight = 'normal' | 'bold' | 'italic' | 'bolditalic';
|
|
4
|
+
export interface Size {
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
}
|
|
8
|
+
export interface TextOpts {
|
|
9
|
+
size?: number;
|
|
10
|
+
color?: Color;
|
|
11
|
+
align?: Align;
|
|
12
|
+
weight?: Weight;
|
|
13
|
+
maxWidth?: number;
|
|
14
|
+
font?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface RectOpts {
|
|
17
|
+
fill?: Color;
|
|
18
|
+
stroke?: Color;
|
|
19
|
+
lineWidth?: number;
|
|
20
|
+
radius?: number;
|
|
21
|
+
}
|
|
22
|
+
export interface LineOpts {
|
|
23
|
+
color?: Color;
|
|
24
|
+
width?: number;
|
|
25
|
+
dash?: number[];
|
|
26
|
+
}
|
|
27
|
+
export interface CircleOpts {
|
|
28
|
+
fill?: Color;
|
|
29
|
+
stroke?: Color;
|
|
30
|
+
lineWidth?: number;
|
|
31
|
+
}
|
|
32
|
+
export interface ImageOpts {
|
|
33
|
+
width?: number;
|
|
34
|
+
height?: number;
|
|
35
|
+
}
|
|
36
|
+
export interface LinkOpts {
|
|
37
|
+
underline?: boolean;
|
|
38
|
+
color?: Color;
|
|
39
|
+
}
|
|
40
|
+
export interface TableCol {
|
|
41
|
+
header: string;
|
|
42
|
+
width?: number;
|
|
43
|
+
align?: Align;
|
|
44
|
+
}
|
|
45
|
+
export interface TableOpts {
|
|
46
|
+
columns: TableCol[];
|
|
47
|
+
headerBg?: Color;
|
|
48
|
+
headerColor?: Color;
|
|
49
|
+
borderColor?: Color;
|
|
50
|
+
fontSize?: number;
|
|
51
|
+
padding?: number;
|
|
52
|
+
}
|
|
53
|
+
export interface PDFMetadata {
|
|
54
|
+
title?: string;
|
|
55
|
+
author?: string;
|
|
56
|
+
subject?: string;
|
|
57
|
+
keywords?: string;
|
|
58
|
+
creator?: string;
|
|
59
|
+
}
|
|
60
|
+
export declare const SIZES: Record<string, Size>;
|
|
61
|
+
export declare class PDF {
|
|
62
|
+
private pages;
|
|
63
|
+
private cur;
|
|
64
|
+
private sz;
|
|
65
|
+
private meta?;
|
|
66
|
+
constructor(s?: Size | keyof typeof SIZES);
|
|
67
|
+
metadata(m: PDFMetadata): this;
|
|
68
|
+
page(s?: Size | keyof typeof SIZES): this;
|
|
69
|
+
text(t: string, x: number, y: number, o?: TextOpts): this;
|
|
70
|
+
rect(x: number, y: number, w: number, h: number, o?: RectOpts): this;
|
|
71
|
+
line(x1: number, y1: number, x2: number, y2: number, o?: LineOpts): this;
|
|
72
|
+
circle(cx: number, cy: number, r: number, o?: CircleOpts): this;
|
|
73
|
+
image(d: Uint8Array, x: number, y: number, o?: ImageOpts): this;
|
|
74
|
+
link(t: string, url: string, x: number, y: number, o?: LinkOpts): this;
|
|
75
|
+
table(data: string[][], x: number, y: number, o: TableOpts): this;
|
|
76
|
+
private ensure;
|
|
77
|
+
build(): Uint8Array;
|
|
78
|
+
/**
|
|
79
|
+
* Download PDF in browser using Blob and URL APIs
|
|
80
|
+
* @param filename - The filename for the downloaded PDF (default: 'document.pdf')
|
|
81
|
+
*/
|
|
82
|
+
download(filename?: string): void;
|
|
83
|
+
/**
|
|
84
|
+
* Get PDF as Blob object (useful for preview or custom handling)
|
|
85
|
+
*/
|
|
86
|
+
toBlob(): Blob;
|
|
87
|
+
/**
|
|
88
|
+
* Get PDF as data URL (useful for iframe preview)
|
|
89
|
+
*/
|
|
90
|
+
toDataURL(): string;
|
|
91
|
+
}
|
|
92
|
+
export declare const pdf: (s?: Size | keyof typeof SIZES) => PDF;
|
|
93
|
+
//# sourceMappingURL=browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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"}
|
package/dist/browser.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
var P={A4:{width:595,height:842},A3:{width:842,height:1191},A5:{width:420,height:595},LETTER:{width:612,height:792}},g={normal:"Helvetica",bold:"Helvetica-Bold",italic:"Helvetica-Oblique",bolditalic:"Helvetica-BoldOblique"},F=(q)=>{if(Array.isArray(q))return q;let B=q.replace("#","");if(B.length===3)return[parseInt(B[0]+B[0],16)/255,parseInt(B[1]+B[1],16)/255,parseInt(B[2]+B[2],16)/255];return[parseInt(B.slice(0,2),16)/255,parseInt(B.slice(2,4),16)/255,parseInt(B.slice(4,6),16)/255]},A=(q)=>{let[B,z,H]=F(q);return`${B.toFixed(3)} ${z.toFixed(3)} ${H.toFixed(3)} rg`},D=(q)=>{let[B,z,H]=F(q);return`${B.toFixed(3)} ${z.toFixed(3)} ${H.toFixed(3)} RG`},E=(q)=>q.replace(/\\/g,"\\\\").replace(/\(/g,"\\(").replace(/\)/g,"\\)"),J=(q)=>Number.isInteger(q)?q.toString():q.toFixed(2),j=(q,B)=>q.length*B*0.52;class R{c=[];s=0;e=new TextEncoder;w(q){let B=typeof q==="string"?this.e.encode(q):q;return this.c.push(B),this.s+=B.length,this}l(q){return this.w(q+`
|
|
2
|
+
`)}size(){return this.s}out(){let q=new Uint8Array(this.s),B=0;for(let z of this.c)q.set(z,B),B+=z.length;return q}}class v{w;h;c=[];f=new Set;imgs=[];links=[];ic=0;constructor(q){this.w=q.width,this.h=q.height}text(q,B,z,H={}){let C=H.size??12,K=H.weight??"normal",Q=H.color??"#000",W=H.align??"left",N=g[K];this.f.add(N);let G=this.h-z,L=B,X=H.maxWidth?this.wrap(q,H.maxWidth,C):[q];for(let V of X)L=W==="center"?B-j(V,C)/2:W==="right"?B-j(V,C):B,this.c.push("q","BT",A(Q),`/${N.replace("-","")} ${C} Tf`,`${J(L)} ${J(G)} Td`,`(${E(V)}) Tj`,"ET","Q"),G-=C*1.2;return this}rect(q,B,z,H,C={}){let K=this.h-B-H;if(this.c.push("q"),C.radius&&C.radius>0){let Q=Math.min(C.radius,z/2,H/2);this.c.push(`${J(q+Q)} ${J(K)} m`,`${J(q+z-Q)} ${J(K)} l`,`${J(q+z)} ${J(K)} ${J(q+z)} ${J(K+Q)} y`,`${J(q+z)} ${J(K+H-Q)} l`,`${J(q+z)} ${J(K+H)} ${J(q+z-Q)} ${J(K+H)} y`,`${J(q+Q)} ${J(K+H)} l`,`${J(q)} ${J(K+H)} ${J(q)} ${J(K+H-Q)} y`,`${J(q)} ${J(K+Q)} l`,`${J(q)} ${J(K)} ${J(q+Q)} ${J(K)} y`,"h")}else this.c.push(`${J(q)} ${J(K)} ${J(z)} ${J(H)} re`);if(C.fill)this.c.push(A(C.fill)),this.c.push(C.stroke?"B":"f");if(C.stroke){if(this.c.push(D(C.stroke)),C.lineWidth)this.c.push(`${C.lineWidth} w`);if(!C.fill)this.c.push("S")}return this.c.push("Q"),this}line(q,B,z,H,C={}){if(this.c.push("q"),C.color)this.c.push(D(C.color));if(C.width)this.c.push(`${C.width} w`);if(C.dash)this.c.push(`[${C.dash.join(" ")}] 0 d`);return this.c.push(`${J(q)} ${J(this.h-B)} m`,`${J(z)} ${J(this.h-H)} l`,"S","Q"),this}circle(q,B,z,H={}){let C=this.h-B;if(this.c.push("q"),this.c.push(`${J(q+z)} ${J(C)} m`,`${J(q+z)} ${J(C+z*0.5523)} ${J(q+z*0.5523)} ${J(C+z)} ${J(q)} ${J(C+z)} c`,`${J(q-z*0.5523)} ${J(C+z)} ${J(q-z)} ${J(C+z*0.5523)} ${J(q-z)} ${J(C)} c`,`${J(q-z*0.5523)} ${J(C-z)} ${J(q-z)} ${J(C-z*0.5523)} ${J(q)} ${J(C-z)} c`,`${J(q+z*0.5523)} ${J(C-z)} ${J(q+z)} ${J(C-z*0.5523)} ${J(q+z)} ${J(C)} c`),H.fill)this.c.push(A(H.fill)),this.c.push(H.stroke?"B":"f");if(H.stroke){if(this.c.push(D(H.stroke)),H.lineWidth)this.c.push(`${H.lineWidth} w`);if(!H.fill)this.c.push("S")}return this.c.push("Q"),this}image(q,B,z,H={}){let C=this.imgInfo(q);if(!C)return this;let K=H.width??C.w,Q=H.height??C.h,W=`I${++this.ic}`;return this.imgs.push({d:q,w:C.w,h:C.h,x:B,y:this.h-z-Q,id:W}),this.c.push("q",`${J(K)} 0 0 ${J(Q)} ${J(B)} ${J(this.h-z-Q)} cm`,`/${W} Do`,"Q"),this}link(q,B,z,H,C={}){let K=C.color??"#00E";this.text(q,z,H,{color:K,size:12});let W=j(q,12);if(C.underline!==!1)this.line(z,H+2,z+W,H+2,{color:K,width:0.5});return this.links.push({x:z,y:this.h-H-12,w:W,h:12,url:B}),this}table(q,B,z,H){let C=H.padding??8,K=H.fontSize??10,Q=K+C*2,W=H.columns.map((X,V)=>X.width??Math.max(j(X.header,K),...q.map((O)=>j(O[V]??"",K)))+C*2),N=W.reduce((X,V)=>X+V,0),G=z;this.rect(B,G,N,Q,{fill:H.headerBg??"#F0F0F0"});let L=B;for(let X=0;X<H.columns.length;X++){let V=H.columns[X];this.text(V.header,L+(V.align==="center"?W[X]/2:V.align==="right"?W[X]-C:C),G+C+K*0.8,{size:K,weight:"bold",color:H.headerColor??"#000",align:V.align}),L+=W[X]}G+=Q;for(let X=0;X<q.length;X++){this.rect(B,G,N,Q,{fill:X%2?"#F9F9F9":"#FFF"}),L=B;for(let V=0;V<H.columns.length;V++){let O=H.columns[V];this.text(q[X][V]??"",L+(O.align==="center"?W[V]/2:O.align==="right"?W[V]-C:C),G+C+K*0.8,{size:K,align:O.align}),L+=W[V]}G+=Q}return this.rect(B,z,N,Q*(q.length+1),{stroke:H.borderColor??"#CCC"}),this}wrap(q,B,z){let H=q.split(" "),C=[],K="";for(let Q of H){let W=K?`${K} ${Q}`:Q;if(j(W,z)<=B)K=W;else{if(K)C.push(K);K=Q}}if(K)C.push(K);return C}imgInfo(q){if(q[0]===255&&q[1]===216){let B=2;while(B<q.length){if(q[B]!==255)break;let z=q[B+1];if(z>=192&&z<=207&&z!==196&&z!==200&&z!==204)return{h:q[B+5]<<8|q[B+6],w:q[B+7]<<8|q[B+8]};B+=2+(q[B+2]<<8|q[B+3])}}if(q[0]===137&&q[1]===80)return{w:q[16]<<24|q[17]<<16|q[18]<<8|q[19],h:q[20]<<24|q[21]<<16|q[22]<<8|q[23]};return null}}class S{pages=[];cur=null;sz;meta;constructor(q="A4"){this.sz=typeof q==="string"?P[q]:q}metadata(q){return this.meta=q,this}page(q){return this.cur=new v(q?typeof q==="string"?P[q]:q:this.sz),this.pages.push(this.cur),this}text(q,B,z,H){return this.ensure().text(q,B,z,H),this}rect(q,B,z,H,C){return this.ensure().rect(q,B,z,H,C),this}line(q,B,z,H,C){return this.ensure().line(q,B,z,H,C),this}circle(q,B,z,H){return this.ensure().circle(q,B,z,H),this}image(q,B,z,H){return this.ensure().image(q,B,z,H),this}link(q,B,z,H,C){return this.ensure().link(q,B,z,H,C),this}table(q,B,z,H){return this.ensure().table(q,B,z,H),this}ensure(){if(!this.cur)this.page();return this.cur}build(){let q=new R,B=[0],z=0;q.l("%PDF-1.4").l("%µµµµ");let H=new Set;this.pages.forEach((M)=>M.f.forEach((_)=>H.add(_)));let C=Array.from(H),K={};for(let M of C){let _=++z;K[M]=_,B[_]=q.size(),q.l(`${_} 0 obj`).l(`<</Type/Font/Subtype/Type1/BaseFont/${M}>>`).l("endobj")}let Q=[],W=[],N=[];for(let M of this.pages){let _=[];for(let Y of M.imgs){let T=++z;_.push(T),B[T]=q.size();let u=String.fromCharCode(...Y.d);q.l(`${T} 0 obj`).l(`<</Type/XObject/Subtype/Image/Width ${Y.w}/Height ${Y.h}/ColorSpace/DeviceRGB/BitsPerComponent 8/Filter/DCTDecode/Length ${Y.d.length}>>`).l("stream").w(u).l("").l("endstream").l("endobj")}N.push(_);let $=M.c.join(`
|
|
3
|
+
`),Z=new TextEncoder().encode($).length,U=++z;Q.push(U),B[U]=q.size(),q.l(`${U} 0 obj`).l(`<</Length ${Z}>>`).l("stream").w($).l("").l("endstream").l("endobj");let k=[];for(let Y of M.links){let T=++z;k.push(T),B[T]=q.size(),q.l(`${T} 0 obj`).l(`<</Type/Annot/Subtype/Link/Rect[${Y.x} ${Y.y} ${Y.x+Y.w} ${Y.y+Y.h}]/Border[0 0 0]/A<</Type/Action/S/URI/URI(${Y.url})>>>>`).l("endobj")}W.push(k)}let G=++z,L=z+1,X=this.pages.map((M,_)=>L+_);B[G]=q.size(),q.l(`${G} 0 obj`).l(`<</Type/Pages/Kids[${X.map((M)=>`${M} 0 R`).join(" ")}]/Count ${X.length}>>`).l("endobj");for(let M=0;M<this.pages.length;M++){let _=this.pages[M],$=++z,Z=Array.from(_.f).map((Y)=>`/${Y.replace("-","")} ${K[Y]} 0 R`).join(""),U=_.imgs.map((Y,T)=>`/${Y.id} ${N[M][T]} 0 R`).join(""),k=W[M].length?`/Annots[${W[M].map((Y)=>`${Y} 0 R`).join(" ")}]`:"";B[$]=q.size(),q.l(`${$} 0 obj`).l(`<</Type/Page/Parent ${G} 0 R/MediaBox[0 0 ${_.w} ${_.h}]/Contents ${Q[M]} 0 R/Resources<<${Z?`/Font<<${Z}>>`:""}${U?`/XObject<<${U}>>`:""}>>${k}>>`).l("endobj")}let V=0;if(this.meta){V=++z,B[V]=q.size();let M=new Date,_=`D:${M.getFullYear()}${String(M.getMonth()+1).padStart(2,"0")}${String(M.getDate()).padStart(2,"0")}${String(M.getHours()).padStart(2,"0")}${String(M.getMinutes()).padStart(2,"0")}${String(M.getSeconds()).padStart(2,"0")}`,$=this.meta;q.l(`${V} 0 obj`).l(`<<${$.title?`/Title(${E($.title)})`:""}${$.author?`/Author(${E($.author)})`:""}${$.subject?`/Subject(${E($.subject)})`:""}${$.keywords?`/Keywords(${E($.keywords)})`:""}${$.creator?`/Creator(${E($.creator)})`:""}/Producer(podpdf-browser)/CreationDate(${_})>>`).l("endobj")}let O=++z;B[O]=q.size(),q.l(`${O} 0 obj`).l(`<</Type/Catalog/Pages ${G} 0 R>>`).l("endobj");let b=q.size();q.l("xref").l(`0 ${z+1}`).l("0000000000 65535 f ");for(let M=1;M<=z;M++)q.l(`${B[M].toString().padStart(10,"0")} 00000 n `);return q.l("trailer").l(`<</Size ${z+1}/Root ${O} 0 R${V?`/Info ${V} 0 R`:""}>>`).l("startxref").l(b.toString()).l("%%EOF"),q.out()}download(q="document.pdf"){if(typeof window>"u")throw Error("download() method is only available in browser environment. Use build() to get Uint8Array instead.");let B=this.build(),z=new Blob([B],{type:"application/pdf"}),H=URL.createObjectURL(z),C=document.createElement("a");C.href=H,C.download=q,C.style.display="none",document.body.appendChild(C),C.click(),document.body.removeChild(C),URL.revokeObjectURL(H)}toBlob(){let q=this.build();return new Blob([q],{type:"application/pdf"})}toDataURL(){let q=this.build(),B=new Blob([q],{type:"application/pdf"});return URL.createObjectURL(B)}}var I=(q)=>new S(q);export{I as pdf,P as SIZES,S as PDF};
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export interface TextOpts {
|
|
|
11
11
|
align?: Align;
|
|
12
12
|
weight?: Weight;
|
|
13
13
|
maxWidth?: number;
|
|
14
|
+
font?: string;
|
|
14
15
|
}
|
|
15
16
|
export interface RectOpts {
|
|
16
17
|
fill?: Color;
|
|
@@ -49,12 +50,21 @@ export interface TableOpts {
|
|
|
49
50
|
fontSize?: number;
|
|
50
51
|
padding?: number;
|
|
51
52
|
}
|
|
53
|
+
export interface PDFMetadata {
|
|
54
|
+
title?: string;
|
|
55
|
+
author?: string;
|
|
56
|
+
subject?: string;
|
|
57
|
+
keywords?: string;
|
|
58
|
+
creator?: string;
|
|
59
|
+
}
|
|
52
60
|
export declare const SIZES: Record<string, Size>;
|
|
53
61
|
export declare class PDF {
|
|
54
62
|
private pages;
|
|
55
63
|
private cur;
|
|
56
64
|
private sz;
|
|
65
|
+
private meta?;
|
|
57
66
|
constructor(s?: Size | keyof typeof SIZES);
|
|
67
|
+
metadata(m: PDFMetadata): this;
|
|
58
68
|
page(s?: Size | keyof typeof SIZES): this;
|
|
59
69
|
text(t: string, x: number, y: number, o?: TextOpts): this;
|
|
60
70
|
rect(x: number, y: number, w: number, h: number, o?: RectOpts): this;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AACrD,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAA;AAC/C,MAAM,MAAM,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,YAAY,CAAA;AAChE,MAAM,WAAW,IAAI;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AACvD,MAAM,WAAW,QAAQ;IAAG,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{createRequire as U}from"node:module";var
|
|
2
|
-
`)}size(){return this.s}out(){let
|
|
3
|
-
`),
|
|
1
|
+
import{createRequire as U}from"node:module";var D=Object.create;var{getPrototypeOf:E,defineProperty:z,getOwnPropertyNames:W}=Object;var P=Object.prototype.hasOwnProperty;var L=(t,r,e)=>{e=t!=null?D(E(t)):{};let n=r||!t||!t.__esModule?z(e,"default",{value:t,enumerable:!0}):e;for(let i of W(t))if(!P.call(n,i))z(n,i,{get:()=>t[i],enumerable:!0});return n};var M=U(import.meta.url);var T={A4:{width:595,height:842},A3:{width:842,height:1191},A5:{width:420,height:595},LETTER:{width:612,height:792}},q={normal:"Helvetica",bold:"Helvetica-Bold",italic:"Helvetica-Oblique",bolditalic:"Helvetica-BoldOblique"},O=(t)=>{if(Array.isArray(t))return t;let r=t.replace("#","");if(r.length===3)return[parseInt(r[0]+r[0],16)/255,parseInt(r[1]+r[1],16)/255,parseInt(r[2]+r[2],16)/255];return[parseInt(r.slice(0,2),16)/255,parseInt(r.slice(2,4),16)/255,parseInt(r.slice(4,6),16)/255]},I=(t)=>{let[r,e,n]=O(t);return`${r.toFixed(3)} ${e.toFixed(3)} ${n.toFixed(3)} rg`},j=(t)=>{let[r,e,n]=O(t);return`${r.toFixed(3)} ${e.toFixed(3)} ${n.toFixed(3)} RG`},C=(t)=>t.replace(/\\/g,"\\\\").replace(/\(/g,"\\(").replace(/\)/g,"\\)"),s=(t)=>Number.isInteger(t)?t.toString():t.toFixed(2),S=(t,r)=>t.length*r*0.52;class x{c=[];s=0;e=new TextEncoder;w(t){let r=typeof t==="string"?this.e.encode(t):t;return this.c.push(r),this.s+=r.length,this}l(t){return this.w(t+`
|
|
2
|
+
`)}size(){return this.s}out(){let t=new Uint8Array(this.s),r=0;for(let e of this.c)t.set(e,r),r+=e.length;return t}}class A{w;h;c=[];f=new Set;imgs=[];links=[];ic=0;constructor(t){this.w=t.width,this.h=t.height}text(t,r,e,n={}){let i=n.size??12,o=n.weight??"normal",h=n.color??"#000",c=n.align??"left",f=q[o];this.f.add(f);let m=this.h-e,b=r,a=n.maxWidth?this.wrap(t,n.maxWidth,i):[t];for(let u of a)b=c==="center"?r-S(u,i)/2:c==="right"?r-S(u,i):r,this.c.push("q","BT",I(h),`/${f.replace("-","")} ${i} Tf`,`${s(b)} ${s(m)} Td`,`(${C(u)}) Tj`,"ET","Q"),m-=i*1.2;return this}rect(t,r,e,n,i={}){let o=this.h-r-n;if(this.c.push("q"),i.radius&&i.radius>0){let h=Math.min(i.radius,e/2,n/2);this.c.push(`${s(t+h)} ${s(o)} m`,`${s(t+e-h)} ${s(o)} l`,`${s(t+e)} ${s(o)} ${s(t+e)} ${s(o+h)} y`,`${s(t+e)} ${s(o+n-h)} l`,`${s(t+e)} ${s(o+n)} ${s(t+e-h)} ${s(o+n)} y`,`${s(t+h)} ${s(o+n)} l`,`${s(t)} ${s(o+n)} ${s(t)} ${s(o+n-h)} y`,`${s(t)} ${s(o+h)} l`,`${s(t)} ${s(o)} ${s(t+h)} ${s(o)} y`,"h")}else this.c.push(`${s(t)} ${s(o)} ${s(e)} ${s(n)} re`);if(i.fill)this.c.push(I(i.fill)),this.c.push(i.stroke?"B":"f");if(i.stroke){if(this.c.push(j(i.stroke)),i.lineWidth)this.c.push(`${i.lineWidth} w`);if(!i.fill)this.c.push("S")}return this.c.push("Q"),this}line(t,r,e,n,i={}){if(this.c.push("q"),i.color)this.c.push(j(i.color));if(i.width)this.c.push(`${i.width} w`);if(i.dash)this.c.push(`[${i.dash.join(" ")}] 0 d`);return this.c.push(`${s(t)} ${s(this.h-r)} m`,`${s(e)} ${s(this.h-n)} l`,"S","Q"),this}circle(t,r,e,n={}){let i=this.h-r;if(this.c.push("q"),this.c.push(`${s(t+e)} ${s(i)} m`,`${s(t+e)} ${s(i+e*0.5523)} ${s(t+e*0.5523)} ${s(i+e)} ${s(t)} ${s(i+e)} c`,`${s(t-e*0.5523)} ${s(i+e)} ${s(t-e)} ${s(i+e*0.5523)} ${s(t-e)} ${s(i)} c`,`${s(t-e*0.5523)} ${s(i-e)} ${s(t-e)} ${s(i-e*0.5523)} ${s(t)} ${s(i-e)} c`,`${s(t+e*0.5523)} ${s(i-e)} ${s(t+e)} ${s(i-e*0.5523)} ${s(t+e)} ${s(i)} c`),n.fill)this.c.push(I(n.fill)),this.c.push(n.stroke?"B":"f");if(n.stroke){if(this.c.push(j(n.stroke)),n.lineWidth)this.c.push(`${n.lineWidth} w`);if(!n.fill)this.c.push("S")}return this.c.push("Q"),this}image(t,r,e,n={}){let i=this.imgInfo(t);if(!i)return this;let o=n.width??i.w,h=n.height??i.h,c=`I${++this.ic}`;return this.imgs.push({d:t,w:i.w,h:i.h,x:r,y:this.h-e-h,id:c}),this.c.push("q",`${s(o)} 0 0 ${s(h)} ${s(r)} ${s(this.h-e-h)} cm`,`/${c} Do`,"Q"),this}link(t,r,e,n,i={}){let o=i.color??"#00E";this.text(t,e,n,{color:o,size:12});let c=S(t,12);if(i.underline!==!1)this.line(e,n+2,e+c,n+2,{color:o,width:0.5});return this.links.push({x:e,y:this.h-n-12,w:c,h:12,url:r}),this}table(t,r,e,n){let i=n.padding??8,o=n.fontSize??10,h=o+i*2,c=n.columns.map((a,u)=>a.width??Math.max(S(a.header,o),...t.map((d)=>S(d[u]??"",o)))+i*2),f=c.reduce((a,u)=>a+u,0),m=e;this.rect(r,m,f,h,{fill:n.headerBg??"#F0F0F0"});let b=r;for(let a=0;a<n.columns.length;a++){let u=n.columns[a];this.text(u.header,b+(u.align==="center"?c[a]/2:u.align==="right"?c[a]-i:i),m+i+o*0.8,{size:o,weight:"bold",color:n.headerColor??"#000",align:u.align}),b+=c[a]}m+=h;for(let a=0;a<t.length;a++){this.rect(r,m,f,h,{fill:a%2?"#F9F9F9":"#FFF"}),b=r;for(let u=0;u<n.columns.length;u++){let d=n.columns[u];this.text(t[a][u]??"",b+(d.align==="center"?c[u]/2:d.align==="right"?c[u]-i:i),m+i+o*0.8,{size:o,align:d.align}),b+=c[u]}m+=h}return this.rect(r,e,f,h*(t.length+1),{stroke:n.borderColor??"#CCC"}),this}wrap(t,r,e){let n=t.split(" "),i=[],o="";for(let h of n){let c=o?`${o} ${h}`:h;if(S(c,e)<=r)o=c;else{if(o)i.push(o);o=h}}if(o)i.push(o);return i}imgInfo(t){if(t[0]===255&&t[1]===216){let r=2;while(r<t.length){if(t[r]!==255)break;let e=t[r+1];if(e>=192&&e<=207&&e!==196&&e!==200&&e!==204)return{h:t[r+5]<<8|t[r+6],w:t[r+7]<<8|t[r+8]};r+=2+(t[r+2]<<8|t[r+3])}}if(t[0]===137&&t[1]===80)return{w:t[16]<<24|t[17]<<16|t[18]<<8|t[19],h:t[20]<<24|t[21]<<16|t[22]<<8|t[23]};return null}}class R{pages=[];cur=null;sz;meta;constructor(t="A4"){this.sz=typeof t==="string"?T[t]:t}metadata(t){return this.meta=t,this}page(t){return this.cur=new A(t?typeof t==="string"?T[t]:t:this.sz),this.pages.push(this.cur),this}text(t,r,e,n){return this.ensure().text(t,r,e,n),this}rect(t,r,e,n,i){return this.ensure().rect(t,r,e,n,i),this}line(t,r,e,n,i){return this.ensure().line(t,r,e,n,i),this}circle(t,r,e,n){return this.ensure().circle(t,r,e,n),this}image(t,r,e,n){return this.ensure().image(t,r,e,n),this}link(t,r,e,n,i){return this.ensure().link(t,r,e,n,i),this}table(t,r,e,n){return this.ensure().table(t,r,e,n),this}ensure(){if(!this.cur)this.page();return this.cur}build(){let t=new x,r=[0],e=0;t.l("%PDF-1.4").l("%µµµµ");let n=new Set;this.pages.forEach((l)=>l.f.forEach((g)=>n.add(g)));let i=Array.from(n),o={};for(let l of i){let g=++e;o[l]=g,r[g]=t.size(),t.l(`${g} 0 obj`).l(`<</Type/Font/Subtype/Type1/BaseFont/${l}>>`).l("endobj")}let h=[],c=[],f=[];for(let l of this.pages){let g=[];for(let p of l.imgs){let w=++e;g.push(w),r[w]=t.size();let v=String.fromCharCode(...p.d);t.l(`${w} 0 obj`).l(`<</Type/XObject/Subtype/Image/Width ${p.w}/Height ${p.h}/ColorSpace/DeviceRGB/BitsPerComponent 8/Filter/DCTDecode/Length ${p.d.length}>>`).l("stream").w(v).l("").l("endstream").l("endobj")}f.push(g);let $=l.c.join(`
|
|
3
|
+
`),k=new TextEncoder().encode($).length,y=++e;h.push(y),r[y]=t.size(),t.l(`${y} 0 obj`).l(`<</Length ${k}>>`).l("stream").w($).l("").l("endstream").l("endobj");let F=[];for(let p of l.links){let w=++e;F.push(w),r[w]=t.size(),t.l(`${w} 0 obj`).l(`<</Type/Annot/Subtype/Link/Rect[${p.x} ${p.y} ${p.x+p.w} ${p.y+p.h}]/Border[0 0 0]/A<</Type/Action/S/URI/URI(${p.url})>>>>`).l("endobj")}c.push(F)}let m=++e,b=e+1,a=this.pages.map((l,g)=>b+g);r[m]=t.size(),t.l(`${m} 0 obj`).l(`<</Type/Pages/Kids[${a.map((l)=>`${l} 0 R`).join(" ")}]/Count ${a.length}>>`).l("endobj");for(let l=0;l<this.pages.length;l++){let g=this.pages[l],$=++e,k=Array.from(g.f).map((p)=>`/${p.replace("-","")} ${o[p]} 0 R`).join(""),y=g.imgs.map((p,w)=>`/${p.id} ${f[l][w]} 0 R`).join(""),F=c[l].length?`/Annots[${c[l].map((p)=>`${p} 0 R`).join(" ")}]`:"";r[$]=t.size(),t.l(`${$} 0 obj`).l(`<</Type/Page/Parent ${m} 0 R/MediaBox[0 0 ${g.w} ${g.h}]/Contents ${h[l]} 0 R/Resources<<${k?`/Font<<${k}>>`:""}${y?`/XObject<<${y}>>`:""}>>${F}>>`).l("endobj")}let u=0;if(this.meta){u=++e,r[u]=t.size();let l=new Date,g=`D:${l.getFullYear()}${String(l.getMonth()+1).padStart(2,"0")}${String(l.getDate()).padStart(2,"0")}${String(l.getHours()).padStart(2,"0")}${String(l.getMinutes()).padStart(2,"0")}${String(l.getSeconds()).padStart(2,"0")}`,$=this.meta;t.l(`${u} 0 obj`).l(`<<${$.title?`/Title(${C($.title)})`:""}${$.author?`/Author(${C($.author)})`:""}${$.subject?`/Subject(${C($.subject)})`:""}${$.keywords?`/Keywords(${C($.keywords)})`:""}${$.creator?`/Creator(${C($.creator)})`:""}/Producer(podpdf)/CreationDate(${g})>>`).l("endobj")}let d=++e;r[d]=t.size(),t.l(`${d} 0 obj`).l(`<</Type/Catalog/Pages ${m} 0 R>>`).l("endobj");let B=t.size();t.l("xref").l(`0 ${e+1}`).l("0000000000 65535 f ");for(let l=1;l<=e;l++)t.l(`${r[l].toString().padStart(10,"0")} 00000 n `);return t.l("trailer").l(`<</Size ${e+1}/Root ${d} 0 R${u?`/Info ${u} 0 R`:""}>>`).l("startxref").l(B.toString()).l("%%EOF"),t.out()}async save(t){let r=this.build();if(typeof Bun<"u")await Bun.write(t,r);else{let{writeFile:e}=await import("fs/promises");await e(t,r)}}}var Z=(t)=>new R(t);export{Z as pdf,T as SIZES,R as PDF};
|
package/dist/plus.d.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export type Color = string | [number, number, number];
|
|
2
|
+
export type Align = 'left' | 'center' | 'right';
|
|
3
|
+
export type Weight = 'normal' | 'bold' | 'italic' | 'bolditalic';
|
|
4
|
+
export interface Size {
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
}
|
|
8
|
+
export interface TextOpts {
|
|
9
|
+
size?: number;
|
|
10
|
+
color?: Color;
|
|
11
|
+
align?: Align;
|
|
12
|
+
weight?: Weight;
|
|
13
|
+
maxWidth?: number;
|
|
14
|
+
font?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface RectOpts {
|
|
17
|
+
fill?: Color;
|
|
18
|
+
stroke?: Color;
|
|
19
|
+
lineWidth?: number;
|
|
20
|
+
radius?: number;
|
|
21
|
+
}
|
|
22
|
+
export interface LineOpts {
|
|
23
|
+
color?: Color;
|
|
24
|
+
width?: number;
|
|
25
|
+
dash?: number[];
|
|
26
|
+
}
|
|
27
|
+
export interface CircleOpts {
|
|
28
|
+
fill?: Color;
|
|
29
|
+
stroke?: Color;
|
|
30
|
+
lineWidth?: number;
|
|
31
|
+
}
|
|
32
|
+
export interface ImageOpts {
|
|
33
|
+
width?: number;
|
|
34
|
+
height?: number;
|
|
35
|
+
}
|
|
36
|
+
export interface LinkOpts {
|
|
37
|
+
underline?: boolean;
|
|
38
|
+
color?: Color;
|
|
39
|
+
}
|
|
40
|
+
export interface TableCol {
|
|
41
|
+
header: string;
|
|
42
|
+
width?: number;
|
|
43
|
+
align?: Align;
|
|
44
|
+
}
|
|
45
|
+
export interface TableOpts {
|
|
46
|
+
columns: TableCol[];
|
|
47
|
+
headerBg?: Color;
|
|
48
|
+
headerColor?: Color;
|
|
49
|
+
borderColor?: Color;
|
|
50
|
+
fontSize?: number;
|
|
51
|
+
padding?: number;
|
|
52
|
+
}
|
|
53
|
+
export interface PDFMetadata {
|
|
54
|
+
title?: string;
|
|
55
|
+
author?: string;
|
|
56
|
+
subject?: string;
|
|
57
|
+
keywords?: string;
|
|
58
|
+
creator?: string;
|
|
59
|
+
}
|
|
60
|
+
export declare const SIZES: Record<string, Size>;
|
|
61
|
+
export declare class PDFPlus {
|
|
62
|
+
private pages;
|
|
63
|
+
private cur;
|
|
64
|
+
private sz;
|
|
65
|
+
private meta?;
|
|
66
|
+
private customFonts;
|
|
67
|
+
constructor(s?: Size | keyof typeof SIZES);
|
|
68
|
+
metadata(m: PDFMetadata): this;
|
|
69
|
+
registerFont(name: string, data: Uint8Array): this;
|
|
70
|
+
page(s?: Size | keyof typeof SIZES): this;
|
|
71
|
+
text(t: string, x: number, y: number, o?: TextOpts): this;
|
|
72
|
+
rect(x: number, y: number, w: number, h: number, o?: RectOpts): this;
|
|
73
|
+
line(x1: number, y1: number, x2: number, y2: number, o?: LineOpts): this;
|
|
74
|
+
circle(cx: number, cy: number, r: number, o?: CircleOpts): this;
|
|
75
|
+
image(d: Uint8Array, x: number, y: number, o?: ImageOpts): this;
|
|
76
|
+
link(t: string, url: string, x: number, y: number, o?: LinkOpts): this;
|
|
77
|
+
table(data: string[][], x: number, y: number, o: TableOpts): this;
|
|
78
|
+
imagePng(d: Uint8Array, x: number, y: number, o?: ImageOpts): Promise<this>;
|
|
79
|
+
private ensure;
|
|
80
|
+
build(): Uint8Array;
|
|
81
|
+
save(path: string): Promise<void>;
|
|
82
|
+
}
|
|
83
|
+
export declare const pdfPlus: (s?: Size | keyof typeof SIZES) => PDFPlus;
|
|
84
|
+
//# sourceMappingURL=plus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plus.d.ts","sourceRoot":"","sources":["../src/plus.ts"],"names":[],"mappings":"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"}
|
package/dist/plus.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{createRequire as e}from"node:module";var x=Object.create;var{getPrototypeOf:t,defineProperty:I,getOwnPropertyNames:c}=Object;var p=Object.prototype.hasOwnProperty;var g=(q,K,L)=>{L=q!=null?x(t(q)):{};let Q=K||!q||!q.__esModule?I(L,"default",{value:q,enumerable:!0}):L;for(let U of c(q))if(!p.call(Q,U))I(Q,U,{get:()=>q[U],enumerable:!0});return Q};var b=e(import.meta.url);var m={A4:{width:595,height:842},A3:{width:842,height:1191},A5:{width:420,height:595},LETTER:{width:612,height:792}},h={helvetica:{normal:"Helvetica",bold:"Helvetica-Bold",italic:"Helvetica-Oblique",bolditalic:"Helvetica-BoldOblique"},times:{normal:"Times-Roman",bold:"Times-Bold",italic:"Times-Italic",bolditalic:"Times-BoldItalic"},courier:{normal:"Courier",bold:"Courier-Bold",italic:"Courier-Oblique",bolditalic:"Courier-BoldOblique"}},l=(q)=>{if(Array.isArray(q))return q;let K=q.replace("#","");if(K.length===3)return[parseInt(K[0]+K[0],16)/255,parseInt(K[1]+K[1],16)/255,parseInt(K[2]+K[2],16)/255];return[parseInt(K.slice(0,2),16)/255,parseInt(K.slice(2,4),16)/255,parseInt(K.slice(4,6),16)/255]},T=(q)=>{let[K,L,Q]=l(q);return`${K.toFixed(3)} ${L.toFixed(3)} ${Q.toFixed(3)} rg`},u=(q)=>{let[K,L,Q]=l(q);return`${K.toFixed(3)} ${L.toFixed(3)} ${Q.toFixed(3)} RG`},F=(q)=>q.replace(/\\/g,"\\\\").replace(/\(/g,"\\(").replace(/\)/g,"\\)"),W=(q)=>Number.isInteger(q)?q.toString():q.toFixed(2),k=(q,K)=>q.length*K*0.52,n=(q)=>{if(q[0]!==137||q[1]!==80||q[2]!==78||q[3]!==71)return null;let K=8,L=0,Q=0,U=0,V=[];while(K<q.length){let B=q[K]<<24|q[K+1]<<16|q[K+2]<<8|q[K+3],z=String.fromCharCode(q[K+4],q[K+5],q[K+6],q[K+7]);if(z==="IHDR")L=q[K+8]<<24|q[K+9]<<16|q[K+10]<<8|q[K+11],Q=q[K+12]<<24|q[K+13]<<16|q[K+14]<<8|q[K+15],U=q[K+17];else if(z==="IDAT")V.push(q.slice(K+8,K+8+B));else if(z==="IEND")break;K+=12+B}if(!L||!V.length)return null;let X=V.reduce((B,z)=>B+z.length,0),C=new Uint8Array(X),Z=0;for(let B of V)C.set(B,Z),Z+=B.length;return{w:L,h:Q,colorType:U,idat:C}},i=(q,K,L,Q)=>{let U=Q===6?4:Q===2?3:Q===4?2:1,V=K*U+1,X=new Uint8Array(K*L*3),C=Q===6||Q===4?new Uint8Array(K*L):void 0,Z=(B,z,_)=>{let Y=B+z-_,J=Math.abs(Y-B),D=Math.abs(Y-z),N=Math.abs(Y-_);return J<=D&&J<=N?B:D<=N?z:_};for(let B=0;B<L;B++){let z=q[B*V];for(let _=0;_<K*U;_++){let Y=B*V+1+_,J=_>=U?q[Y-U]:0,D=B>0?q[(B-1)*V+1+_]:0,N=_>=U&&B>0?q[(B-1)*V+1+_-U]:0;if(z===1)q[Y]=q[Y]+J&255;else if(z===2)q[Y]=q[Y]+D&255;else if(z===3)q[Y]=q[Y]+Math.floor((J+D)/2)&255;else if(z===4)q[Y]=q[Y]+Z(J,D,N)&255}for(let _=0;_<K;_++){let Y=B*V+1+_*U,J=(B*K+_)*3;if(Q===6){if(X[J]=q[Y],X[J+1]=q[Y+1],X[J+2]=q[Y+2],C)C[B*K+_]=q[Y+3]}else if(Q===4){if(X[J]=X[J+1]=X[J+2]=q[Y],C)C[B*K+_]=q[Y+1]}else if(Q===2)X[J]=q[Y],X[J+1]=q[Y+1],X[J+2]=q[Y+2];else X[J]=X[J+1]=X[J+2]=q[Y]}}return{w:K,h:L,rgb:X,alpha:C}},r=(q)=>{let K=(O)=>q[O]<<8|q[O+1],L=(O)=>{let $=K(O);return $>32767?$-65536:$},Q=(O)=>q[O]<<24|q[O+1]<<16|q[O+2]<<8|q[O+3],U=K(4),V={};for(let O=0;O<U;O++){let $=12+O*16;V[String.fromCharCode(q[$],q[$+1],q[$+2],q[$+3])]={offset:Q($+8),length:Q($+12)}}if(!V.head||!V.hhea||!V.hmtx||!V.maxp)return null;let X=V.head.offset,C=K(X+18),Z=[L(X+36),L(X+38),L(X+40),L(X+42)],B=V.hhea.offset,z=L(B+4),_=L(B+6),Y=K(B+34),J=V.hmtx.offset,D=[];for(let O=0;O<Math.min(Y,256);O++)D.push(K(J+O*4));let N="CustomFont";if(V.name){let O=V.name.offset,$=K(O+2),M=O+K(O+4);for(let H=0;H<$;H++){let E=O+6+H*12;if(K(E+6)===6){N=Array.from(q.slice(M+K(E+10),M+K(E+10)+K(E+8))).filter((G)=>G>31&&G<127).map((G)=>String.fromCharCode(G)).join("");break}}}return{name:N.replace(/[^a-zA-Z0-9]/g,""),unitsPerEm:C,ascent:z,descent:_,bbox:Z,widths:D,data:q}};class f{c=[];s=0;e=new TextEncoder;w(q){let K=typeof q==="string"?this.e.encode(q):q;return this.c.push(K),this.s+=K.length,this}l(q){return this.w(q+`
|
|
2
|
+
`)}size(){return this.s}out(){let q=new Uint8Array(this.s),K=0;for(let L of this.c)q.set(L,K),K+=L.length;return q}}class w{w;h;c=[];f=new Set;imgs=[];links=[];ic=0;constructor(q){this.w=q.width,this.h=q.height}text(q,K,L,Q={}){let U=Q.size??12,V=Q.weight??"normal",X=Q.color??"#000",C=Q.align??"left",Z=Q.font&&h[Q.font]?Q.font:"helvetica",B=h[Z][V];this.f.add(B);let z=this.h-L,_=K,Y=Q.maxWidth?this.wrap(q,Q.maxWidth,U):[q];for(let J of Y)_=C==="center"?K-k(J,U)/2:C==="right"?K-k(J,U):K,this.c.push("q","BT",T(X),`/${B.replace("-","")} ${U} Tf`,`${W(_)} ${W(z)} Td`,`(${F(J)}) Tj`,"ET","Q"),z-=U*1.2;return this}rect(q,K,L,Q,U={}){let V=this.h-K-Q;if(this.c.push("q"),U.radius&&U.radius>0){let X=Math.min(U.radius,L/2,Q/2);this.c.push(`${W(q+X)} ${W(V)} m`,`${W(q+L-X)} ${W(V)} l`,`${W(q+L)} ${W(V)} ${W(q+L)} ${W(V+X)} y`,`${W(q+L)} ${W(V+Q-X)} l`,`${W(q+L)} ${W(V+Q)} ${W(q+L-X)} ${W(V+Q)} y`,`${W(q+X)} ${W(V+Q)} l`,`${W(q)} ${W(V+Q)} ${W(q)} ${W(V+Q-X)} y`,`${W(q)} ${W(V+X)} l`,`${W(q)} ${W(V)} ${W(q+X)} ${W(V)} y`,"h")}else this.c.push(`${W(q)} ${W(V)} ${W(L)} ${W(Q)} re`);if(U.fill)this.c.push(T(U.fill)),this.c.push(U.stroke?"B":"f");if(U.stroke){if(this.c.push(u(U.stroke)),U.lineWidth)this.c.push(`${U.lineWidth} w`);if(!U.fill)this.c.push("S")}return this.c.push("Q"),this}line(q,K,L,Q,U={}){if(this.c.push("q"),U.color)this.c.push(u(U.color));if(U.width)this.c.push(`${U.width} w`);if(U.dash)this.c.push(`[${U.dash.join(" ")}] 0 d`);return this.c.push(`${W(q)} ${W(this.h-K)} m`,`${W(L)} ${W(this.h-Q)} l`,"S","Q"),this}circle(q,K,L,Q={}){let U=this.h-K;if(this.c.push("q"),this.c.push(`${W(q+L)} ${W(U)} m`,`${W(q+L)} ${W(U+L*0.5523)} ${W(q+L*0.5523)} ${W(U+L)} ${W(q)} ${W(U+L)} c`,`${W(q-L*0.5523)} ${W(U+L)} ${W(q-L)} ${W(U+L*0.5523)} ${W(q-L)} ${W(U)} c`,`${W(q-L*0.5523)} ${W(U-L)} ${W(q-L)} ${W(U-L*0.5523)} ${W(q)} ${W(U-L)} c`,`${W(q+L*0.5523)} ${W(U-L)} ${W(q+L)} ${W(U-L*0.5523)} ${W(q+L)} ${W(U)} c`),Q.fill)this.c.push(T(Q.fill)),this.c.push(Q.stroke?"B":"f");if(Q.stroke){if(this.c.push(u(Q.stroke)),Q.lineWidth)this.c.push(`${Q.lineWidth} w`);if(!Q.fill)this.c.push("S")}return this.c.push("Q"),this}image(q,K,L,Q={},U){let V=U||this.imgInfo(q);if(!V)return this;let X=Q.width??V.w,C=Q.height??V.h,Z=`I${++this.ic}`,B=U?"png":"jpeg";return this.imgs.push({d:q,w:V.w,h:V.h,x:K,y:this.h-L-C,id:Z,fmt:B,png:U}),this.c.push("q",`${W(X)} 0 0 ${W(C)} ${W(K)} ${W(this.h-L-C)} cm`,`/${Z} Do`,"Q"),this}link(q,K,L,Q,U={}){let V=U.color??"#00E";this.text(q,L,Q,{color:V,size:12});let C=k(q,12);if(U.underline!==!1)this.line(L,Q+2,L+C,Q+2,{color:V,width:0.5});return this.links.push({x:L,y:this.h-Q-12,w:C,h:12,url:K}),this}table(q,K,L,Q){let U=Q.padding??8,V=Q.fontSize??10,X=V+U*2,C=Q.columns.map((_,Y)=>_.width??Math.max(k(_.header,V),...q.map((J)=>k(J[Y]??"",V)))+U*2),Z=C.reduce((_,Y)=>_+Y,0),B=L;this.rect(K,B,Z,X,{fill:Q.headerBg??"#F0F0F0"});let z=K;for(let _=0;_<Q.columns.length;_++){let Y=Q.columns[_];this.text(Y.header,z+(Y.align==="center"?C[_]/2:Y.align==="right"?C[_]-U:U),B+U+V*0.8,{size:V,weight:"bold",color:Q.headerColor??"#000",align:Y.align}),z+=C[_]}B+=X;for(let _=0;_<q.length;_++){this.rect(K,B,Z,X,{fill:_%2?"#F9F9F9":"#FFF"}),z=K;for(let Y=0;Y<Q.columns.length;Y++){let J=Q.columns[Y];this.text(q[_][Y]??"",z+(J.align==="center"?C[Y]/2:J.align==="right"?C[Y]-U:U),B+U+V*0.8,{size:V,align:J.align}),z+=C[Y]}B+=X}return this.rect(K,L,Z,X*(q.length+1),{stroke:Q.borderColor??"#CCC"}),this}wrap(q,K,L){let Q=q.split(" "),U=[],V="";for(let X of Q){let C=V?`${V} ${X}`:X;if(k(C,L)<=K)V=C;else{if(V)U.push(V);V=X}}if(V)U.push(V);return U}imgInfo(q){if(q[0]===255&&q[1]===216){let K=2;while(K<q.length){if(q[K]!==255)break;let L=q[K+1];if(L>=192&&L<=207&&L!==196&&L!==200&&L!==204)return{h:q[K+5]<<8|q[K+6],w:q[K+7]<<8|q[K+8]};K+=2+(q[K+2]<<8|q[K+3])}}return null}}class y{pages=[];cur=null;sz;meta;customFonts=new Map;constructor(q="A4"){this.sz=typeof q==="string"?m[q]:q}metadata(q){return this.meta=q,this}registerFont(q,K){let L=r(K);if(L)this.customFonts.set(q,L);return this}page(q){return this.cur=new w(q?typeof q==="string"?m[q]:q:this.sz),this.pages.push(this.cur),this}text(q,K,L,Q){return this.ensure().text(q,K,L,Q),this}rect(q,K,L,Q,U){return this.ensure().rect(q,K,L,Q,U),this}line(q,K,L,Q,U){return this.ensure().line(q,K,L,Q,U),this}circle(q,K,L,Q){return this.ensure().circle(q,K,L,Q),this}image(q,K,L,Q){return this.ensure().image(q,K,L,Q),this}link(q,K,L,Q,U){return this.ensure().link(q,K,L,Q,U),this}table(q,K,L,Q){return this.ensure().table(q,K,L,Q),this}async imagePng(q,K,L,Q){let U=n(q);if(!U)return this;let V;if(typeof Bun<"u")V=Bun.inflateSync(new Uint8Array(U.idat));else{let{inflateSync:C}=await import("zlib");V=new Uint8Array(C(U.idat))}let X=i(V,U.w,U.h,U.colorType);return this.ensure().image(q,K,L,Q,X),this}ensure(){if(!this.cur)this.page();return this.cur}build(){let q=new f,K=[0],L=0;q.l("%PDF-1.4").l("%µµµµ");let Q=new Set;this.pages.forEach(($)=>$.f.forEach((M)=>Q.add(M)));let U=Array.from(Q),V={};for(let $ of U){let M=++L;V[$]=M,K[M]=q.size(),q.l(`${M} 0 obj`).l(`<</Type/Font/Subtype/Type1/BaseFont/${$}>>`).l("endobj")}let X={};for(let[$,M]of this.customFonts){let H=++L;K[H]=q.size(),q.l(`${H} 0 obj`).l(`<</Length ${M.data.length}/Length1 ${M.data.length}>>`).l("stream"),q.w(M.data).l("").l("endstream").l("endobj");let E=++L;K[E]=q.size();let G=1000/M.unitsPerEm;q.l(`${E} 0 obj`).l(`<</Type/FontDescriptor/FontName/${M.name}/Flags 32/FontBBox[${M.bbox.map((j)=>Math.round(j*G)).join(" ")}]/ItalicAngle 0/Ascent ${Math.round(M.ascent*G)}/Descent ${Math.round(M.descent*G)}/CapHeight ${Math.round(M.ascent*G*0.7)}/StemV 80/FontFile2 ${H} 0 R>>`).l("endobj");let R=++L;K[R]=q.size();let v=M.widths.slice(0,256).map((j)=>Math.round(j*G)).join(" ");q.l(`${R} 0 obj`).l(`<</Type/Font/Subtype/TrueType/BaseFont/${M.name}/FirstChar 0/LastChar 255/Widths[${v}]/FontDescriptor ${E} 0 R/Encoding/WinAnsiEncoding>>`).l("endobj"),X[$]={fontId:R,descId:E,fileId:H}}let C=[],Z=[],B=[],z=[];for(let $ of this.pages){let M=[],H=[];for(let j of $.imgs)if(j.fmt==="png"&&j.png){let A=j.png,P=0;if(A.alpha)P=++L,H.push(P),K[P]=q.size(),q.l(`${P} 0 obj`).l(`<</Type/XObject/Subtype/Image/Width ${A.w}/Height ${A.h}/ColorSpace/DeviceGray/BitsPerComponent 8/Length ${A.alpha.length}>>`).l("stream"),q.w(A.alpha).l("").l("endstream").l("endobj");let S=++L;M.push(S),K[S]=q.size(),q.l(`${S} 0 obj`).l(`<</Type/XObject/Subtype/Image/Width ${A.w}/Height ${A.h}/ColorSpace/DeviceRGB/BitsPerComponent 8${P?`/SMask ${P} 0 R`:""}/Length ${A.rgb.length}>>`).l("stream"),q.w(A.rgb).l("").l("endstream").l("endobj")}else{let A=++L;M.push(A),K[A]=q.size(),q.l(`${A} 0 obj`).l(`<</Type/XObject/Subtype/Image/Width ${j.w}/Height ${j.h}/ColorSpace/DeviceRGB/BitsPerComponent 8/Filter/DCTDecode/Length ${j.d.length}>>`).l("stream"),q.w(j.d).l("").l("endstream").l("endobj")}B.push(M),z.push(H);let E=$.c.join(`
|
|
3
|
+
`),G=new TextEncoder().encode(E).length,R=++L;C.push(R),K[R]=q.size(),q.l(`${R} 0 obj`).l(`<</Length ${G}>>`).l("stream").w(E).l("").l("endstream").l("endobj");let v=[];for(let j of $.links){let A=++L;v.push(A),K[A]=q.size(),q.l(`${A} 0 obj`).l(`<</Type/Annot/Subtype/Link/Rect[${j.x} ${j.y} ${j.x+j.w} ${j.y+j.h}]/Border[0 0 0]/A<</Type/Action/S/URI/URI(${j.url})>>>>`).l("endobj")}Z.push(v)}let _=++L,Y=L+1,J=this.pages.map(($,M)=>Y+M);K[_]=q.size(),q.l(`${_} 0 obj`).l(`<</Type/Pages/Kids[${J.map(($)=>`${$} 0 R`).join(" ")}]/Count ${J.length}>>`).l("endobj");for(let $=0;$<this.pages.length;$++){let M=this.pages[$],H=++L,E=Array.from(M.f).map((j)=>`/${j.replace("-","")} ${V[j]} 0 R`).join(""),G=Array.from(this.customFonts.keys()).map((j)=>`/${j} ${X[j].fontId} 0 R`).join(""),R=M.imgs.map((j,A)=>`/${j.id} ${B[$][A]} 0 R`).join(""),v=Z[$].length?`/Annots[${Z[$].map((j)=>`${j} 0 R`).join(" ")}]`:"";K[H]=q.size(),q.l(`${H} 0 obj`).l(`<</Type/Page/Parent ${_} 0 R/MediaBox[0 0 ${M.w} ${M.h}]/Contents ${C[$]} 0 R/Resources<<${E||G?`/Font<<${E}${G}>>`:""}${R?`/XObject<<${R}>>`:""}>>${v}>>`).l("endobj")}let D=0;if(this.meta){D=++L,K[D]=q.size();let $=new Date,M=`D:${$.getFullYear()}${String($.getMonth()+1).padStart(2,"0")}${String($.getDate()).padStart(2,"0")}${String($.getHours()).padStart(2,"0")}${String($.getMinutes()).padStart(2,"0")}${String($.getSeconds()).padStart(2,"0")}`,H=this.meta;q.l(`${D} 0 obj`).l(`<<${H.title?`/Title(${F(H.title)})`:""}${H.author?`/Author(${F(H.author)})`:""}${H.subject?`/Subject(${F(H.subject)})`:""}${H.keywords?`/Keywords(${F(H.keywords)})`:""}${H.creator?`/Creator(${F(H.creator)})`:""}/Producer(podpdf)/CreationDate(${M})>>`).l("endobj")}let N=++L;K[N]=q.size(),q.l(`${N} 0 obj`).l(`<</Type/Catalog/Pages ${_} 0 R>>`).l("endobj");let O=q.size();q.l("xref").l(`0 ${L+1}`).l("0000000000 65535 f ");for(let $=1;$<=L;$++)q.l(`${K[$].toString().padStart(10,"0")} 00000 n `);return q.l("trailer").l(`<</Size ${L+1}/Root ${N} 0 R${D?`/Info ${D} 0 R`:""}>>`).l("startxref").l(O.toString()).l("%%EOF"),q.out()}async save(q){let K=this.build();if(typeof Bun<"u")await Bun.write(q,K);else{let{writeFile:L}=await import("fs/promises");await L(q,K)}}}var d=(q)=>new y(q);export{d as pdfPlus,m as SIZES,y as PDFPlus};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "podpdf",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "Ultra-fast, zero-dependency PDF generation
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "Ultra-fast, zero-dependency PDF generation for Node.js, Bun & Browser. 8KB minified, 5x faster than jsPDF.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -10,13 +10,23 @@
|
|
|
10
10
|
".": {
|
|
11
11
|
"import": "./dist/index.js",
|
|
12
12
|
"types": "./dist/index.d.ts"
|
|
13
|
+
},
|
|
14
|
+
"./plus": {
|
|
15
|
+
"import": "./dist/plus.js",
|
|
16
|
+
"types": "./dist/plus.d.ts"
|
|
17
|
+
},
|
|
18
|
+
"./browser": {
|
|
19
|
+
"import": "./dist/browser.js",
|
|
20
|
+
"types": "./dist/browser.d.ts"
|
|
13
21
|
}
|
|
14
22
|
},
|
|
15
23
|
"files": [
|
|
16
24
|
"dist"
|
|
17
25
|
],
|
|
18
26
|
"scripts": {
|
|
19
|
-
"build": "bun build
|
|
27
|
+
"build": "bun run build:node && bun run build:browser && bun run build:types",
|
|
28
|
+
"build:node": "bun build src/index.ts src/plus.ts --outdir dist --target node --minify",
|
|
29
|
+
"build:browser": "bun build src/browser.ts --outdir dist --target browser --minify",
|
|
20
30
|
"build:types": "tsc --emitDeclarationOnly",
|
|
21
31
|
"dev": "bun --watch src/index.ts",
|
|
22
32
|
"test": "bun test/test.ts",
|
|
@@ -35,7 +45,10 @@
|
|
|
35
45
|
"zero-dependency",
|
|
36
46
|
"fast",
|
|
37
47
|
"lightweight",
|
|
38
|
-
"minimal"
|
|
48
|
+
"minimal",
|
|
49
|
+
"browser",
|
|
50
|
+
"browser-pdf",
|
|
51
|
+
"client-side"
|
|
39
52
|
],
|
|
40
53
|
"author": "",
|
|
41
54
|
"license": "MIT",
|