unpdf 0.12.0 → 0.12.2

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 CHANGED
@@ -38,20 +38,23 @@ yarn add unpdf
38
38
  ### Extract Text From PDF
39
39
 
40
40
  ```ts
41
- import { extractText, getDocumentProxy } from "unpdf";
41
+ import { extractText, getDocumentProxy } from 'unpdf'
42
42
 
43
43
  // Fetch a PDF file from the web
44
44
  const buffer = await fetch(
45
- "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
46
- ).then((res) => res.arrayBuffer());
45
+ 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf',
46
+ ).then(res => res.arrayBuffer())
47
47
 
48
48
  // Or load it from the filesystem
49
- const buffer = await readFile("./dummy.pdf");
49
+ const buffer = await readFile('./dummy.pdf')
50
50
 
51
51
  // Load PDF from buffer
52
- const pdf = await getDocumentProxy(new Uint8Array(buffer));
52
+ const pdf = await getDocumentProxy(new Uint8Array(buffer))
53
53
  // Extract text from PDF
54
- const { totalPages, text } = await extractText(pdf, { mergePages: true });
54
+ const { totalPages, text } = await extractText(pdf, { mergePages: true })
55
+
56
+ console.log(`Total pages: ${totalPages}`)
57
+ console.log(text)
55
58
  ```
56
59
 
57
60
  ### Access the PDF.js API
@@ -65,19 +68,19 @@ This will return the resolved PDF.js module and gives full access to the PDF.js
65
68
  Especially useful for platforms like 🦕 Deno or if you want to use the PDF.js API directly. If no custom build was defined beforehand, the serverless build bundled with `unpdf` will be initialized.
66
69
 
67
70
  ```ts
68
- import { getResolvedPDFJS } from "unpdf";
71
+ import { getResolvedPDFJS } from 'unpdf'
69
72
 
70
- const { getDocument } = await getResolvedPDFJS();
71
- const data = Deno.readFileSync("dummy.pdf");
72
- const doc = await getDocument(data).promise;
73
+ const { getDocument } = await getResolvedPDFJS()
74
+ const data = Deno.readFileSync('dummy.pdf')
75
+ const doc = await getDocument(data).promise
73
76
 
74
- console.log(await doc.getMetadata());
77
+ console.log(await doc.getMetadata())
75
78
 
76
79
  for (let i = 1; i <= doc.numPages; i++) {
77
- const page = await doc.getPage(i);
78
- const textContent = await page.getTextContent();
79
- const contents = textContent.items.map((item) => item.str).join(" ");
80
- console.log(contents);
80
+ const page = await doc.getPage(i)
81
+ const textContent = await page.getTextContent()
82
+ const contents = textContent.items.map(item => item.str).join(' ')
83
+ console.log(contents)
81
84
  }
82
85
  ```
83
86
 
@@ -91,12 +94,12 @@ Generally speaking, you don't need to worry about the PDF.js build. `unpdf` ship
91
94
  ```ts
92
95
  // Before using any other method, define the PDF.js module
93
96
  // if you need another PDF.js build
94
- import { configureUnPDF } from "unpdf";
97
+ import { configureUnPDF } from 'unpdf'
95
98
 
96
99
  await configureUnPDF({
97
100
  // Use the official PDF.js build (make sure to install it first)
98
- pdfjs: () => import("pdfjs-dist"),
99
- });
101
+ pdfjs: () => import('pdfjs-dist'),
102
+ })
100
103
 
101
104
  // Now, you can use the other methods
102
105
  // …
@@ -115,7 +118,7 @@ interface UnPDFConfiguration {
115
118
  * // Use the official PDF.js build (make sure to install it first)
116
119
  * () => import('pdfjs-dist')
117
120
  */
118
- pdfjs?: () => Promise<PDFJS>;
121
+ pdfjs?: () => Promise<PDFJS>
119
122
  }
120
123
  ```
121
124
 
