diff --git a/README.md b/README.md index f7a3f49..2a1ec41 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,16 @@ This library is inspired by the [PHP library PDFMerger](https://github.com/myoky `npm install --save pdf-merger-js` +of global installation if you want to use the cli tool: + +`npm install -g pdf-merger-js` + ## Usage +### CLI + +`pdf-merge --output ./merged.pdf ./input1.pdf#1-2 ./input2.pdf#1,2,5-7` + ### node.js The node.js version has the following export functions: diff --git a/cli.js b/cli.js new file mode 100644 index 0000000..a75018f --- /dev/null +++ b/cli.js @@ -0,0 +1,46 @@ +#!/usr/bin/env node + +import { program } from 'commander' + +import PDFMerger from './index.js' +import { parsePagesString } from './parsePagesString.js' + +import packageJson from './package.json' assert { type: 'json' }; + +async function main() { + program + .version(packageJson.version) + .description(packageJson.description) + .option('-o, --output ', 'Merged PDF output file path') + .arguments('') + .action(async (inputFiles, cmd) => { + const outputFile = cmd.output; + + if (!outputFile) { + console.error('Please provide an output file using the --output flag'); + return; + } + + try { + await mergePDFs(outputFile, inputFiles); + console.log(`Merged PDFs successfully into ${outputFile}`); + } catch (error) { + console.error('An error occurred while merging PDFs:', error); + } + }); + + program.parse(process.argv); +} + +async function mergePDFs(outputFile, inputFiles) { + const merger = new PDFMerger(); + + for (const inputFile of inputFiles) { + const [filePath, pageRange] = inputFile.split('#'); + const pages = pageRange ? parsePagesString(pageRange) : null; + await merger.add(filePath, pages); + } + await merger.save(outputFile); +} + +main(); diff --git a/package-lock.json b/package-lock.json index ade5dec..1e8f133 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,12 @@ "version": "5.0.0", "license": "MIT", "dependencies": { + "commander": "^11.1.0", "pdf-lib": "^1.17.1" }, + "bin": { + "pdf-merger-js": "cli.js" + }, "devDependencies": { "fs-extra": "^11.2.0", "jest": "^29.7.0", @@ -2054,6 +2058,14 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "engines": { + "node": ">=16" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -9152,6 +9164,11 @@ "delayed-stream": "~1.0.0" } }, + "commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==" + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", diff --git a/package.json b/package.json index eaa6d14..60e452e 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,9 @@ "main": "./index.js", "types": "./index.d.ts", "browser": "./browser.js", + "bin": { + "pdf-merge": "cli.js" + }, "scripts": { "standard": "standard", "standard:fix": "standard --fix", @@ -29,6 +32,7 @@ "author": "nbesli", "license": "MIT", "dependencies": { + "commander": "^11.1.0", "pdf-lib": "^1.17.1" }, "devDependencies": { diff --git a/test/cli.test.js b/test/cli.test.js new file mode 100644 index 0000000..b33a499 --- /dev/null +++ b/test/cli.test.js @@ -0,0 +1,41 @@ +import path from 'path' +import fs from 'fs-extra' +import pdfDiff from 'pdf-diff' +import { exec } from 'child_process' +import util from 'util' +import { jest } from '@jest/globals' + +const asyncExec = util.promisify(exec) + +const __dirname = path.dirname(new URL(import.meta.url).pathname) +const FIXTURES_DIR = path.join(__dirname, 'fixtures') +const TMP_DIR = path.join(__dirname, 'tmp') + +jest.setTimeout(10000) + +async function mergePDFsCli (outputFile, inputFiles) { + const { stdout, stderr } = await asyncExec(`node ./cli.js --output ${outputFile} ${inputFiles.join(' ')}`) + return { stdout, stderr } +} + +describe('issues', () => { + beforeAll(async () => { + await fs.ensureDir(TMP_DIR) + }) + + test('should merge two pdfs', async () => { + await mergePDFsCli(path.join(TMP_DIR, 'Testfile_AB.pdf'), [ + path.join(FIXTURES_DIR, 'Testfile_A.pdf'), + path.join(FIXTURES_DIR, 'Testfile_B.pdf') + ]) + const diff1 = await pdfDiff( + path.join(FIXTURES_DIR, 'Testfile_AB.pdf'), + path.join(TMP_DIR, 'Testfile_AB.pdf') + ) + expect(diff1).toBeFalsy() + }) + + afterAll(async () => { + await fs.remove(TMP_DIR) + }) +})