@lexmata/micropdf 0.4.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.
Files changed (170) hide show
  1. package/LICENSE +191 -0
  2. package/README.md +985 -0
  3. package/binding.gyp +73 -0
  4. package/dist/annot.d.ts +458 -0
  5. package/dist/annot.d.ts.map +1 -0
  6. package/dist/annot.js +697 -0
  7. package/dist/annot.js.map +1 -0
  8. package/dist/archive.d.ts +128 -0
  9. package/dist/archive.d.ts.map +1 -0
  10. package/dist/archive.js +268 -0
  11. package/dist/archive.js.map +1 -0
  12. package/dist/buffer.d.ts +572 -0
  13. package/dist/buffer.d.ts.map +1 -0
  14. package/dist/buffer.js +971 -0
  15. package/dist/buffer.js.map +1 -0
  16. package/dist/colorspace.d.ts +287 -0
  17. package/dist/colorspace.d.ts.map +1 -0
  18. package/dist/colorspace.js +542 -0
  19. package/dist/colorspace.js.map +1 -0
  20. package/dist/context.d.ts +184 -0
  21. package/dist/context.d.ts.map +1 -0
  22. package/dist/context.js +320 -0
  23. package/dist/context.js.map +1 -0
  24. package/dist/cookie.d.ts +164 -0
  25. package/dist/cookie.d.ts.map +1 -0
  26. package/dist/cookie.js +306 -0
  27. package/dist/cookie.js.map +1 -0
  28. package/dist/device.d.ts +169 -0
  29. package/dist/device.d.ts.map +1 -0
  30. package/dist/device.js +350 -0
  31. package/dist/device.js.map +1 -0
  32. package/dist/display-list.d.ts +202 -0
  33. package/dist/display-list.d.ts.map +1 -0
  34. package/dist/display-list.js +410 -0
  35. package/dist/display-list.js.map +1 -0
  36. package/dist/document.d.ts +637 -0
  37. package/dist/document.d.ts.map +1 -0
  38. package/dist/document.js +902 -0
  39. package/dist/document.js.map +1 -0
  40. package/dist/easy.d.ts +423 -0
  41. package/dist/easy.d.ts.map +1 -0
  42. package/dist/easy.js +644 -0
  43. package/dist/easy.js.map +1 -0
  44. package/dist/enhanced.d.ts +226 -0
  45. package/dist/enhanced.d.ts.map +1 -0
  46. package/dist/enhanced.js +368 -0
  47. package/dist/enhanced.js.map +1 -0
  48. package/dist/filter.d.ts +51 -0
  49. package/dist/filter.d.ts.map +1 -0
  50. package/dist/filter.js +381 -0
  51. package/dist/filter.js.map +1 -0
  52. package/dist/font.d.ts +222 -0
  53. package/dist/font.d.ts.map +1 -0
  54. package/dist/font.js +381 -0
  55. package/dist/font.js.map +1 -0
  56. package/dist/form.d.ts +214 -0
  57. package/dist/form.d.ts.map +1 -0
  58. package/dist/form.js +497 -0
  59. package/dist/form.js.map +1 -0
  60. package/dist/geometry.d.ts +469 -0
  61. package/dist/geometry.d.ts.map +1 -0
  62. package/dist/geometry.js +780 -0
  63. package/dist/geometry.js.map +1 -0
  64. package/dist/image.d.ts +172 -0
  65. package/dist/image.d.ts.map +1 -0
  66. package/dist/image.js +348 -0
  67. package/dist/image.js.map +1 -0
  68. package/dist/index.d.ts +171 -0
  69. package/dist/index.d.ts.map +1 -0
  70. package/dist/index.js +339 -0
  71. package/dist/index.js.map +1 -0
  72. package/dist/link.d.ts +168 -0
  73. package/dist/link.d.ts.map +1 -0
  74. package/dist/link.js +343 -0
  75. package/dist/link.js.map +1 -0
  76. package/dist/micropdf.d.ts +40 -0
  77. package/dist/micropdf.d.ts.map +1 -0
  78. package/dist/micropdf.js +45 -0
  79. package/dist/micropdf.js.map +1 -0
  80. package/dist/nanopdf.d.ts +40 -0
  81. package/dist/nanopdf.d.ts.map +1 -0
  82. package/dist/nanopdf.js +45 -0
  83. package/dist/nanopdf.js.map +1 -0
  84. package/dist/native.d.ts +242 -0
  85. package/dist/native.d.ts.map +1 -0
  86. package/dist/native.js +509 -0
  87. package/dist/native.js.map +1 -0
  88. package/dist/output.d.ts +166 -0
  89. package/dist/output.d.ts.map +1 -0
  90. package/dist/output.js +365 -0
  91. package/dist/output.js.map +1 -0
  92. package/dist/path.d.ts +420 -0
  93. package/dist/path.d.ts.map +1 -0
  94. package/dist/path.js +687 -0
  95. package/dist/path.js.map +1 -0
  96. package/dist/pdf/object.d.ts +489 -0
  97. package/dist/pdf/object.d.ts.map +1 -0
  98. package/dist/pdf/object.js +1045 -0
  99. package/dist/pdf/object.js.map +1 -0
  100. package/dist/pixmap.d.ts +315 -0
  101. package/dist/pixmap.d.ts.map +1 -0
  102. package/dist/pixmap.js +590 -0
  103. package/dist/pixmap.js.map +1 -0
  104. package/dist/profiler.d.ts +159 -0
  105. package/dist/profiler.d.ts.map +1 -0
  106. package/dist/profiler.js +380 -0
  107. package/dist/profiler.js.map +1 -0
  108. package/dist/render-options.d.ts +227 -0
  109. package/dist/render-options.d.ts.map +1 -0
  110. package/dist/render-options.js +130 -0
  111. package/dist/render-options.js.map +1 -0
  112. package/dist/resource-tracking.d.ts +332 -0
  113. package/dist/resource-tracking.d.ts.map +1 -0
  114. package/dist/resource-tracking.js +653 -0
  115. package/dist/resource-tracking.js.map +1 -0
  116. package/dist/simple.d.ts +276 -0
  117. package/dist/simple.d.ts.map +1 -0
  118. package/dist/simple.js +343 -0
  119. package/dist/simple.js.map +1 -0
  120. package/dist/stext.d.ts +290 -0
  121. package/dist/stext.d.ts.map +1 -0
  122. package/dist/stext.js +312 -0
  123. package/dist/stext.js.map +1 -0
  124. package/dist/stream.d.ts +174 -0
  125. package/dist/stream.d.ts.map +1 -0
  126. package/dist/stream.js +476 -0
  127. package/dist/stream.js.map +1 -0
  128. package/dist/text.d.ts +337 -0
  129. package/dist/text.d.ts.map +1 -0
  130. package/dist/text.js +454 -0
  131. package/dist/text.js.map +1 -0
  132. package/dist/typed-arrays.d.ts +127 -0
  133. package/dist/typed-arrays.d.ts.map +1 -0
  134. package/dist/typed-arrays.js +410 -0
  135. package/dist/typed-arrays.js.map +1 -0
  136. package/dist/types.d.ts +358 -0
  137. package/dist/types.d.ts.map +1 -0
  138. package/dist/types.js +216 -0
  139. package/dist/types.js.map +1 -0
  140. package/native/annot.cc +557 -0
  141. package/native/buffer.cc +204 -0
  142. package/native/colorspace.cc +166 -0
  143. package/native/context.cc +84 -0
  144. package/native/cookie.cc +179 -0
  145. package/native/device.cc +179 -0
  146. package/native/display_list.cc +179 -0
  147. package/native/document.cc +268 -0
  148. package/native/enhanced.cc +70 -0
  149. package/native/font.cc +282 -0
  150. package/native/form.cc +523 -0
  151. package/native/geometry.cc +255 -0
  152. package/native/image.cc +216 -0
  153. package/native/include/micropdf/enhanced.h +38 -0
  154. package/native/include/micropdf/types.h +36 -0
  155. package/native/include/micropdf.h +106 -0
  156. package/native/include/mupdf-ffi.h +39 -0
  157. package/native/include/mupdf.h +11 -0
  158. package/native/include/mupdf_minimal.h +381 -0
  159. package/native/lib/linux-x64/libmicropdf.a +0 -0
  160. package/native/link.cc +234 -0
  161. package/native/micropdf.cc +71 -0
  162. package/native/output.cc +229 -0
  163. package/native/page.cc +572 -0
  164. package/native/path.cc +259 -0
  165. package/native/pixmap.cc +240 -0
  166. package/native/stext.cc +610 -0
  167. package/native/stream.cc +239 -0
  168. package/package.json +120 -0
  169. package/scripts/build-from-rust.js +97 -0
  170. package/scripts/install.js +184 -0
