libreconv
Version:
A simple and fast node.js module for converting office documents to different formats
91 lines (81 loc) • 2.57 kB
JavaScript
const debug = require('debug')('libreconv');
const assert = require('assert');
const fs = require('fs-extra');
const tmp = require('tmp');
const path = require('path');
const exec = require('child-process-promise').exec;
const PromiseA = require('bluebird');
tmp.setGracefulCleanup();
const SOFFICE_POSSIBLE_PATHS = (platform => {
switch (platform) {
case 'darwin':
return ['/Applications/LibreOffice.app/Contents/MacOS/soffice'];
case 'linux':
return ['/usr/bin/libreoffice', '/usr/bin/soffice'];
case 'win32':
return [path.join(process.env['PROGRAMFILES(X86)'], 'LIBREO~1/program/soffice.exe')];
}
})(process.platform);
function findSoffice(paths) {
for (let i = 0; i < paths.length; i++) {
if (paths[i] && fs.existsSync(paths[i])) {
return paths[i];
}
}
}
exports.convert = function (file, format, opts) {
if (!SOFFICE_POSSIBLE_PATHS) {
return PromiseA.reject(new Error('Operating system not yet supported: ' + process.platform));
}
const soffice = findSoffice(SOFFICE_POSSIBLE_PATHS);
if (!soffice) {
return PromiseA.reject(new Error('Could not find soffice binary'));
}
assert(file, '`file` is required');
file = path.resolve(file);
opts = opts || {};
if (typeof format !== 'string') {
opts = format;
format = null;
}
format = format || opts.format;
assert(format, '`format` is required');
let filter, dir;
if (format.indexOf(':') > 0) {
const parts = format.split(':');
format = parts[0];
filter = parts[1];
}
dir = opts.output || opts.dir;
filter = opts.filter || filter;
if (filter && filter[0] !== '"') {
filter = `"${filter}"`;
}
return PromiseA.try(() => {
if (dir) {
fs.mkdirpSync(dir);
return {dir};
}
return PromiseA.fromCallback(cb => tmp.dir({
unsafeCleanup: true,
template: '/tmp/libreconv-XXXXXX'
}, cb), {multiArgs: true}).spread((dir, cleanup) => ({dir, cleanup}));
}).then(({dir, cleanup}) => {
let command = `${soffice} --headless --convert-to ${format}`;
if (filter) {
command += `:${filter}`;
}
command += ` --outdir "${dir}" "${file}"`;
debug('Executing:\n', command);
return exec(command).then(result => {
const {stdout, stderr} = result;
if (stderr) {
throw new Error(stderr);
}
debug('Executed with result:\n', stdout);
const output = path.resolve(dir, path.basename(file, path.extname(file)) + '.' + format);
debug('output:', output);
return {stdout, output, cleanup};
});
})
};