@@ -126,7 +129,7 @@ interface UnPDFConfiguration {
126
129
  Define a custom PDF.js module, like the legacy build. Make sure to call this method before using any other methods.
127
130
 
128
131
  ```ts
129
- function configureUnPDF(config: UnPDFConfiguration): Promise<void>;
132
+ function configureUnPDF(config: UnPDFConfiguration): Promise<void>
130
133
  ```
131
134
 
132
135
  ### `getResolvedPDFJS`
@@ -134,18 +137,18 @@ function configureUnPDF(config: UnPDFConfiguration): Promise<void>;
134
137
  Returns the resolved PDF.js module. If no build is defined, the latest version will be initialized.
135
138
 
136
139
  ```ts
137
- function getResolvedPDFJS(): Promise<PDFJS>;
140
+ function getResolvedPDFJS(): Promise<PDFJS>
138
141
  ```
139
142
 
140
143
  ### `getMeta`
141
144
 
142
145
  ```ts
143
146
  function getMeta(
144
- data: DocumentInitParameters["data"] | PDFDocumentProxy,
147
+ data: DocumentInitParameters['data'] | PDFDocumentProxy,
145
148
  ): Promise<{
146
- info: Record<string, any>;
147
- metadata: Record<string, any>;
148
- }>;
149
+ info: Record<string, any>
150
+ metadata: Record<string, any>
151
+ }>
149
152
  ```
150
153
 
151
154
  ### `extractText`
@@ -154,12 +157,12 @@ Extracts all text from a PDF. If `mergePages` is set to `true`, the text of all
154
157
 
155
158
  ```ts
156
159
  function extractText(
157
- data: DocumentInitParameters["data"] | PDFDocumentProxy,
160
+ data: DocumentInitParameters['data'] | PDFDocumentProxy,
158
161
  { mergePages }?: { mergePages?: boolean },
159
162
  ): Promise<{
160
- totalPages: number;
161
- text: string | string[];
162
- }>;
163
+ totalPages: number
164
+ text: string | string[]
165
+ }>
163
166
  ```
164
167
 
165
168
  ### `renderPageAsImage`
@@ -177,37 +180,37 @@ In order to use this method, you have to meet the following requirements:
177
180
  **Example**
178
181
 
179
182
  ```ts
180
- import { configureUnPDF, renderPageAsImage } from "unpdf";
183
+ import { configureUnPDF, renderPageAsImage } from 'unpdf'
181
184
 
182
185
  await configureUnPDF({
183
186
  // Use the official PDF.js build
184
- pdfjs: () => import("pdfjs-dist"),
185
- });
187
+ pdfjs: () => import('pdfjs-dist'),
188
+ })
186
189
 
187
- const pdf = await readFile("./dummy.pdf");
188
- const buffer = new Uint8Array(pdf);
189
- const pageNumber = 1;
190
+ const pdf = await readFile('./dummy.pdf')
191
+ const buffer = new Uint8Array(pdf)
192
+ const pageNumber = 1
190
193
 
191
194
  const result = await renderPageAsImage(buffer, pageNumber, {
192
- canvas: () => import("canvas"),
193
- });
194
- await writeFile("dummy-page-1.png", Buffer.from(result));
195
+ canvas: () => import('canvas'),
196
+ })
197
+ await writeFile('dummy-page-1.png', result)
195
198
  ```
196
199
 
197
200
  **Type Declaration**
198
201
 
199
202
  ```ts
200
203
  declare function renderPageAsImage(
201
- data: DocumentInitParameters["data"],
204
+ data: DocumentInitParameters['data'],
202
205
  pageNumber: number,
203
206
  options?: {
204
- canvas?: () => Promise<typeof import("canvas")>;
207
+ canvas?: () => Promise<typeof import('canvas')>
205
208
  /** @default 1 */
206
- scale?: number;
207
- width?: number;
208
- height?: number;
209
+ scale?: number
210
+ width?: number
211
+ height?: number
209
212
  },
210
- ): Promise<ArrayBuffer>;
213
+ ): Promise<ArrayBuffer>
211
214
  ```
212
215
 
213
216
  ## FAQ
package/dist/index.cjs CHANGED
@@ -33,19 +33,15 @@ async function resolvePDFJSImports(pdfjsResolver, { force = false } = {}) {
33
33
  return;
34
34
  } catch (error) {
35
35
  console.error(error);
36
- throw new Error(
37
- "Resolving failed. Please check the provided configuration."
38
- );
36
+ throw new Error("Resolving failed. Please check the provided configuration.");
39
37
  }
40
38
  }
41
39
  try {
42
- const { resolvePDFJS } = await Promise.resolve().then(function () { return pdfjs; });
40
+ const { resolvePDFJS } = await import('unpdf/pdfjs');
43
41
  resolvedModule = await resolvePDFJS();
44
42
  } catch (error) {
45
43
  console.error(error);
46
- throw new Error(
47
- "PDF.js is not available. Please add the package as a dependency."
48
- );
44
+ throw new Error("PDF.js is not available. Please add the package as a dependency.");
49
45
  }
50
46
  }
