Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev tools #195

Merged
merged 2 commits into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx lint-staged
7 changes: 7 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"trailingComma": "all",
"tabWidth": 2,
"semi": true,
"printWidth": 120,
"singleQuote": true
}
11 changes: 9 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@
"@typescript-eslint/parser": "^6.2.1",
"chai": "^4.3.7",
"eslint": "^8.46.0",
"husky": "^8.0.3",
"lint-staged": "^15.2.0",
"mocha": "^10.2.0",
"nyc": "^15.1.0",
"prettier": "^3.1.1",
"rimraf": "^5.0.1",
"rollup": "^3.27.2",
"ts-node": "^10.9.1",
Expand All @@ -37,7 +40,8 @@
"rollup": "rollup -c",
"clean": "rimraf ./dist",
"lint": "eslint --ext .ts .",
"build": "npm run test && npm run clean && npm run rollup"
"build": "npm run test && npm run clean && npm run rollup",
"prepare": "husky install"
},
"engines": {
"node": ">=14"
Expand Down Expand Up @@ -72,5 +76,8 @@
"bugs": {
"url": "https://github.com/yakovmeister/pdf2image/issues"
},
"homepage": "https://github.com/yakovmeister/pdf2image#readme"
"homepage": "https://github.com/yakovmeister/pdf2image#readme",
"lint-staged": {
"*.{js,ts}": ["prettier --write", "eslint --fix"]
}
}
73 changes: 36 additions & 37 deletions src/graphics.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import gm from "gm";
import path from "path";
import fs from "fs";
import gm from 'gm';
import path from 'path';
import fs from 'fs';
import { BufferResponse, ToBase64Response, WriteImageResponse } from './types/convertResponse';
import { Options } from "./types/options";
import { Options } from './types/options';

export class Graphics {
private quality = 0;

private format = "png";
private format = 'png';

private width = 768;

Expand All @@ -17,21 +17,21 @@ export class Graphics {

private density = 72;

private savePath = "./";
private savePath = './';

private saveFilename = "untitled";
private saveFilename = 'untitled';

private compression = "jpeg";
private compression = 'jpeg';

private gm: gm.SubClass = gm.subClass({ imageMagick: false });

public generateValidFilename(page?: number): string {
let filePath = path.join(this.savePath, this.saveFilename);
if (this.savePath.startsWith('./')) {
filePath = `./${filePath}`
filePath = `./${filePath}`;
}

if (typeof page === "number") {
if (typeof page === 'number') {
filePath = `${filePath}.${page + 1}`;
}

Expand All @@ -43,13 +43,13 @@ export class Graphics {
.density(this.density, this.density)
.resize(this.width, this.height, this.preserveAspectRatio ? '^' : '!')
.quality(this.quality)
.compress(this.compression)
.compress(this.compression);
}

public async toBase64(stream: fs.ReadStream, page?: number): Promise<ToBase64Response> {
const { buffer, size, page: pageResponse } = await this.toBuffer(stream, page);

return { base64: buffer.toString("base64"), size, page: pageResponse }
return { base64: buffer.toString('base64'), size, page: pageResponse };
}

public toBuffer(stream: fs.ReadStream, page?: number): Promise<BufferResponse> {
Expand All @@ -67,11 +67,11 @@ export class Graphics {
.on('data', (data) => {
buffers.push(data);
})
.on("end", () => {
.on('end', () => {
return resolve({
buffer: Buffer.concat(buffers),
size: `${this.width}x${this.height}`,
page: page + 1
page: page + 1,
});
});
});
Expand All @@ -83,20 +83,19 @@ export class Graphics {
const pageSetup = `${stream.path}[${page}]`;

return new Promise((resolve, reject) => {
this.gmBaseCommand(stream, pageSetup)
.write(output, (error) => {
if (error) {
return reject(error);
}
this.gmBaseCommand(stream, pageSetup).write(output, (error) => {
if (error) {
return reject(error);
}

return resolve({
name: path.basename(output),
size: `${this.width}x${this.height}`,
fileSize: fs.statSync(output).size / 1000.0,
path: output,
page: page + 1
});
return resolve({
name: path.basename(output),
size: `${this.width}x${this.height}`,
fileSize: fs.statSync(output).size / 1000.0,
path: output,
page: page + 1,
});
});
});
}

Expand All @@ -110,7 +109,7 @@ export class Graphics {
return reject(error);
}

return resolve(data.replace(/^[\w\W]*?1/, "1"));
return resolve(data.replace(/^[\w\W]*?1/, '1'));
});
} else {
image.identify((error, data) => {
Expand All @@ -119,7 +118,7 @@ export class Graphics {
}

return resolve(data);
})
});
}
});
}
Expand Down Expand Up @@ -174,13 +173,13 @@ export class Graphics {
}

