Skip to content

Commit

Permalink
Refactor the lib to async/await and refactor the tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathas committed Nov 8, 2017
1 parent 0ddcd37 commit 8471ef6
Show file tree
Hide file tree
Showing 5 changed files with 224 additions and 241 deletions.
54 changes: 54 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"parser": "babel-eslint",
"rules": {
"strict": [2, "global"],
"indent": ["error", 4],
"quotes": [2, "single"],
"linebreak-style": [2, "unix"],
"semi": [2, "always"],
"array-bracket-spacing": [2, "never"],
"space-in-parens": [2, "never"],
"computed-property-spacing": [2, "never"],
"block-spacing": [2, "never"],
"brace-style": [2],
"camelcase": [2, { "properties": "never" }],
"comma-spacing": [2, { "before": false, "after": true }],
"eol-last": 0,
"key-spacing": [2, { "beforeColon": false, "afterColon": true }],
"new-cap": 2,
"new-parens": 2,
"no-mixed-spaces-and-tabs": [2, "smart-tabs"],
"no-multiple-empty-lines": [2, { "max": 2 }],
"no-trailing-spaces": 2,
"no-spaced-func": 2,
"no-unneeded-ternary": 2,
"one-var": [2, "never"],
"operator-linebreak": [2, "after"],
"padded-blocks": [2, "never"],
"quote-props": [2, "consistent-as-needed"],
"semi-spacing": [2, { "before": false, "after": true }],
"keyword-spacing": 2,
"no-console": "off",
"space-before-blocks": 2,
"space-before-function-paren": [
0, { "anonymous": "always", "named": "never" }
],
"space-infix-ops": 2,
"space-unary-ops": [1, { "words": true, "nonwords": false }],
"spaced-comment": [2, "always", { "markers": ["!", "*"] }]
},
"env": {
"es6": true,
"node": true,
"browser": true,
"mocha": true
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": 6,
"ecmaFeatures": {
"experimentalObjectRestSpread": true
}
},
"plugins": []
}
4 changes: 1 addition & 3 deletions .jshintrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
{
"esnext" : true,
"node" : true,
"mocha" : true
"esversion": 6
}
15 changes: 1 addition & 14 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1 @@
"use strict";

const child = require('child_process');
const pdf2img = require('./lib/pdf2img');

module.exports = (() => {
child.exec(`which graphicsmagick`, (err, stdout, stderr) => {
if (err) {
console.error('Please install graphicsmagick in order to run pdf2img');
process.exit(1);
}
return pdf2img;
});
})();
module.exports = require('./lib/pdf2img');
264 changes: 119 additions & 145 deletions lib/pdf2img.js
Original file line number Diff line number Diff line change
@@ -1,185 +1,159 @@
"use strict";

const fs = require('fs');
const gm = require('gm');
const path = require('path');
const util = require('util');
const stat = util.promisify(fs.stat);
const mkdir = util.promisify(fs.mkdir);