51
47
  function isPDFDocumentProxy(data) {
@@ -56,40 +52,12 @@ async function interopDefault(m) {
56
52
  return resolved.default || resolved;
57
53
  }
58
54
 
59
- async function getMeta$1(data) {
60
- const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
61
- const meta = await pdf.getMetadata();
62
- return {
63
- info: meta?.info ?? {},
64
- metadata: meta?.metadata?.getAll() ?? {}
65
- };
66
- }
67
-
68
- async function extractText$1(data, options = {}) {
69
- const { mergePages = false } = { ...options };
70
- const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
71
- const texts = await Promise.all(
72
- Array.from({ length: pdf.numPages }, (_, i) => getPageText(pdf, i + 1))
73
- );
74
- return {
75
- totalPages: pdf.numPages,
76
- text: mergePages ? texts.join("\n").replace(/\s+/g, " ") : texts
77
- };
78
- }
79
- async function getPageText(document, pageNumber) {
80
- const page = await document.getPage(pageNumber);
81
- const content = await page.getTextContent();
82
- return content.items.filter((item) => item.str != null).map((item) => item.str + (item.hasEOL ? "\n" : "")).join("");
83
- }
84
-
85
55
  async function extractImages$1(data, pageNumber) {
86
56
  const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
87
- const page = await pdf.getPage(pageNumber);
88
57
  if (pageNumber < 1 || pageNumber > pdf.numPages) {
89
- throw new Error(
90
- `Invalid page number. Must be between 1 and ${pdf.numPages}.`
91
- );
58
+ throw new Error(`Invalid page number. Must be between 1 and ${pdf.numPages}.`);
92
59
  }
60
+ const page = await pdf.getPage(pageNumber);
93
61
  const operatorList = await page.getOperatorList();
94
62
  const { OPS } = await getResolvedPDFJS();
95
63
  const images = [];
@@ -100,7 +68,22 @@ async function extractImages$1(data, pageNumber) {
100
68
  }
101
69
  const imageKey = operatorList.argsArray[i][0];
102
70
  const image = await page.objs.get(imageKey);
103
- images.push(image.data);
71
+ if (!image || !image.data || !image.width || !image.height) {
72
+ continue;
73
+ }
74
+ const { width, height, data: data2 } = image;
75
+ const calculatedChannels = data2.length / (width * height);
76
+ if (![1, 3, 4].includes(calculatedChannels)) {
77
+ continue;
78
+ }
79
+ const channels = calculatedChannels;
80
+ images.push({
81
+ data: data2,
82
+ width,
83
+ height,
84
+ channels,
85
+ key: imageKey
86
+ });
104
87
  }
105
88
  return images;
106
89
  }
@@ -109,9 +92,7 @@ async function renderPageAsImage$1(data, pageNumber, options = {}) {
109
92
  const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data, { canvasFactory });
110
93
  const page = await pdf.getPage(pageNumber);
111
94
  if (pageNumber < 1 || pageNumber > pdf.numPages) {
112
- throw new Error(
113
- `Invalid page number. Must be between 1 and ${pdf.numPages}.`
114
- );
95
+ throw new Error(`Invalid page number. Must be between 1 and ${pdf.numPages}.`);
115
96
  }
116
97
  let outputScale = options.scale || 1;
117
98
  let viewport = page.getViewport({ scale: outputScale });
@@ -177,6 +158,32 @@ async function createIsomorphicCanvasFactory(canvas) {
177
158
  };
178
159
  }
179
160
 