@@ -0,0 +1,276 @@
1
+ /**
2
+ * Simple API - Ultra-simplified functions for common PDF tasks
3
+ *
4
+ * This module provides the simplest possible API for basic PDF operations.
5
+ * Perfect for beginners or quick scripts.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import * as pdf from 'micropdf/simple';
10
+ *
11
+ * // Extract all text
12
+ * const text = await pdf.extractText('document.pdf');
13
+ *
14
+ * // Render first page to PNG
15
+ * await pdf.renderToPNG('document.pdf', 'output.png');
16
+ *
17
+ * // Get page count
18
+ * const pages = await pdf.getPageCount('document.pdf');
19
+ * ```
20
+ */
21
+ import { type PdfMetadata, type DocumentInfo } from './easy.js';
22
+ /**
23
+ * Extract all text from a PDF
24
+ *
25
+ * @param pdfPath - Path to PDF file
26
+ * @param password - Optional password for encrypted PDFs
27
+ * @returns All text from the PDF
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * const text = await extractText('document.pdf');
32
+ * console.log(text);
33
+ * ```
34
+ */
35
+ export declare function extractText(pdfPath: string, password?: string): Promise<string>;
36
+ /**
37
+ * Extract text from a specific page
38
+ *
39
+ * @param pdfPath - Path to PDF file
40
+ * @param pageNumber - Page number (0-indexed)
41
+ * @param password - Optional password for encrypted PDFs
42
+ * @returns Text from the specified page
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * const text = await extractPageText('document.pdf', 0);
47
+ * console.log(text);
48
+ * ```
49
+ */
50
+ export declare function extractPageText(pdfPath: string, pageNumber: number, password?: string): Promise<string>;
51
+ /**
52
+ * Get the number of pages in a PDF
53
+ *
54
+ * @param pdfPath - Path to PDF file
55
+ * @param password - Optional password for encrypted PDFs
56
+ * @returns Number of pages
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * const count = await getPageCount('document.pdf');
61
+ * console.log(`Document has ${count} pages`);
62
+ * ```
63
+ */
64
+ export declare function getPageCount(pdfPath: string, password?: string): Promise<number>;
65
+ /**
66
+ * Get PDF metadata (title, author, etc.)
67
+ *
68
+ * @param pdfPath - Path to PDF file
69
+ * @param password - Optional password for encrypted PDFs
70
+ * @returns PDF metadata
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * const meta = await getMetadata('document.pdf');
75
+ * console.log(meta.title);
76
+ * console.log(meta.author);
77
+ * ```
78
+ */
79
+ export declare function getMetadata(pdfPath: string, password?: string): Promise<PdfMetadata>;
80
+ /**
81
+ * Get complete document information
82
+ *
83
+ * @param pdfPath - Path to PDF file
84
+ * @param password - Optional password for encrypted PDFs
85
+ * @returns Document information including metadata and page details
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * const info = await getInfo('document.pdf');
90
+ * console.log(`Pages: ${info.pageCount}`);
91
+ * console.log(`Title: ${info.metadata.title}`);
92
+ * info.pages.forEach((page, i) => {
93
+ * console.log(`Page ${i}: ${page.width}x${page.height}`);
94
+ * });
95
+ * ```
96
+ */
97
+ export declare function getInfo(pdfPath: string, password?: string): Promise<DocumentInfo>;
98
+ /**
99
+ * Render a page to PNG
100
+ *
101
+ * @param pdfPath - Path to PDF file
102
+ * @param outputPath - Output PNG file path
103
+ * @param pageNumber - Page number (0-indexed, default: 0)
104
+ * @param dpi - DPI for rendering (default: 150)
105
+ * @param password - Optional password for encrypted PDFs
106
+ *
107
+ * @example
108
+ * ```typescript
109
+ * // Render first page at 150 DPI
110
+ * await renderToPNG('document.pdf', 'output.png');
111
+ *
112
+ * // Render second page at 300 DPI
113
+ * await renderToPNG('document.pdf', 'output.png', 1, 300);
114
+ * ```
115
+ */
116
+ export declare function renderToPNG(pdfPath: string, outputPath: string, pageNumber?: number, dpi?: number, password?: string): Promise<void>;
117
+ /**
118
+ * Render all pages to PNG files
119
+ *
120
+ * @param pdfPath - Path to PDF file
121
+ * @param outputPattern - Output file pattern (use {page} for page number)
122
+ * @param dpi - DPI for rendering (default: 150)
123
+ * @param password - Optional password for encrypted PDFs
124
+ *
125
+ * @example
126
+ * ```typescript
127
+ * // Render all pages
128
+ * await renderAllToPNG('document.pdf', 'output/page-{page}.png');
129
+ *
130
+ * // High quality rendering
131
+ * await renderAllToPNG('document.pdf', 'output/page-{page}.png', 300);
132
+ * ```
133
+ */
134
+ export declare function renderAllToPNG(pdfPath: string, outputPattern: string, dpi?: number, password?: string): Promise<void>;
135
+ /**
136
+ * Get a page as a PNG buffer
137
+ *
138
+ * @param pdfPath - Path to PDF file
139
+ * @param pageNumber - Page number (0-indexed, default: 0)
140
+ * @param dpi - DPI for rendering (default: 150)
141
+ * @param password - Optional password for encrypted PDFs
142
+ * @returns PNG buffer
143
+ *
144
+ * @example
145
+ * ```typescript
146
+ * const buffer = await getPageAsPNG('document.pdf', 0, 300);
147
+ * await fs.writeFile('output.png', buffer);
148
+ * ```
149
+ */
150
+ export declare function getPageAsPNG(pdfPath: string, pageNumber?: number, dpi?: number, password?: string): Promise<Buffer>;
151
+ /**
152
+ * Search for text in a PDF
153
+ *
154
+ * @param pdfPath - Path to PDF file
155
+ * @param query - Text to search for
156
+ * @param password - Optional password for encrypted PDFs
157
+ * @returns Array of page numbers where text was found
158
+ *
159
+ * @example
160
+ * ```typescript
161
+ * const pages = await searchText('document.pdf', 'important');
162
+ * console.log(`Found on pages: ${pages.join(', ')}`);
163
+ * ```
164
+ */
165
+ export declare function searchText(pdfPath: string, query: string, password?: string): Promise<number[]>;
166
+ /**
167
+ * Check if a PDF is encrypted
168
+ *
169
+ * @param pdfPath - Path to PDF file
170
+ * @returns True if the PDF is encrypted
171
+ *
172
+ * @example
173
+ * ```typescript
174
+ * if (await isEncrypted('document.pdf')) {
175
+ * console.log('This PDF requires a password');
176
+ * }
177
+ * ```
178
+ */
179
+ export declare function isEncrypted(pdfPath: string): Promise<boolean>;
180
+ /**
181
+ * Save text extraction to a file
182
+ *
183
+ * @param pdfPath - Path to PDF file
184
+ * @param outputPath - Output text file path
185
+ * @param password - Optional password for encrypted PDFs
186
+ *
187
+ * @example
188
+ * ```typescript
189
+ * await saveTextToFile('document.pdf', 'output.txt');
190
+ * ```
191
+ */
192
+ export declare function saveTextToFile(pdfPath: string, outputPath: string, password?: string): Promise<void>;
193
+ /**
194
+ * Convert PDF to images (one per page)
195
+ *
196
+ * @param pdfPath - Path to PDF file
197
+ * @param outputDir - Output directory for images
198
+ * @param options - Rendering options
199
+ * @returns Array of output file paths
200
+ *
201
+ * @example
202
+ * ```typescript
203
+ * const files = await convertToImages('document.pdf', 'output/', {
204
+ * dpi: 300,
205
+ * format: 'png'
206
+ * });
207
+ * console.log(`Created ${files.length} images`);
208
+ * ```
209
+ */
210
+ export declare function convertToImages(pdfPath: string, outputDir: string, options?: {
211
+ dpi?: number;
212
+ format?: 'png' | 'pnm' | 'pam';
213
+ password?: string;
214
+ }): Promise<string[]>;
215
+ /**
216
+ * Quick info summary for a PDF
217
+ *
218
+ * @param pdfPath - Path to PDF file
219
+ * @param password - Optional password for encrypted PDFs
220
+ * @returns Human-readable summary string
221
+ *
222
+ * @example
223
+ * ```typescript
224
+ * const summary = await quickSummary('document.pdf');
225
+ * console.log(summary);
226
+ * // Output:
227
+ * // Document: document.pdf
228
+ * // Pages: 42
229
+ * // Title: My Document
230
+ * // Author: John Doe
231
+ * // Encrypted: No
232
+ * ```
233
+ */
234
+ export declare function quickSummary(pdfPath: string, password?: string): Promise<string>;
235
+ /**
236
+ * Merge multiple PDF files into a single output file
237
+ *
238
+ * This is the simplest way to merge PDFs - just provide the input paths and output path.
239
+ * Handles large documents (5000+ pages) and corrupted PDFs robustly.
240
+ *
241
+ * @param inputPaths - Array of PDF file paths to merge (in order)
242
+ * @param outputPath - Path where the merged PDF will be saved
243
+ * @returns Promise that resolves to the number of pages in the merged PDF
244
+ * @throws Error if any input file is invalid, not found, or merge fails
245
+ *
246
+ * @example Basic merge
247
+ * ```typescript
248
+ * import { mergePDF } from 'micropdf/simple';
249
+ *
250
+ * const pageCount = await mergePDF(
251
+ * ['document1.pdf', 'document2.pdf', 'document3.pdf'],
252
+ * 'merged.pdf'
253
+ * );
254
+ * console.log(`Merged ${pageCount} pages`);
255
+ * ```
256
+ *
257
+ * @example Large documents
258
+ * ```typescript
259
+ * // Works with large documents (5000+ pages)
260
+ * const pageCount = await mergePDF(
261
+ * ['large_doc1.pdf', 'large_doc2.pdf'],
262
+ * 'combined.pdf'
263
+ * );
264
+ * ```
265
+ *
266
+ * @example Error handling
267
+ * ```typescript
268
+ * try {
269
+ * await mergePDF(['doc1.pdf', 'doc2.pdf'], 'output.pdf');
270
+ * } catch (error) {
271
+ * console.error('Merge failed:', error.message);
272
+ * }
273
+ * ```
274
+ */
275
+ export declare function mergePDF(inputPaths: string[], outputPath: string): Promise<number>;
276
+ //# sourceMappingURL=simple.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simple.d.ts","sourceRoot":"","sources":["../src/simple.ts"],"names":[],"mappings":"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"}
package/dist/simple.js ADDED
@@ -0,0 +1,343 @@
1
+ /**
2
+ * Simple API - Ultra-simplified functions for common PDF tasks
3
+ *
4
+ * This module provides the simplest possible API for basic PDF operations.
5
+ * Perfect for beginners or quick scripts.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import * as pdf from 'micropdf/simple';
10
+ *
11
+ * // Extract all text
12
+ * const text = await pdf.extractText('document.pdf');
13
+ *
14
+ * // Render first page to PNG
15
+ * await pdf.renderToPNG('document.pdf', 'output.png');
16
+ *
17
+ * // Get page count
18
+ * const pages = await pdf.getPageCount('document.pdf');
19
+ * ```
20
+ */
21
+ import { EasyPDF } from './easy.js';
22
+ import { Context } from './context.js';
23
+ import { Enhanced } from './enhanced.js';
24
+ import * as fs from 'fs/promises';
25
+ /**
26
+ * Extract all text from a PDF
27
+ *
28
+ * @param pdfPath - Path to PDF file
29
+ * @param password - Optional password for encrypted PDFs
30
+ * @returns All text from the PDF
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * const text = await extractText('document.pdf');
35
+ * console.log(text);
36
+ * ```
37
+ */
38
+ export async function extractText(pdfPath, password) {
39
+ return EasyPDF.open(pdfPath, password).use((pdf) => pdf.extractAllText());
40
+ }
41
+ /**
42
+ * Extract text from a specific page
43
+ *
44
+ * @param pdfPath - Path to PDF file
45
+ * @param pageNumber - Page number (0-indexed)
46
+ * @param password - Optional password for encrypted PDFs
47
+ * @returns Text from the specified page
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * const text = await extractPageText('document.pdf', 0);
52
+ * console.log(text);
53
+ * ```
54
+ */
55
+ export async function extractPageText(pdfPath, pageNumber, password) {
56
+ return EasyPDF.open(pdfPath, password).use((pdf) => pdf.extractPageText(pageNumber));
57
+ }
58
+ /**
59
+ * Get the number of pages in a PDF
60
+ *
61
+ * @param pdfPath - Path to PDF file
62
+ * @param password - Optional password for encrypted PDFs
63
+ * @returns Number of pages
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * const count = await getPageCount('document.pdf');
68
+ * console.log(`Document has ${count} pages`);
69
+ * ```
70
+ */
71
+ export async function getPageCount(pdfPath, password) {
72
+ return EasyPDF.open(pdfPath, password).use((pdf) => pdf.pageCount);
73
+ }
74
+ /**
75
+ * Get PDF metadata (title, author, etc.)
76
+ *
77
+ * @param pdfPath - Path to PDF file
78
+ * @param password - Optional password for encrypted PDFs
79
+ * @returns PDF metadata
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * const meta = await getMetadata('document.pdf');
84
+ * console.log(meta.title);
85
+ * console.log(meta.author);
86
+ * ```
87
+ */
88
+ export async function getMetadata(pdfPath, password) {
89
+ return EasyPDF.open(pdfPath, password).use((pdf) => pdf.getMetadata());
90
+ }
91
+ /**
92
+ * Get complete document information
93
+ *
94
+ * @param pdfPath - Path to PDF file
95
+ * @param password - Optional password for encrypted PDFs
96
+ * @returns Document information including metadata and page details
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * const info = await getInfo('document.pdf');
101
+ * console.log(`Pages: ${info.pageCount}`);
102
+ * console.log(`Title: ${info.metadata.title}`);
103
+ * info.pages.forEach((page, i) => {
104
+ * console.log(`Page ${i}: ${page.width}x${page.height}`);
105
+ * });
106
+ * ```
107
+ */
108
+ export async function getInfo(pdfPath, password) {
109
+ return EasyPDF.open(pdfPath, password).use((pdf) => pdf.getInfo());
110
+ }
111
+ /**
112
+ * Render a page to PNG
113
+ *
114
+ * @param pdfPath - Path to PDF file
115
+ * @param outputPath - Output PNG file path
116
+ * @param pageNumber - Page number (0-indexed, default: 0)
117
+ * @param dpi - DPI for rendering (default: 150)
118
+ * @param password - Optional password for encrypted PDFs
119
+ *
120
+ * @example
121
+ * ```typescript
122
+ * // Render first page at 150 DPI
123
+ * await renderToPNG('document.pdf', 'output.png');
124
+ *
125
+ * // Render second page at 300 DPI
126
+ * await renderToPNG('document.pdf', 'output.png', 1, 300);
127
+ * ```
128
+ */
129
+ export async function renderToPNG(pdfPath, outputPath, pageNumber = 0, dpi = 150, password) {
130
+ await EasyPDF.open(pdfPath, password).useAsync(async (pdf) => {
131
+ await pdf.renderToFile(pageNumber, outputPath, { dpi, format: 'png' });
132
+ });
133
+ }
134
+ /**
135
+ * Render all pages to PNG files
136
+ *
137
+ * @param pdfPath - Path to PDF file
138
+ * @param outputPattern - Output file pattern (use {page} for page number)
139
+ * @param dpi - DPI for rendering (default: 150)
140
+ * @param password - Optional password for encrypted PDFs
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * // Render all pages
145
+ * await renderAllToPNG('document.pdf', 'output/page-{page}.png');
146
+ *
147
+ * // High quality rendering
148
+ * await renderAllToPNG('document.pdf', 'output/page-{page}.png', 300);
149
+ * ```
150
+ */
151
+ export async function renderAllToPNG(pdfPath, outputPattern, dpi = 150, password) {
152
+ await EasyPDF.open(pdfPath, password).useAsync(async (pdf) => {
153
+ await pdf.renderAllToFiles(outputPattern, { dpi, format: 'png' });
154
+ });
155
+ }
156
+ /**
157
+ * Get a page as a PNG buffer
158
+ *
159
+ * @param pdfPath - Path to PDF file
160
+ * @param pageNumber - Page number (0-indexed, default: 0)
161
+ * @param dpi - DPI for rendering (default: 150)
162
+ * @param password - Optional password for encrypted PDFs
163
+ * @returns PNG buffer
164
+ *
165
+ * @example
166
+ * ```typescript
167
+ * const buffer = await getPageAsPNG('document.pdf', 0, 300);
168
+ * await fs.writeFile('output.png', buffer);
169
+ * ```
170
+ */
171
+ export async function getPageAsPNG(pdfPath, pageNumber = 0, dpi = 150, password) {
172
+ return EasyPDF.open(pdfPath, password).use((pdf) => pdf.renderToBuffer(pageNumber, { dpi, format: 'png' }));
173
+ }
174
+ /**
175
+ * Search for text in a PDF
176
+ *
177
+ * @param pdfPath - Path to PDF file
178
+ * @param query - Text to search for
179
+ * @param password - Optional password for encrypted PDFs
180
+ * @returns Array of page numbers where text was found
181
+ *
182
+ * @example
183
+ * ```typescript
184
+ * const pages = await searchText('document.pdf', 'important');
185
+ * console.log(`Found on pages: ${pages.join(', ')}`);
186
+ * ```
187
+ */
188
+ export async function searchText(pdfPath, query, password) {
189
+ return EasyPDF.open(pdfPath, password).use((pdf) => {
190
+ const results = pdf.search(query);
191
+ // Return unique page numbers
192
+ return [...new Set(results.map((r) => r.pageNumber))];
193
+ });
194
+ }
195
+ /**
196
+ * Check if a PDF is encrypted
197
+ *
198
+ * @param pdfPath - Path to PDF file
199
+ * @returns True if the PDF is encrypted
200
+ *
201
+ * @example
202
+ * ```typescript
203
+ * if (await isEncrypted('document.pdf')) {
204
+ * console.log('This PDF requires a password');
205
+ * }
206
+ * ```
207
+ */
208
+ export async function isEncrypted(pdfPath) {
209
+ return EasyPDF.open(pdfPath).use((pdf) => pdf.isEncrypted);
210
+ }
211
+ /**
212
+ * Save text extraction to a file
213
+ *
214
+ * @param pdfPath - Path to PDF file
215
+ * @param outputPath - Output text file path
216
+ * @param password - Optional password for encrypted PDFs
217
+ *
218
+ * @example
219
+ * ```typescript
220
+ * await saveTextToFile('document.pdf', 'output.txt');
221
+ * ```
222
+ */
223
+ export async function saveTextToFile(pdfPath, outputPath, password) {
224
+ const text = await extractText(pdfPath, password);
225
+ await fs.writeFile(outputPath, text, 'utf-8');
226
+ }
227
+ /**
228
+ * Convert PDF to images (one per page)
229
+ *
230
+ * @param pdfPath - Path to PDF file
231
+ * @param outputDir - Output directory for images
232
+ * @param options - Rendering options
233
+ * @returns Array of output file paths
234
+ *
235
+ * @example
236
+ * ```typescript
237
+ * const files = await convertToImages('document.pdf', 'output/', {
238
+ * dpi: 300,
239
+ * format: 'png'
240
+ * });
241
+ * console.log(`Created ${files.length} images`);
242
+ * ```
243
+ */
244
+ export async function convertToImages(pdfPath, outputDir, options = {}) {
245
+ const { dpi = 150, format = 'png', password } = options;
246
+ // Ensure output directory exists
247
+ await fs.mkdir(outputDir, { recursive: true });
248
+ return EasyPDF.open(pdfPath, password).useAsync(async (pdf) => {
249
+ const files = [];
250
+ const pageCount = pdf.pageCount;
251
+ for (let i = 0; i < pageCount; i++) {
252
+ const outputPath = `${outputDir}/page-${String(i + 1).padStart(4, '0')}.${format}`;
253
+ await pdf.renderToFile(i, outputPath, { dpi, format });
254
+ files.push(outputPath);
255
+ }
256
+ return files;
257
+ });
258
+ }
259
+ /**
260
+ * Quick info summary for a PDF
261
+ *
262
+ * @param pdfPath - Path to PDF file
263
+ * @param password - Optional password for encrypted PDFs
264
+ * @returns Human-readable summary string
265
+ *
266
+ * @example
267
+ * ```typescript
268
+ * const summary = await quickSummary('document.pdf');
269
+ * console.log(summary);
270
+ * // Output:
271
+ * // Document: document.pdf
272
+ * // Pages: 42
273
+ * // Title: My Document
274
+ * // Author: John Doe
275
+ * // Encrypted: No
276
+ * ```
277
+ */
278
+ export async function quickSummary(pdfPath, password) {
279
+ return EasyPDF.open(pdfPath, password).use((pdf) => {
280
+ const info = pdf.getInfo();
281
+ const lines = [
282
+ `Document: ${pdfPath}`,
283
+ `Pages: ${info.pageCount}`,
284
+ info.metadata.title ? `Title: ${info.metadata.title}` : null,
285
+ info.metadata.author ? `Author: ${info.metadata.author}` : null,
286
+ info.metadata.subject ? `Subject: ${info.metadata.subject}` : null,
287
+ `Encrypted: ${info.isEncrypted ? 'Yes' : 'No'}`,
288
+ `Has XFA: ${info.hasXfa ? 'Yes' : 'No'}`
289
+ ];
290
+ return lines.filter((l) => l !== null).join('\n');
291
+ });
292
+ }
293
+ /**
294
+ * Merge multiple PDF files into a single output file
295
+ *
296
+ * This is the simplest way to merge PDFs - just provide the input paths and output path.
297
+ * Handles large documents (5000+ pages) and corrupted PDFs robustly.
298
+ *
299
+ * @param inputPaths - Array of PDF file paths to merge (in order)
300
+ * @param outputPath - Path where the merged PDF will be saved
301
+ * @returns Promise that resolves to the number of pages in the merged PDF
302
+ * @throws Error if any input file is invalid, not found, or merge fails
303
+ *
304
+ * @example Basic merge
305
+ * ```typescript
306
+ * import { mergePDF } from 'micropdf/simple';
307
+ *
308
+ * const pageCount = await mergePDF(
309
+ * ['document1.pdf', 'document2.pdf', 'document3.pdf'],
310
+ * 'merged.pdf'
311
+ * );
312
+ * console.log(`Merged ${pageCount} pages`);
313
+ * ```
314
+ *
315
+ * @example Large documents
316
+ * ```typescript
317
+ * // Works with large documents (5000+ pages)
318
+ * const pageCount = await mergePDF(
319
+ * ['large_doc1.pdf', 'large_doc2.pdf'],
320
+ * 'combined.pdf'
321
+ * );
322
+ * ```
323
+ *
324
+ * @example Error handling
325
+ * ```typescript
326
+ * try {
327
+ * await mergePDF(['doc1.pdf', 'doc2.pdf'], 'output.pdf');
328
+ * } catch (error) {
329
+ * console.error('Merge failed:', error.message);
330
+ * }
331
+ * ```
332
+ */
333
+ export async function mergePDF(inputPaths, outputPath) {
334
+ const ctx = new Context();
335
+ const enhanced = new Enhanced(ctx);
336
+ try {
337
+ return await enhanced.mergePDF(inputPaths, outputPath);
338
+ }
339
+ finally {
340
+ ctx.free();
341
+ }
342
+ }
343
+ //# sourceMappingURL=simple.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simple.js","sourceRoot":"","sources":["../src/simple.ts"],"names":[],"mappings":"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"}