public setGMClass(gmClass: string | boolean): Graphics {
if (typeof gmClass === "boolean") {
if (typeof gmClass === 'boolean') {
this.gm = gm.subClass({ imageMagick: gmClass });

return this;
}

if (gmClass.toLocaleLowerCase() === "imagemagick") {
if (gmClass.toLocaleLowerCase() === 'imagemagick') {
this.gm = gm.subClass({ imageMagick: true });

return this;
Expand All @@ -193,15 +192,15 @@ export class Graphics {

public getOptions(): Options {
return {
quality: this.quality,
format: this.format,
width: this.width,
height: this.height,
quality: this.quality,
format: this.format,
width: this.width,
height: this.height,
preserveAspectRatio: this.preserveAspectRatio,
density: this.density,
savePath: this.savePath,
density: this.density,
savePath: this.savePath,
saveFilename: this.saveFilename,
compression: this.compression
compression: this.compression,
};
}
}
12 changes: 6 additions & 6 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { Convert } from "./types/convert";
import { defaultOptions } from "./utils/defaultOptions";
import { pdf2picCore } from "./pdf2picCore";
import { Convert } from './types/convert';
import { defaultOptions } from './utils/defaultOptions';
import { pdf2picCore } from './pdf2picCore';

export function fromPath(filePath: string, options = defaultOptions): Convert {
return pdf2picCore("path", filePath, options);
return pdf2picCore('path', filePath, options);
}

export function fromBuffer(buffer: Buffer, options = defaultOptions): Convert {
return pdf2picCore("buffer", buffer, options);
return pdf2picCore('buffer', buffer, options);
}

export function fromBase64(b64string: string, options = defaultOptions): Convert {
return pdf2picCore("base64", b64string, options);
return pdf2picCore('base64', b64string, options);
}
47 changes: 23 additions & 24 deletions src/pdf2picCore.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import fs from 'fs';
import { Graphics } from "./graphics";
import type { Convert, ConvertOptions } from "./types/convert";
import { Graphics } from './graphics';
import type { Convert, ConvertOptions } from './types/convert';
import type { ConvertResponse } from './types/convertResponse';
import type { Options } from "./types/options";
import type { Options } from './types/options';
import { bufferToStream } from './utils/converters/bufferToStream';
import { convertToBuffer } from "./utils/converters/convertToBuffer";
import { convertToBuffer } from './utils/converters/convertToBuffer';
import { convertToStream } from './utils/converters/convertToStream';
import { defaultOptions } from "./utils/defaultOptions";
import { defaultOptions } from './utils/defaultOptions';
import { getPages } from './utils/getPages';
import { resolveResponseType } from './utils/resolveResponseType';

Expand All @@ -17,45 +17,44 @@ export function pdf2picCore(source: string, data: string | Buffer, options = def

const _convert = (stream: fs.ReadStream, page: number, convertOptions: ConvertOptions): Promise<ConvertResponse> => {
if (page < 1) {
throw new Error("Page number should be more than or equal 1");
throw new Error('Page number should be more than or equal 1');
}

const responseType = resolveResponseType(convertOptions)
const responseType = resolveResponseType(convertOptions);
switch (responseType) {
case 'base64':
return gm.toBase64(stream, (page - 1))
return gm.toBase64(stream, page - 1);
case 'image':
return gm.writeImage(stream, (page - 1))
return gm.writeImage(stream, page - 1);
case 'buffer':
return gm.toBuffer(stream, (page - 1))
return gm.toBuffer(stream, page - 1);
default:
throw new Error(`Invalid responseType: ${responseType}`)
throw new Error(`Invalid responseType: ${responseType}`);
}
}
};

const _bulk = (stream, pages, convertOptions) => {
return Promise.all(pages.map(page => _convert(stream, page, convertOptions)));
}
return Promise.all(pages.map((page) => _convert(stream, page, convertOptions)));
};

const convert = (page = 1, convertOptions) => {
const stream = convertToStream(source, data);
return _convert(stream, page, convertOptions)
return _convert(stream, page, convertOptions);
};

convert.bulk = async (pages, convertOptions) => {
const buffer = await convertToBuffer(source, data);
const pagesToConvert = pages === -1
? await getPages(gm, bufferToStream(buffer))
: Array.isArray(pages) ? pages : [pages];
const pagesToConvert =
pages === -1 ? await getPages(gm, bufferToStream(buffer)) : Array.isArray(pages) ? pages : [pages];

const results = []
const batchSize = 10
const results = [];
const batchSize = 10;
for (let i = 0; i < pagesToConvert.length; i += batchSize) {
results.push(...await _bulk(bufferToStream(buffer), pagesToConvert.slice(i, i + batchSize), convertOptions))
results.push(...(await _bulk(bufferToStream(buffer), pagesToConvert.slice(i, i + batchSize), convertOptions)));
}

return results
}
return results;
};

convert.setOptions = (): void => setGMOptions(gm, options);

Expand All @@ -78,7 +77,7 @@ function setGMOptions(gm: Graphics, options: Options): void {
.setDensity(options.density)
.setSavePath(options.savePath)
.setSaveFilename(options.saveFilename)
.setCompression(options.compression)
.setCompression(options.compression);

return;
}
8 changes: 4 additions & 4 deletions src/types/convert.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { BufferResponse, ToBase64Response, WriteImageResponse } from './convertResponse';

export type ResponseType = 'image' | 'base64' | 'buffer'
export type ResponseType = 'image' | 'base64' | 'buffer';
export type ConvertOptions = {
responseType: ResponseType
}
responseType: ResponseType;
};

export type Convert = {
(pages?: number, options?: undefined): Promise<WriteImageResponse>;
Expand All @@ -23,4 +23,4 @@ export type Convert = {
setOptions: () => void;

setGMClass: (gmClass: string | boolean) => void;
}
};
2 changes: 1 addition & 1 deletion src/types/convertResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ export interface BufferResponse extends BaseResponse {
buffer?: Buffer;
}

export type ConvertResponse = WriteImageResponse | ToBase64Response | BufferResponse
export type ConvertResponse = WriteImageResponse | ToBase64Response | BufferResponse;
2 changes: 1 addition & 1 deletion src/types/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ export type Options = {
savePath?: string;
saveFilename?: string;
compression?: string;
}
};
6 changes: 3 additions & 3 deletions src/utils/converters/base64ToStream.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { ReadStream } from "fs";
import { bufferToStream } from "../../utils/converters/bufferToStream";
import { ReadStream } from 'fs';
import { bufferToStream } from '../../utils/converters/bufferToStream';

export function base64ToStream(base64: string): ReadStream {
const buffer = Buffer.from(base64, "base64");
const buffer = Buffer.from(base64, 'base64');

return bufferToStream(buffer);
}
6 changes: 3 additions & 3 deletions src/utils/converters/bufferToStream.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { ReadStream } from "fs";
import { Readable } from "stream";
import { ReadStream } from 'fs';
import { Readable } from 'stream';

export function bufferToStream(buffer: Buffer): ReadStream {
const readableInstanceStream = new Readable({
read() {
this.push(buffer);
this.push(null);
}
},
});

return readableInstanceStream as ReadStream;
Expand Down
Loading