161
+ async function getMeta$1(data) {
162
+ const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
163
+ const meta = await pdf.getMetadata();
164
+ return {
165
+ info: meta?.info ?? {},
166
+ metadata: meta?.metadata?.getAll() ?? {}
167
+ };
168
+ }
169
+
170
+ async function extractText$1(data, options = {}) {
171
+ const { mergePages = false } = { ...options };
172
+ const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
173
+ const texts = await Promise.all(
174
+ Array.from({ length: pdf.numPages }, (_, i) => getPageText(pdf, i + 1))
175
+ );
176
+ return {
177
+ totalPages: pdf.numPages,
178
+ text: mergePages ? texts.join("\n").replace(/\s+/g, " ") : texts
179
+ };
180
+ }
181
+ async function getPageText(document, pageNumber) {
182
+ const page = await document.getPage(pageNumber);
183
+ const content = await page.getTextContent();
184
+ return content.items.filter((item) => item.str != null).map((item) => item.str + (item.hasEOL ? "\n" : "")).join("");
185
+ }
186
+
180
187
  async function configureUnPDF(options) {
181
188
  const { pdfjs } = { ...options };
182
189
  if (pdfjs) {
@@ -201,10 +208,6 @@ const renderPageAsImage = async (...args) => {
201
208
  return await renderPageAsImage$1(...args);
202
209
  };
203
210
 
204
- const pdfjs = {
205
- __proto__: null
206
- };
207
-
208
211
  exports.configureUnPDF = configureUnPDF;
209
212
  exports.createIsomorphicCanvasFactory = createIsomorphicCanvasFactory;
210
213
  exports.extractImages = extractImages;
package/dist/index.d.cts CHANGED
@@ -1,28 +1,37 @@
1
- import { DocumentInitParameters, PDFDocumentProxy } from './types/src/display/api';
2
1
  import * as canvas from 'canvas';
3
2
  import { Canvas } from 'canvas';
3
+ import { DocumentInitParameters, PDFDocumentProxy } from './types/src/display/api';
4
4
  import * as _PDFJS from './types/src/pdf';
5
5
 
6
- declare function getMeta$1(data: DocumentInitParameters["data"] | PDFDocumentProxy): Promise<{
7
- info: Record<string, any>;
8
- metadata: Record<string, any>;
9
- }>;
10
-
11
- declare function extractText$1(data: DocumentInitParameters["data"] | PDFDocumentProxy, options?: {
12
- mergePages?: false;
13
- }): Promise<{
14
- totalPages: number;
15
- text: string[];
16
- }>;
17
- declare function extractText$1(data: DocumentInitParameters["data"] | PDFDocumentProxy, options: {
18
- mergePages: true;
19
- }): Promise<{
20
- totalPages: number;
21
- text: string;
22
- }>;
23
-
24
- declare function extractImages$1(data: DocumentInitParameters["data"] | PDFDocumentProxy, pageNumber: number): Promise<Uint8ClampedArray[]>;
25
- declare function renderPageAsImage$1(data: DocumentInitParameters["data"] | PDFDocumentProxy, pageNumber: number, options?: {
6
+ interface ExtractedImageObject {
7
+ data: Uint8ClampedArray;
8
+ width: number;
9
+ height: number;
10
+ channels: 1 | 3 | 4;
11
+ key: string;
12
+ }
13
+ /**
14
+ * Extracts images from a specific page of a PDF document, including necessary metadata,
15
+ * such as width, height, and calculated color channels.
16
+ *
17
+ * This version calculates channels based on image data length, width, and height,
18
+ * as the `kind` property provided by PDF.js might not reliably indicate the actual
19
+ * channel count of the raw pixel data (e.g., returning RGBA data even when kind is 3).
20
+ *
21
+ * @example
22
+ * const imagesData = await extractImages(pdf, pageNum)
23
+ *
24
+ * for (const imgData of imagesData) {
25
+ * const imageIndex = totalImagesProcessed + 1;
26
+ * await sharp(imgData.data, {
27
+ * raw: { width: imgData.width, height: imgData.height, channels: imgData.channels }
28
+ * })
29
+ * .png()
30
+ * .toFile(`${imageIndex}.png`);
31
+ * }
32
+ */
33
+ declare function extractImages$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, pageNumber: number): Promise<ExtractedImageObject[]>;
34
+ declare function renderPageAsImage$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, pageNumber: number, options?: {
26
35
  canvas?: () => Promise<typeof canvas>;
27
36
  /** @default 1 */
28
37
  scale?: number;
@@ -45,6 +54,24 @@ declare function createIsomorphicCanvasFactory(canvas?: () => Promise<typeof can
45
54
  }): void;
46
55
  }>;
47
56
 
57
+ declare function getMeta$1(data: DocumentInitParameters['data'] | PDFDocumentProxy): Promise<{
58
+ info: Record<string, any>;
59
+ metadata: Record<string, any>;
60
+ }>;
61
+
62
+ declare function extractText$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, options?: {
63
+ mergePages?: false;
64
+ }): Promise<{
65
+ totalPages: number;
66
+ text: string[];
67
+ }>;
68
+ declare function extractText$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, options: {
69
+ mergePages: true;
70
+ }): Promise<{
71
+ totalPages: number;
72
+ text: string;
73
+ }>;
74
+
48
75
  type PDFJS = typeof _PDFJS;
