images-to-pdf-book
Advanced tools
Comparing version 0.1.6 to 0.1.7
@@ -24,2 +24,2 @@ #!/usr/bin/env node | ||
.demandOption(['images-directory', 'w', 'h', 'o']).argv; | ||
src_1.default(argv); | ||
src_1.main(argv).run(); |
@@ -1,120 +0,73 @@ | ||
'use strict'; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const chalk_1 = require("chalk"); | ||
const fs = require("fs-extra"); | ||
const Apply_1 = require("fp-ts/lib/Apply"); | ||
const Array_1 = require("fp-ts/lib/Array"); | ||
const Either_1 = require("fp-ts/lib/Either"); | ||
const function_1 = require("fp-ts/lib/function"); | ||
const IO_1 = require("fp-ts/lib/IO"); | ||
const Ord_1 = require("fp-ts/lib/Ord"); | ||
const TaskEither_1 = require("fp-ts/lib/TaskEither"); | ||
const isImage = require("is-image"); | ||
const ora = require("ora"); | ||
const os = require("os"); | ||
const pMap = require("p-map"); | ||
const Path = require("path"); | ||
const PDFDocument = require("pdfkit"); | ||
const ProgressBar = require("progress"); | ||
const recursive = require("recursive-readdir"); | ||
const sharp = require("sharp"); | ||
const cpuCount = os.cpus().length; | ||
const error = chalk_1.default.bold.red; | ||
function start({ imagesDirectory, width, height, output, }) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const doc = new PDFDocument({ | ||
autoFirstPage: false, | ||
}); | ||
const imagesDir = Path.resolve(imagesDirectory); | ||
const outputStream = fs.createWriteStream(Path.resolve(output)); | ||
doc.pipe(outputStream); | ||
const docSpinner = ora('Creating document...'); | ||
outputStream.on('close', () => { | ||
docSpinner.succeed(); | ||
process.exit(); | ||
}); | ||
const images = yield getImages(imagesDir); | ||
const resizingImagesProgressBar = new ProgressBar('Processing images [:bar] :current/:total', { | ||
total: images.length, | ||
width: 17, | ||
}); | ||
const resizingImagesPromises = pMap(images, (imagePath) => __awaiter(this, void 0, void 0, function* () { | ||
const parentDirName = getParentDirName(imagePath); | ||
const imageBuffer = yield fs.readFile(imagePath); | ||
return new Promise((resolve, reject) => sharp(imageBuffer) | ||
.trim() | ||
.toBuffer((err, trimmedImageBuffer, info) => { | ||
if (err) | ||
return reject(err); | ||
const name = parentDirName + Path.parse(imagePath).name; | ||
const newSize = calculateOutputImageSize(info, { width, height }); | ||
const resizeAndArchive = sharp(trimmedImageBuffer) | ||
.resize(...newSize) | ||
.png() | ||
.toBuffer() | ||
.then((buffer) => { | ||
resizingImagesProgressBar.tick(); | ||
return { | ||
buffer, | ||
name, | ||
size: newSize, | ||
}; | ||
}); | ||
resolve(resizeAndArchive); | ||
})); | ||
}), { concurrency: cpuCount }); | ||
yield resizingImagesPromises.then((res) => { | ||
docSpinner.start(); | ||
res | ||
.sort(sortImagesByName) // tslint:disable-line no-misleading-array-reverse | ||
.forEach((resizedImage) => addImageToDoc(resizedImage, doc)); | ||
}); | ||
doc.end(); | ||
const ora = require("./fancyConsole/ora"); | ||
const progressBar = require("./fancyConsole/progress"); | ||
const fs = require("./fs"); | ||
const img = require("./imageProcessing"); | ||
const d = require("./pdfDocument"); | ||
const recursiveReaddir_1 = require("./recursiveReaddir"); | ||
const ioParallel = Array_1.array.sequence(IO_1.io); | ||
const tEParallel = Array_1.array.sequence(TaskEither_1.taskEither); | ||
const tESeries = Array_1.array.sequence(TaskEither_1.taskEitherSeq); | ||
const sequenceTIo = Apply_1.sequenceT(IO_1.io); | ||
const cpuCountIO = new IO_1.IO(() => os.cpus()).map((_) => _.length); | ||
const exit = new IO_1.IO(() => process.exit()); | ||
const createProgressBar = (total) => progressBar.create('Processing images [:bar] :current/:total', { | ||
total, | ||
width: 17, | ||
}); | ||
const getImagePaths = (imagesDir) => recursiveReaddir_1.recursiveTE(imagesDir).map((files) => Array_1.filter(files, isImage)); | ||
const getParentDirName = (imagePath) => Array_1.last(Path.dirname(imagePath).split('/')); | ||
const ordImagesByName = Ord_1.contramap((image) => image.name.toLowerCase(), Ord_1.ordString); | ||
const initOutputAndCreateSpinner = (outputFile, doc) => TaskEither_1.fromIO(sequenceTIo(fs.createWriteStream(Path.resolve(outputFile)).chain(d.pipeDoc(doc)), ora.create('Creating document...'))); | ||
const processImage = (progressBarInstance) => (imagePath, { width, height }) => { | ||
const fileName = Path.parse(imagePath).name; | ||
const fullName = getParentDirName(imagePath).fold(fileName, (dirName) => dirName + fileName); | ||
return fs | ||
.readFile(imagePath) | ||
.chain(img.trimImage) | ||
.chain(({ fst: buffer, snd: info }) => { | ||
const outputSize = img.calculateOutputImageSize(info, { width, height }); | ||
return img | ||
.resizeImage(outputSize, buffer) | ||
.chain(() => TaskEither_1.fromIO(progressBar.tick(progressBarInstance)).chain(() => TaskEither_1.taskEither.of({ buffer, name: fullName, size: outputSize }))); | ||
}); | ||
} | ||
exports.default = start; | ||
function getImages(imagesDir) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const files = yield recursive(imagesDir); | ||
return files.filter(isImage); | ||
}; | ||
const prepareImages = (imagePaths, outputSize, cpuCount, progressBarInstance) => { | ||
const processImageWithProgressBar = processImage(progressBarInstance); | ||
// Let's take advantage on multithreading by running the tasks asynchronously. | ||
// The tasks are being chunked, each chunk runs in series, in order to bail out | ||
// as soon as a task fails. | ||
return tESeries(Array_1.chunksOf(imagePaths, cpuCount).map((chunk) => tEParallel(chunk.map((imagePath) => processImageWithProgressBar(imagePath, outputSize))))).map(function_1.compose(Array_1.sort(ordImagesByName), Array_1.flatten)); | ||
}; | ||
const writeImagesToDocument = (doc, docSpinner) => (images) => TaskEither_1.fromIO(ora | ||
.start(docSpinner) | ||
.chain(() => ioParallel(images.map(d.addImageToDoc(doc)))) | ||
.chain(() => d.closeDoc(doc))); | ||
const getCpuCountAndCreateProgressBar = (progressBarLength) => TaskEither_1.fromIO(sequenceTIo(cpuCountIO, createProgressBar(progressBarLength))); | ||
function main({ imagesDirectory, width, height, output, }) { | ||
const doc = new PDFDocument({ autoFirstPage: false }); | ||
const imagesDir = Path.resolve(imagesDirectory); | ||
const outputSize = { width, height }; | ||
return initOutputAndCreateSpinner(output, doc).chain(([outputStream, docSpinner]) => { | ||
outputStream.on('close', () => (docSpinner.isSpinning | ||
? sequenceTIo(ora.succeed(docSpinner, 'Done!'), exit) | ||
: exit).run()); | ||
return getImagePaths(imagesDir).chain((imagePaths) => getCpuCountAndCreateProgressBar(imagePaths.length) | ||
.chain(([cpuCount, progressBarInstance]) => prepareImages(imagePaths, outputSize, cpuCount, progressBarInstance)) | ||
.chain(writeImagesToDocument(doc, docSpinner)) | ||
.foldTaskEither((err) => TaskEither_1.fromIO(ora.fail(docSpinner, err.message).chain(() => IO_1.io.of(undefined))).chain(() => TaskEither_1.fromEither(Either_1.left(err))), () => TaskEither_1.taskEither.of(undefined))); | ||
}); | ||
} | ||
function getParentDirName(imagePath) { | ||
return Path.dirname(imagePath) | ||
.split('/') | ||
.pop(); | ||
} | ||
function calculateOutputImageSize(imageSize, viewportSize) { | ||
const outputRatio = viewportSize.width / viewportSize.height; | ||
const imageRatio = imageSize.width / imageSize.height; | ||
// determs if the image orientation will be portrait or landscape | ||
// if landscape, fit the image by viewport's height | ||
const outputImageRatio = imageRatio < outputRatio | ||
? viewportSize.width / viewportSize.height | ||
: (viewportSize.width * 2) / viewportSize.height; | ||
return imageRatio > outputImageRatio | ||
? [viewportSize.width, Math.round(viewportSize.width / imageRatio)] | ||
: [Math.round(viewportSize.height * imageRatio), viewportSize.height]; | ||
} | ||
function sortImagesByName(prev, next) { | ||
const prevName = prev.name.toLowerCase(); | ||
const nextName = next.name.toLowerCase(); | ||
if (prevName < nextName) | ||
return -1; | ||
if (prevName > nextName) | ||
return 1; | ||
return 0; | ||
} | ||
function addImageToDoc({ buffer, size }, doc) { | ||
doc.addPage({ size }); | ||
doc.image(buffer, 0, 0, { fit: size }); | ||
} | ||
process.on('unhandledRejection', (err) => { | ||
throw err; | ||
}); | ||
process.on('uncaughtException', ({ message, stack }) => { | ||
console.error(error(message)); | ||
console.error(stack); | ||
process.exit(1); | ||
}); | ||
exports.main = main; |
{ | ||
"name": "images-to-pdf-book", | ||
"version": "0.1.6", | ||
"version": "0.1.7", | ||
"description": "Create a PDF document from a bunch of images.", | ||
@@ -24,32 +24,31 @@ "keywords": [ | ||
"dependencies": { | ||
"chalk": "^2.4.1", | ||
"fs-extra": "^7.0.0", | ||
"fp-ts": "^1.15.1", | ||
"io-ts": "^1.8.5", | ||
"io-ts-types": "^0.4.6", | ||
"is-image": "^2.0.0", | ||
"ora": "^3.0.0", | ||
"p-map": "^1.2.0", | ||
"pdfkit": "^0.8.3", | ||
"progress": "^2.0.0", | ||
"ora": "^3.4.0", | ||
"pdfkit": "^0.9.0", | ||
"progress": "^2.0.3", | ||
"recursive-readdir": "^2.2.2", | ||
"rm": "^0.1.8", | ||
"sharp": "^0.20.5", | ||
"yargs": "^12.0.1" | ||
"sharp": "^0.22.0", | ||
"yargs": "^13.2.2" | ||
}, | ||
"devDependencies": { | ||
"@types/fs-extra": "^5.0.4", | ||
"@types/node": "^10.5.4", | ||
"@types/ora": "^1.3.4", | ||
"@types/p-map": "^1.1.0", | ||
"@types/is-image": "^2.0.0", | ||
"@types/node": "^11.13.0", | ||
"@types/ora": "^3.2.0", | ||
"@types/pdfkit": "^0.7.36", | ||
"@types/progress": "^2.0.1", | ||
"@types/progress": "^2.0.3", | ||
"@types/recursive-readdir": "^2.2.0", | ||
"@types/sharp": "^0.17.9", | ||
"@types/yargs": "^11.1.1", | ||
"husky": "^0.14.3", | ||
"prettier": "^1.13.7", | ||
"tslint": "^5.11.0", | ||
"tslint-config-prettier": "^1.14.0", | ||
"tslint-immutable": "^4.6.0", | ||
"tslint-plugin-prettier": "^1.3.0", | ||
"tslint-sonarts": "^1.7.0", | ||
"typescript": "^2.9.2" | ||
"@types/sharp": "^0.22.1", | ||
"@types/yargs": "^11.1.2", | ||
"husky": "^1.3.1", | ||
"prettier": "^1.16.4", | ||
"tslint": "^5.15.0", | ||
"tslint-config-prettier": "^1.18.0", | ||
"tslint-config-standard": "^8.0.1", | ||
"tslint-plugin-prettier": "^2.0.1", | ||
"typescript": "^3.4.2", | ||
"typestrict": "^1.0.2" | ||
}, | ||
@@ -56,0 +55,0 @@ "author": { |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
182135
16
18
227
2
1
+ Addedfp-ts@^1.15.1
+ Addedio-ts@^1.8.5
+ Addedio-ts-types@^0.4.6
+ Addedbl@4.1.0(transitive)
+ Addedbuffer@5.7.1(transitive)
+ Addedcliui@5.0.0(transitive)
+ Addedcrypto-js@3.3.0(transitive)
+ Addeddecompress-response@4.2.1(transitive)
+ Addedemoji-regex@7.0.3(transitive)
+ Addedexpand-template@2.0.3(transitive)
+ Addedfp-ts@1.19.5(transitive)
+ Addedieee754@1.2.1(transitive)
+ Addedio-ts@1.10.4(transitive)
+ Addedio-ts-types@0.4.8(transitive)
+ Addedmimic-response@2.1.0(transitive)
+ Addedmkdirp-classic@0.5.3(transitive)
+ Addedmonocle-ts@1.7.2(transitive)
+ Addednapi-build-utils@1.0.2(transitive)
+ Addednewtype-ts@0.2.4(transitive)
+ Addedpdfkit@0.9.1(transitive)
+ Addedprebuild-install@5.3.6(transitive)
+ Addedreadable-stream@3.6.2(transitive)
+ Addedrequire-main-filename@2.0.0(transitive)
+ Addedsaslprep@1.0.1(transitive)
+ Addedsemver@6.3.1(transitive)
+ Addedsharp@0.22.1(transitive)
+ Addedsimple-get@3.1.1(transitive)
+ Addedstring-width@3.1.0(transitive)
+ Addedtar-fs@2.1.2(transitive)
+ Addedtar-stream@2.2.0(transitive)
+ Addedwrap-ansi@5.1.0(transitive)
+ Addedyargs@13.3.2(transitive)
+ Addedyargs-parser@13.1.2(transitive)
- Removedchalk@^2.4.1
- Removedfs-extra@^7.0.0
- Removedp-map@^1.2.0
- Removedansi-regex@3.0.1(transitive)
- Removedbl@1.2.3(transitive)
- Removedbuffer-alloc@1.2.0(transitive)
- Removedbuffer-alloc-unsafe@1.1.0(transitive)
- Removedbuffer-fill@1.0.0(transitive)
- Removedcliui@4.1.0(transitive)
- Removedcross-spawn@6.0.6(transitive)
- Removeddecompress-response@3.3.0(transitive)
- Removedexeca@1.0.0(transitive)
- Removedexpand-template@1.1.1(transitive)
- Removedfs-extra@7.0.1(transitive)
- Removedget-caller-file@1.0.3(transitive)
- Removedget-stream@4.1.0(transitive)
- Removedinvert-kv@2.0.0(transitive)
- Removedis-stream@1.1.0(transitive)
- Removedlcid@2.0.0(transitive)
- Removedmap-age-cleaner@0.1.3(transitive)
- Removedmem@4.3.0(transitive)
- Removedmimic-fn@2.1.0(transitive)
- Removedmimic-response@1.0.1(transitive)
- Removednice-try@1.0.5(transitive)
- Removednpm-run-path@2.0.2(transitive)
- Removedos-homedir@1.0.2(transitive)
- Removedos-locale@3.1.0(transitive)
- Removedp-defer@1.0.0(transitive)
- Removedp-finally@1.0.0(transitive)
- Removedp-is-promise@2.1.0(transitive)
- Removedp-map@1.2.0(transitive)
- Removedpath-key@2.0.1(transitive)
- Removedpdfkit@0.8.3(transitive)
- Removedprebuild-install@4.0.0(transitive)
- Removedpump@1.0.32.0.1(transitive)
- Removedrequire-main-filename@1.0.1(transitive)
- Removedsharp@0.20.8(transitive)
- Removedshebang-command@1.2.0(transitive)
- Removedshebang-regex@1.0.0(transitive)
- Removedsimple-get@2.8.2(transitive)
- Removedstring-width@2.1.1(transitive)
- Removedstrip-ansi@4.0.0(transitive)
- Removedstrip-eof@1.0.0(transitive)
- Removedtar-fs@1.16.4(transitive)
- Removedtar-stream@1.6.2(transitive)
- Removedto-buffer@1.1.1(transitive)
- Removedwhich@1.3.1(transitive)
- Removedwrap-ansi@2.1.0(transitive)
- Removedyargs@12.0.5(transitive)
- Removedyargs-parser@11.1.1(transitive)
Updatedora@^3.4.0
Updatedpdfkit@^0.9.0
Updatedprogress@^2.0.3
Updatedsharp@^0.22.0
Updatedyargs@^13.2.2