class Pdf2Img {
constructor() {
this.options = {
type: 'jpg',
size: 1024,
density: 600,
outputdir: null,
outputname: null,
page: null
};
}

let options = {
type: 'jpg',
size: 1024,
density: 600,
outputdir: null,
outputname: null,
page: null
};

let Pdf2Img = function() {};

Pdf2Img.prototype.setOptions = function(opts) {
options.type = opts.type || options.type;
options.size = opts.size || options.size;
options.density = opts.density || options.density;
options.outputdir = opts.outputdir || options.outputdir;
options.outputname = opts.outputname || options.outputname;
options.page = opts.page || options.page;
};

Pdf2Img.prototype.convert = function(input, callbackreturn) {
// Make sure it has correct extension
if (path.extname(path.basename(input)) != '.pdf') {
return callbackreturn({
result: 'error',
message: 'Unsupported file type.'
});
setOptions(opts) {
this.options.type = opts.type || this.options.type;
this.options.size = opts.size || this.options.size;
this.options.density = opts.density || this.options.density;
this.options.outputdir = opts.outputdir || this.options.outputdir;
this.options.outputname = opts.outputname || this.options.outputname;
this.options.page = opts.page || this.options.page;
}

// Check if input file exists
if (!isFileExists(input)) {
return callbackreturn({
result: 'error',
message: 'Input file not found.'
});
async convert(input) {
try {
await this.validate(input);
let pages = await this.getPagesCount(input);
return this.convertPdf(input, pages);
} catch (err) {
console.error(err);
throw err;
}
}

let stdout = [];
let output = path.basename(input, path.extname(path.basename(input)));
async validate(input) {
if (!input) {
throw new Error('Invalid input file path.');
}

// Set output dir
if (options.outputdir) {
options.outputdir = options.outputdir + path.sep;
} else {
options.outputdir = output + path.sep;
}
if (path.extname(path.basename(input)) != '.pdf') {
throw new Error('Unsupported file type.');
}

// Create output dir if it doesn't exists
if (!isDirExists(options.outputdir)) {
fs.mkdirSync(options.outputdir);
}
let statInput = await stat(input);

// Set output name
if (options.outputname) {
options.outputname = options.outputname;
} else {
options.outputname = output;
if (!statInput.isFile()) {
throw new Error('Input file not found.');
}
}

async.waterfall([
// Get pages count
function(callback) {
gm(input).identify("%p ", function(err, value) {
getPagesCount(input) {
return new Promise((resolve, reject) => {
gm(input).identify('%p ', (err, value) => {
if (err) return reject(err);

let pageCount = String(value).split(' ');

if (!pageCount.length) {
callback({
result: 'error',
message: 'Invalid page number.'
}, null);
return reject('Invalid page number.');
} else {
// Convert selected page
if (options.page !== null) {
if (options.page < pageCount.length) {
callback(null, [options.page]);
if (this.options.page !== null) {
if (this.options.page < pageCount.length) {
return resolve([this.options.page]);
} else {
callback({
result: 'error',
message: 'Invalid page number.'
}, null);
return reject('Invalid page number.');
}
} else {
callback(null, pageCount);
return resolve(pageCount);
}
}
});
});
}

})
async convertPdf(input, pages) {
try {
let stdout = [];
let output = this.getOutput(input);
await this.setOutDir(output);
this.setOutName(output);

},
for (let page of pages) {
let inputStream = fs.createReadStream(input);
let outputFile = `${this.options.outputdir}${this.options.outputname}_${page}.${this.options.type}`;
let result = await this.convertPdf2Img(inputStream, outputFile, parseInt(page));
stdout.push(result);
}

return {
result: 'success',
message: stdout
};
} catch (err) {
throw new Error(err);
}
}

// Convert pdf file
function(pages, callback) {
// Use eachSeries to make sure that conversion has done page by page
async.eachSeries(pages, function(page, callbackmap) {
let inputStream = fs.createReadStream(input);
let outputFile = options.outputdir + options.outputname + '_' + page + '.' + options.type;
getOutput(input) {
return path.basename(input, path.extname(path.basename(input)));
}

convertPdf2Img(inputStream, outputFile, parseInt(page), function(error, result) {
if (error) {
return callbackmap(error);
}
async setOutDir(output) {
if (this.options.outputdir) {
this.options.outputdir = this.options.outputdir + path.sep;
} else {
this.options.outputdir = output + path.sep;
}

stdout.push(result);
return callbackmap(error, result);
});
}, function(e) {
if (e) callback(e);
let statDir = await stat(this.options.outputdir);

return callback(null, {
result: 'success',
message: stdout
});
});
if (!statDir.isDirectory()) {
await mkdir(this.options.outputdir);
}
], callbackreturn);
};

let convertPdf2Img = function(input, output, page, callback) {
if (input.path) {
let filepath = input.path;
} else {
return callback({
result: 'error',
message: 'Invalid input file path.'
}, null);
}

let filename = filepath + '[' + (page - 1) + ']';

gm(input, filename)
.density(options.density, options.density)
.resize(options.size)
.quality(100)
.write(output, function(err) {
if (err) {
return callback({
result: 'error',
message: 'Can not write output file.'
}, null);
}
setOutName(output) {
if (this.options.outputname) {
this.options.outputname = this.options.outputname;
} else {
this.options.outputname = output;
}
}

if (!(fs.statSync(output)['size'] / 1000)) {
return callback({
result: 'error',
message: 'Zero sized output image detected.'
}, null);
}
async convertPdf2Img(inputStream, output, page) {
return new Promise((resolve, reject) => {
let filename = `${inputStream.path}[${(page - 1)}]`;
gm(inputStream, filename)
.density(this.options.density, this.options.density)
.resize(this.options.size)
.quality(100)
.write(output, (err) => {
if (err) {
return reject('Wasn\'t able to write the output file.');
}

let results = {
page: page,
name: path.basename(output),
size: fs.statSync(output)['size'] / 1000.0,
path: output
};
stat(output).then(statOut => {
if ((statOut.size / 1000) === 0) {
return reject('Zero sized output image detected.');
}

return callback(null, results);
return resolve({
page: page,
name: path.basename(output),
size: statOut.size / 1000.0,
path: output
});
});
});
});
};

// Check if directory is exists
let isDirExists = function(path) {
try {
return fs.statSync(path).isDirectory();
} catch (e) {
return false;
}
}

// Check if file is exists
let isFileExists = function(path) {
try {
return fs.statSync(path).isFile();
} catch (e) {
return false;
}
}

module.exports = new Pdf2Img;
module.exports = new Pdf2Img();
Loading

0 comments on commit 8471ef6

Please sign in to comment.