49
76
  interface UnPDFConfiguration {
50
77
  /**
@@ -59,6 +86,8 @@ interface UnPDFConfiguration {
59
86
  pdfjs?: () => Promise<any>;
60
87
  }
61
88
 
89
+ declare function configureUnPDF(options: UnPDFConfiguration): Promise<void>;
90
+
62
91
  /**
63
92
  * Returns a PDFDocumentProxy instance from a given binary data.
64
93
  *
@@ -66,14 +95,12 @@ interface UnPDFConfiguration {
66
95
  * - `isEvalSupported: false`
67
96
  * - `useSystemFonts: true`
68
97
  */
69
- declare function getDocumentProxy(data: DocumentInitParameters["data"], options?: DocumentInitParameters): Promise<PDFDocumentProxy>;
98
+ declare function getDocumentProxy(data: DocumentInitParameters['data'], options?: DocumentInitParameters): Promise<PDFDocumentProxy>;
70
99
  declare function getResolvedPDFJS(): Promise<PDFJS>;
71
100
  declare function resolvePDFJSImports(pdfjsResolver?: () => Promise<any>, { force }?: {
72
101
  force?: boolean | undefined;
73
102
  }): Promise<void>;
74
103
 
75
- declare function configureUnPDF(options: UnPDFConfiguration): Promise<void>;
76
-
77
104
  declare const getMeta: typeof getMeta$1;
78
105
  declare const extractText: typeof extractText$1;
79
106
  declare const extractImages: typeof extractImages$1;
package/dist/index.d.mts CHANGED
@@ -1,28 +1,37 @@
1
- import { DocumentInitParameters, PDFDocumentProxy } from './types/src/display/api';
2
1
  import * as canvas from 'canvas';
3
2
  import { Canvas } from 'canvas';
3
+ import { DocumentInitParameters, PDFDocumentProxy } from './types/src/display/api';
4
4
  import * as _PDFJS from './types/src/pdf';
5
5
 
6
- declare function getMeta$1(data: DocumentInitParameters["data"] | PDFDocumentProxy): Promise<{
7
- info: Record<string, any>;
8
- metadata: Record<string, any>;
9
- }>;
10
-
11
- declare function extractText$1(data: DocumentInitParameters["data"] | PDFDocumentProxy, options?: {
12
- mergePages?: false;
13
- }): Promise<{
14
- totalPages: number;
15
- text: string[];
16
- }>;
17
- declare function extractText$1(data: DocumentInitParameters["data"] | PDFDocumentProxy, options: {
18
- mergePages: true;
19
- }): Promise<{
20
- totalPages: number;
21
- text: string;
22
- }>;
23
-
24
- declare function extractImages$1(data: DocumentInitParameters["data"] | PDFDocumentProxy, pageNumber: number): Promise<Uint8ClampedArray[]>;
25
- declare function renderPageAsImage$1(data: DocumentInitParameters["data"] | PDFDocumentProxy, pageNumber: number, options?: {
6
+ interface ExtractedImageObject {
7
+ data: Uint8ClampedArray;
8
+ width: number;
9
+ height: number;
10
+ channels: 1 | 3 | 4;
11
+ key: string;
12
+ }
13
+ /**
14
+ * Extracts images from a specific page of a PDF document, including necessary metadata,
15
+ * such as width, height, and calculated color channels.
16
+ *
17
+ * This version calculates channels based on image data length, width, and height,
18
+ * as the `kind` property provided by PDF.js might not reliably indicate the actual
19
+ * channel count of the raw pixel data (e.g., returning RGBA data even when kind is 3).
20
+ *
21
+ * @example
22
+ * const imagesData = await extractImages(pdf, pageNum)
23
+ *
24
+ * for (const imgData of imagesData) {
25
+ * const imageIndex = totalImagesProcessed + 1;
26
+ * await sharp(imgData.data, {
27
+ * raw: { width: imgData.width, height: imgData.height, channels: imgData.channels }
28
+ * })
29
+ * .png()
30
+ * .toFile(`${imageIndex}.png`);
31
+ * }
32
+ */
33
+ declare function extractImages$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, pageNumber: number): Promise<ExtractedImageObject[]>;
34
+ declare function renderPageAsImage$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, pageNumber: number, options?: {
26
35
  canvas?: () => Promise<typeof canvas>;
27
36
  /** @default 1 */
28
37
  scale?: number;
@@ -45,6 +54,24 @@ declare function createIsomorphicCanvasFactory(canvas?: () => Promise<typeof can
45
54
  }): void;
46
55
  }>;
47
56
 
57
+ declare function getMeta$1(data: DocumentInitParameters['data'] | PDFDocumentProxy): Promise<{
58
+ info: Record<string, any>;
59
+ metadata: Record<string, any>;
60
+ }>;
61
+
62
+ declare function extractText$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, options?: {
63
+ mergePages?: false;
64
+ }): Promise<{
65
+ totalPages: number;
66
+ text: string[];
67
+ }>;
68
+ declare function extractText$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, options: {
69
+ mergePages: true;
70
+ }): Promise<{
71
+ totalPages: number;
72
+ text: string;
73
+ }>;
74
+
48
75
  type PDFJS = typeof _PDFJS;
