From a13ab9f6c9cd24e8a415dbe64dae411d1605a087 Mon Sep 17 00:00:00 2001 From: daido1976 Date: Thu, 19 Dec 2024 14:59:45 +0900 Subject: [PATCH 1/3] Allow custom LibreOffice binary path via environment variable --- src/convert.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/convert.ts b/src/convert.ts index dfbb157..b8653a1 100644 --- a/src/convert.ts +++ b/src/convert.ts @@ -14,7 +14,7 @@ export const DEFAULT_ARGS = [ '--nologo', '--norestore', ]; -const LO_BINARY_PATH = 'libreoffice7.6'; +const LO_BINARY_PATH = process.env.LO_BINARY_PATH ?? 'libreoffice7.6'; export async function convertTo(filename: string, format: string): Promise { await cleanupTempFiles(); From 7564082f6b7f0cb057136dc29dd27c0d105f250a Mon Sep 17 00:00:00 2001 From: daido1976 Date: Thu, 19 Dec 2024 15:11:50 +0900 Subject: [PATCH 2/3] Don't ignore lib directories to commit build output --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index f6a1162..16c64ae 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ .vscode/ .serverless/ coverage/ -lib/ +# lib/ node_modules/ *.log From 2e81d28f9adedfca1ebf064a7b47b53b205cd549 Mon Sep 17 00:00:00 2001 From: daido1976 Date: Thu, 19 Dec 2024 15:13:04 +0900 Subject: [PATCH 3/3] $ npm run build --- lib/cleanup.d.ts | 1 + lib/cleanup.js | 23 +++++++++++++++++++++++ lib/convert.d.ts | 2 ++ lib/convert.js | 33 +++++++++++++++++++++++++++++++++ lib/index.d.ts | 2 ++ lib/index.js | 27 +++++++++++++++++++++++++++ lib/logs.d.ts | 1 + lib/logs.js | 15 +++++++++++++++ lib/validations.d.ts | 1 + lib/validations.js | 19 +++++++++++++++++++ 10 files changed, 124 insertions(+) create mode 100644 lib/cleanup.d.ts create mode 100644 lib/cleanup.js create mode 100644 lib/convert.d.ts create mode 100644 lib/convert.js create mode 100644 lib/index.d.ts create mode 100644 lib/index.js create mode 100644 lib/logs.d.ts create mode 100644 lib/logs.js create mode 100644 lib/validations.d.ts create mode 100644 lib/validations.js diff --git a/lib/cleanup.d.ts b/lib/cleanup.d.ts new file mode 100644 index 0000000..9eea238 --- /dev/null +++ b/lib/cleanup.d.ts @@ -0,0 +1 @@ +export declare function cleanupTempFiles(): Promise; diff --git a/lib/cleanup.js b/lib/cleanup.js new file mode 100644 index 0000000..ec7b31f --- /dev/null +++ b/lib/cleanup.js @@ -0,0 +1,23 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.cleanupTempFiles = cleanupTempFiles; +var _promises = _interopRequireDefault(require("fs/promises")); +var _del = _interopRequireDefault(require("del")); +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } +// Removes temp files generated by LibreOffice +async function cleanupTempFiles() { + const files = await _promises.default.readdir(`/tmp`); + for (const file of files) { + if (file.endsWith('.tmp') === true || file.startsWith('OSL_PIPE')) { + try { + await (0, _del.default)([`/tmp/${file}`, `/tmp/${file}/*`], { + force: true + }); + // eslint-disable-next-line no-empty + } catch (error) {} + } + } +} \ No newline at end of file diff --git a/lib/convert.d.ts b/lib/convert.d.ts new file mode 100644 index 0000000..76e8fef --- /dev/null +++ b/lib/convert.d.ts @@ -0,0 +1,2 @@ +export declare const DEFAULT_ARGS: string[]; +export declare function convertTo(filename: string, format: string): Promise; diff --git a/lib/convert.js b/lib/convert.js new file mode 100644 index 0000000..d79a800 --- /dev/null +++ b/lib/convert.js @@ -0,0 +1,33 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.DEFAULT_ARGS = void 0; +exports.convertTo = convertTo; +var _child_process = _interopRequireDefault(require("child_process")); +var _util = _interopRequireDefault(require("util")); +var _cleanup = require("./cleanup"); +var _logs = require("./logs"); +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } +const exec = _util.default.promisify(_child_process.default.exec); +const DEFAULT_ARGS = ['--headless', '--invisible', '--nodefault', '--view', '--nolockcheck', '--nologo', '--norestore']; +exports.DEFAULT_ARGS = DEFAULT_ARGS; +const LO_BINARY_PATH = process.env.LO_BINARY_PATH ?? 'libreoffice7.6'; +async function convertTo(filename, format) { + await (0, _cleanup.cleanupTempFiles)(); + const argumentsString = DEFAULT_ARGS.join(' '); + const outputFilename = filename.split(/\\ /).join(' '); + const cmd = `cd /tmp && ${LO_BINARY_PATH} ${argumentsString} --convert-to ${format} --outdir /tmp '/tmp/${outputFilename}'`; + let logs; + + // due to an unknown issue, we need to run command twice + try { + logs = (await exec(cmd)).stdout; + } catch (e) { + logs = (await exec(cmd)).stdout; + } + await exec(`rm '/tmp/${outputFilename}'`); + await (0, _cleanup.cleanupTempFiles)(); + return (0, _logs.getConvertedFilePath)(logs.toString()); +} \ No newline at end of file diff --git a/lib/index.d.ts b/lib/index.d.ts new file mode 100644 index 0000000..b793b7f --- /dev/null +++ b/lib/index.d.ts @@ -0,0 +1,2 @@ +export * from './convert'; +export * from './validations'; diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000..963d5a4 --- /dev/null +++ b/lib/index.js @@ -0,0 +1,27 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +var _convert = require("./convert"); +Object.keys(_convert).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (key in exports && exports[key] === _convert[key]) return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _convert[key]; + } + }); +}); +var _validations = require("./validations"); +Object.keys(_validations).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (key in exports && exports[key] === _validations[key]) return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _validations[key]; + } + }); +}); \ No newline at end of file diff --git a/lib/logs.d.ts b/lib/logs.d.ts new file mode 100644 index 0000000..94f5929 --- /dev/null +++ b/lib/logs.d.ts @@ -0,0 +1 @@ +export declare function getConvertedFilePath(logs: string): string; diff --git a/lib/logs.js b/lib/logs.js new file mode 100644 index 0000000..5fb948b --- /dev/null +++ b/lib/logs.js @@ -0,0 +1,15 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getConvertedFilePath = getConvertedFilePath; +function getConvertedFilePath(logs) { + try { + return logs.match(/\/tmp\/.+->\s(\/tmp\/.+) using/)[1]; + } catch (e) { + const ErrorWithExtendedMessage = new Error(e); + ErrorWithExtendedMessage.message += `;\tTried to parse string: "${logs}"`; + throw ErrorWithExtendedMessage; + } +} \ No newline at end of file diff --git a/lib/validations.d.ts b/lib/validations.d.ts new file mode 100644 index 0000000..99c762d --- /dev/null +++ b/lib/validations.d.ts @@ -0,0 +1 @@ +export declare function canBeConvertedToPDF(filename: string): boolean; diff --git a/lib/validations.js b/lib/validations.js new file mode 100644 index 0000000..54e65f4 --- /dev/null +++ b/lib/validations.js @@ -0,0 +1,19 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.canBeConvertedToPDF = canBeConvertedToPDF; +var _isVideo = _interopRequireDefault(require("is-video")); +var _isImage = _interopRequireDefault(require("is-image")); +var _isAudioFilepath = _interopRequireDefault(require("@shelf/is-audio-filepath")); +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } +const UNSUPPORTED_FILE_EXTENSIONS = ['.chm', '.heic', '.gdoc', '.gsheet', '.gslides', '.zip', '.dwg']; +function canBeConvertedToPDF(filename) { + filename = filename.toLowerCase(); + const isFileExtensionUnsupported = UNSUPPORTED_FILE_EXTENSIONS.some(ext => filename.endsWith(ext)); + if (isFileExtensionUnsupported) { + return false; + } + return !(0, _isImage.default)(filename) && !(0, _isVideo.default)(filename) && !(0, _isAudioFilepath.default)(filename); +} \ No newline at end of file