49
76
  interface UnPDFConfiguration {
50
77
  /**
@@ -59,6 +86,8 @@ interface UnPDFConfiguration {
59
86
  pdfjs?: () => Promise<any>;
60
87
  }
61
88
 
89
+ declare function configureUnPDF(options: UnPDFConfiguration): Promise<void>;
90
+
62
91
  /**
63
92
  * Returns a PDFDocumentProxy instance from a given binary data.
64
93
  *
@@ -66,14 +95,12 @@ interface UnPDFConfiguration {
66
95
  * - `isEvalSupported: false`
67
96
  * - `useSystemFonts: true`
68
97
  */
69
- declare function getDocumentProxy(data: DocumentInitParameters["data"], options?: DocumentInitParameters): Promise<PDFDocumentProxy>;
98
+ declare function getDocumentProxy(data: DocumentInitParameters['data'], options?: DocumentInitParameters): Promise<PDFDocumentProxy>;
70
99
  declare function getResolvedPDFJS(): Promise<PDFJS>;
71
100
  declare function resolvePDFJSImports(pdfjsResolver?: () => Promise<any>, { force }?: {
72
101
  force?: boolean | undefined;
73
102
  }): Promise<void>;
74
103
 
75
- declare function configureUnPDF(options: UnPDFConfiguration): Promise<void>;
76
-
77
104
  declare const getMeta: typeof getMeta$1;
78
105
  declare const extractText: typeof extractText$1;
79
106
  declare const extractImages: typeof extractImages$1;
package/dist/index.d.ts CHANGED
@@ -1,28 +1,37 @@
1
- import { DocumentInitParameters, PDFDocumentProxy } from './types/src/display/api';
2
1
  import * as canvas from 'canvas';
3
2
  import { Canvas } from 'canvas';
3
+ import { DocumentInitParameters, PDFDocumentProxy } from './types/src/display/api';
4
4
  import * as _PDFJS from './types/src/pdf';
5
5
 
6
- declare function getMeta$1(data: DocumentInitParameters["data"] | PDFDocumentProxy): Promise<{
7
- info: Record<string, any>;
8
- metadata: Record<string, any>;
9
- }>;
10
-
11
- declare function extractText$1(data: DocumentInitParameters["data"] | PDFDocumentProxy, options?: {
12
- mergePages?: false;
13
- }): Promise<{
14
- totalPages: number;
15
- text: string[];
16
- }>;
17
- declare function extractText$1(data: DocumentInitParameters["data"] | PDFDocumentProxy, options: {
18
- mergePages: true;
19
- }): Promise<{
20
- totalPages: number;
21
- text: string;
22
- }>;
23
-
24
- declare function extractImages$1(data: DocumentInitParameters["data"] | PDFDocumentProxy, pageNumber: number): Promise<Uint8ClampedArray[]>;
25
- declare function renderPageAsImage$1(data: DocumentInitParameters["data"] | PDFDocumentProxy, pageNumber: number, options?: {
6
+ interface ExtractedImageObject {
7
+ data: Uint8ClampedArray;
8
+ width: number;
9
+ height: number;
10
+ channels: 1 | 3 | 4;
11
+ key: string;
12
+ }
13
+ /**
14
+ * Extracts images from a specific page of a PDF document, including necessary metadata,
15
+ * such as width, height, and calculated color channels.
16
+ *
17
+ * This version calculates channels based on image data length, width, and height,
18
+ * as the `kind` property provided by PDF.js might not reliably indicate the actual
19
+ * channel count of the raw pixel data (e.g., returning RGBA data even when kind is 3).
20
+ *
21
+ * @example
22
+ * const imagesData = await extractImages(pdf, pageNum)
23
+ *
24
+ * for (const imgData of imagesData) {
25
+ * const imageIndex = totalImagesProcessed + 1;
26
+ * await sharp(imgData.data, {
27
+ * raw: { width: imgData.width, height: imgData.height, channels: imgData.channels }
28
+ * })
29
+ * .png()
30
+ * .toFile(`${imageIndex}.png`);
31
+ * }
32
+ */
33
+ declare function extractImages$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, pageNumber: number): Promise<ExtractedImageObject[]>;
34
+ declare function renderPageAsImage$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, pageNumber: number, options?: {
26
35
  canvas?: () => Promise<typeof canvas>;
27
36
  /** @default 1 */
28
37
  scale?: number;
@@ -45,6 +54,24 @@ declare function createIsomorphicCanvasFactory(canvas?: () => Promise<typeof can
45
54
  }): void;
46
55
  }>;
47
56
 
57
+ declare function getMeta$1(data: DocumentInitParameters['data'] | PDFDocumentProxy): Promise<{
58
+ info: Record<string, any>;
59
+ metadata: Record<string, any>;
60
+ }>;
61
+
62
+ declare function extractText$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, options?: {
63
+ mergePages?: false;
64
+ }): Promise<{
65
+ totalPages: number;
66
+ text: string[];
67
+ }>;
68
+ declare function extractText$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, options: {
69
+ mergePages: true;
70
+ }): Promise<{
71
+ totalPages: number;
72
+ text: string;
73
+ }>;
74
+
48
75
  type PDFJS = typeof _PDFJS;
49
76
  interface UnPDFConfiguration {
50
77
  /**
@@ -59,6 +86,8 @@ interface UnPDFConfiguration {
59
86
  pdfjs?: () => Promise<any>;
60
87
  }
61
88
 
89
+ declare function configureUnPDF(options: UnPDFConfiguration): Promise<void>;
90
+
62
91
  /**
63
92
  * Returns a PDFDocumentProxy instance from a given binary data.
64
93
  *
@@ -66,14 +95,12 @@ interface UnPDFConfiguration {
66
95
  * - `isEvalSupported: false`
67
96
  * - `useSystemFonts: true`
68
97
  */
69
- declare function getDocumentProxy(data: DocumentInitParameters["data"], options?: DocumentInitParameters): Promise<PDFDocumentProxy>;
98
+ declare function getDocumentProxy(data: DocumentInitParameters['data'], options?: DocumentInitParameters): Promise<PDFDocumentProxy>;
70
99
  declare function getResolvedPDFJS(): Promise<PDFJS>;
71
100
  declare function resolvePDFJSImports(pdfjsResolver?: () => Promise<any>, { force }?: {
72
101
  force?: boolean | undefined;
73
102
  }): Promise<void>;
74
103
 
75
- declare function configureUnPDF(options: UnPDFConfiguration): Promise<void>;
76
-
77
104
  declare const getMeta: typeof getMeta$1;
78
105
  declare const extractText: typeof extractText$1;
79
106
  declare const extractImages: typeof extractImages$1;
package/dist/index.mjs CHANGED
@@ -31,19 +31,15 @@ async function resolvePDFJSImports(pdfjsResolver, { force = false } = {}) {
31
31
  return;
32
32
  } catch (error) {
33
33
  console.error(error);
34
- throw new Error(
35
- "Resolving failed. Please check the provided configuration."
36
- );
34
+ throw new Error("Resolving failed. Please check the provided configuration.");
37
35
  }
38
36
  }
39
37
  try {
40
- const { resolvePDFJS } = await Promise.resolve().then(function () { return pdfjs; });
38
+ const { resolvePDFJS } = await import('unpdf/pdfjs');
41
39
  resolvedModule = await resolvePDFJS();
42
40
  } catch (error) {
43
41
  console.error(error);
44
- throw new Error(
45
- "PDF.js is not available. Please add the package as a dependency."
46
- );
42
+ throw new Error("PDF.js is not available. Please add the package as a dependency.");
47
43
  }
48
44
  }
49
45
  function isPDFDocumentProxy(data) {
@@ -54,40 +50,12 @@ async function interopDefault(m) {
54
50
  return resolved.default || resolved;
55
51
  }
56
52
 
57
- async function getMeta$1(data) {
58
- const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
59
- const meta = await pdf.getMetadata();
60
- return {
61
- info: meta?.info ?? {},
62
- metadata: meta?.metadata?.getAll() ?? {}
63
- };
64
- }
65
-
66
- async function extractText$1(data, options = {}) {
67
- const { mergePages = false } = { ...options };
68
- const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
69
- const texts = await Promise.all(
70
- Array.from({ length: pdf.numPages }, (_, i) => getPageText(pdf, i + 1))
71
- );
72
- return {
73
- totalPages: pdf.numPages,
74
- text: mergePages ? texts.join("\n").replace(/\s+/g, " ") : texts
75
- };
76
- }
77
- async function getPageText(document, pageNumber) {
78
- const page = await document.getPage(pageNumber);
79
- const content = await page.getTextContent();
80
- return content.items.filter((item) => item.str != null).map((item) => item.str + (item.hasEOL ? "\n" : "")).join("");
81
- }
82
-
83
53
  async function extractImages$1(data, pageNumber) {
84
54
  const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
85
- const page = await pdf.getPage(pageNumber);
86
55
  if (pageNumber < 1 || pageNumber > pdf.numPages) {
87
- throw new Error(
88
- `Invalid page number. Must be between 1 and ${pdf.numPages}.`
89
- );
56
+ throw new Error(`Invalid page number. Must be between 1 and ${pdf.numPages}.`);
90
57
  }
58
+ const page = await pdf.getPage(pageNumber);
91
59
  const operatorList = await page.getOperatorList();
92
60
  const { OPS } = await getResolvedPDFJS();
93
61
  const images = [];
@@ -98,7 +66,22 @@ async function extractImages$1(data, pageNumber) {
98
66
  }
99
67
  const imageKey = operatorList.argsArray[i][0];
100
68
  const image = await page.objs.get(imageKey);
101
- images.push(image.data);
69
+ if (!image || !image.data || !image.width || !image.height) {
70
+ continue;
71
+ }
72
+ const { width, height, data: data2 } = image;
73
+ const calculatedChannels = data2.length / (width * height);
74
+ if (![1, 3, 4].includes(calculatedChannels)) {
75
+ continue;
76
+ }
77
+ const channels = calculatedChannels;
78
+ images.push({
79
+ data: data2,
80
+ width,
81
+ height,
82
+ channels,
83
+ key: imageKey
84
+ });
102
85
  }
103
86
  return images;
104
87
  }
@@ -107,9 +90,7 @@ async function renderPageAsImage$1(data, pageNumber, options = {}) {
107
90
  const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data, { canvasFactory });
108
91
  const page = await pdf.getPage(pageNumber);
109
92
  if (pageNumber < 1 || pageNumber > pdf.numPages) {
110
- throw new Error(
111
- `Invalid page number. Must be between 1 and ${pdf.numPages}.`
112
- );
93
+ throw new Error(`Invalid page number. Must be between 1 and ${pdf.numPages}.`);
113
94
  }
114
95
  let outputScale = options.scale || 1;
115
96
  let viewport = page.getViewport({ scale: outputScale });
@@ -175,6 +156,32 @@ async function createIsomorphicCanvasFactory(canvas) {
175
156
  };
176
157
  }
177
158
 
159
+ async function getMeta$1(data) {
160
+ const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
161
+ const meta = await pdf.getMetadata();
162
+ return {
163
+ info: meta?.info ?? {},
164
+ metadata: meta?.metadata?.getAll() ?? {}
165
+ };
166
+ }
167
+
168
+ async function extractText$1(data, options = {}) {
169
+ const { mergePages = false } = { ...options };
170
+ const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
171
+ const texts = await Promise.all(
172
+ Array.from({ length: pdf.numPages }, (_, i) => getPageText(pdf, i + 1))
173
+ );
174
+ return {
175
+ totalPages: pdf.numPages,
176
+ text: mergePages ? texts.join("\n").replace(/\s+/g, " ") : texts
177
+ };
178
+ }
179
+ async function getPageText(document, pageNumber) {
180
+ const page = await document.getPage(pageNumber);
181
+ const content = await page.getTextContent();
182
+ return content.items.filter((item) => item.str != null).map((item) => item.str + (item.hasEOL ? "\n" : "")).join("");
183
+ }
184
+
178
185
  async function configureUnPDF(options) {
179
186
  const { pdfjs } = { ...options };
180
187
  if (pdfjs) {
@@ -199,8 +206,4 @@ const renderPageAsImage = async (...args) => {
199
206
  return await renderPageAsImage$1(...args);
200
207
  };
201
208
 
202
- const pdfjs = {
203
- __proto__: null
204
- };
205
-
206
209
  export { configureUnPDF, createIsomorphicCanvasFactory, extractImages, extractText, getDocumentProxy, getMeta, getResolvedPDFJS, renderPageAsImage, resolvePDFJSImports };
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "unpdf",
3
3
  "type": "module",
4
- "version": "0.12.0",
5
- "packageManager": "pnpm@9.11.0",
4
+ "version": "0.12.2",
5
+ "packageManager": "pnpm@9.12.1",
6
6
  "description": "Utilities to work with PDFs in Node.js, browser and workers",
7
7
  "author": "Johann Schopplich <hello@johannschopplich.com>",
8
8
  "license": "MIT",
@@ -56,9 +56,7 @@
56
56
  "build:pdfjs": "rollup --config pdfjs.rollup.config.ts --configPlugin typescript && cp -R node_modules/pdfjs-dist/types dist",
57
57
  "dev": "unbuild --stub",
58
58
  "lint": "eslint .",
59
- "lint:fix": "npm run lint -- --fix",
60
- "format": "prettier \"**/*.{json,md,cjs,mjs,ts,yml}\" --write",
61
- "format:check": "prettier \"**/*.{json,md,cjs,mjs,ts,yml}\" --check",
59
+ "lint:fix": "eslint . --fix",
62
60
  "release": "bumpp",
63
61
  "test": "vitest",
64
62
  "test:types": "tsc --noEmit"
@@ -67,6 +65,7 @@
67
65
  "canvas": "^2.11.2"
68
66
  },
69
67
  "devDependencies": {
68
+ "@antfu/eslint-config": "^3.7.3",
70
69
  "@rollup/plugin-alias": "^5.1.1",
71
70
  "@rollup/plugin-commonjs": "^28.0.0",
72
71
  "@rollup/plugin-inject": "^5.0.5",
@@ -74,19 +73,17 @@
74
73
  "@rollup/plugin-replace": "^6.0.1",
75
74
  "@rollup/plugin-terser": "^0.4.4",
76
75
  "@rollup/plugin-typescript": "^12.1.0",
77
- "@types/node": "^20.16.10",
76
+ "@types/node": "^20.16.11",
78
77
  "bumpp": "^9.6.1",
79
- "eslint": "^9.11.1",
80
- "eslint-config-unjs": "^0.4.1",
78
+ "eslint": "^9.12.0",
81
79
  "fast-glob": "^3.3.2",
82
- "pdfjs-dist": "^4.6.82",
83
- "prettier": "^3.3.3",
84
- "rollup": "^4.22.5",
80
+ "pdfjs-dist": "~4.6.82",
81
+ "rollup": "^4.24.0",
85
82
  "tslib": "^2.7.0",
86
83
  "typescript": "^5.5.4",
87
- "unbuild": "^3.0.0-rc.8",
84
+ "unbuild": "^3.0.0-rc.11",
88
85
  "unenv": "^1.10.0",
89
- "vitest": "^2.1.1"
86
+ "vitest": "^2.1.2"
90
87
  },
91
88
  "pnpm": {
92
89
  "patchedDependencies": {