UNPKG

pdflatex-ts

Version:

A TypeScript library for converting LaTeX files to PDF using pdflatex. Supports both file conversion and dynamic content generation.

161 lines 5.82 kB
import * as fs from 'fs'; import * as path from 'path'; import { spawn } from 'child_process'; import { FileUtils } from './utils/file-utils'; import process from 'process'; export class LatexToPdfConverter { convert(input, options = {}, callback) { const startTime = Date.now(); try { FileUtils.validateInputFile(input); const config = this.setupConfiguration(input, options); FileUtils.ensureDirectoryExists(config.outputDir); this.executeConversion(input, config, startTime, callback); } catch (error) { const executionTime = Date.now() - startTime; callback(error, { success: false, error: error.message, executionTime, }); } } convertAsync(input, options = {}) { return new Promise((resolve, reject) => { this.convert(input, options, (error, result) => { if (error) { reject(error); } else { resolve(result); } }); }); } async convertFromContent(latexContent, filename, options = {}) { const tempDir = path.join(process.cwd(), 'temp'); const tempFile = path.join(tempDir, `${filename}.tex`); try { FileUtils.ensureDirectoryExists(tempDir); fs.writeFileSync(tempFile, latexContent, 'utf8'); const result = await this.convertAsync(tempFile, options); FileUtils.safeDelete(tempFile); return result; } catch (error) { FileUtils.safeDelete(tempFile); throw error; } } setupConfiguration(input, options) { const inputParsed = path.parse(input); const outputDir = options.output ? path.parse(options.output).dir : LatexToPdfConverter.DEFAULT_OUTPUT_DIR; const outputFile = options.output ? path.parse(options.output).name : inputParsed.name; return { outputDir, outputFile, timeout: options.timeout ?? LatexToPdfConverter.DEFAULT_TIMEOUT, debug: options.debug ?? false, cleanupAuxFiles: options.cleanupAuxFiles ?? true, }; } executeConversion(input, config, startTime, callback) { let processKilled = false; let outputBuffer = ''; let errorBuffer = ''; const pdflatexProcess = spawn('pdflatex', [ '--jobname', config.outputFile, '-output-directory', config.outputDir, input, ]); pdflatexProcess.stdout?.on('data', (data) => { const output = data.toString(); outputBuffer += output; if (config.debug) { console.log('STDOUT:', output); } }); pdflatexProcess.stderr?.on('data', (data) => { const error = data.toString(); errorBuffer += error; if (config.debug) { console.error('STDERR:', error); } }); pdflatexProcess.on('exit', (code) => { const executionTime = Date.now() - startTime; if (config.cleanupAuxFiles) { this.cleanupAuxiliaryFiles(config.outputDir, config.outputFile); } if (processKilled) { callback(new Error('Conversion timeout'), { success: false, error: 'Process timed out', executionTime, }); return; } if (code === 0) { const outputPath = path.join(config.outputDir, `${config.outputFile}.pdf`); if (fs.existsSync(outputPath)) { callback(null, { success: true, outputPath, executionTime, }); } else { callback(new Error('PDF file was not created'), { success: false, error: 'PDF file was not created', executionTime, }); } } else { callback(new Error(`pdflatex failed with code ${code}`), { success: false, error: `pdflatex failed with code ${code}. Error: ${errorBuffer}`, executionTime, }); } }); pdflatexProcess.on('error', (error) => { const executionTime = Date.now() - startTime; callback(error, { success: false, error: `Process error: ${error.message}`, executionTime, }); }); const timeoutId = setTimeout(() => { processKilled = true; pdflatexProcess.kill('SIGTERM'); setTimeout(() => { if (!pdflatexProcess.killed) { pdflatexProcess.kill('SIGKILL'); } }, 5000); }, config.timeout); pdflatexProcess.on('exit', () => { clearTimeout(timeoutId); }); } cleanupAuxiliaryFiles(outputDir, outputFile) { const auxiliaryExtensions = ['.aux', '.log', '.out', '.toc', '.nav', '.snm']; auxiliaryExtensions.forEach((ext) => { const filePath = path.join(outputDir, `${outputFile}${ext}`); FileUtils.safeDelete(filePath); }); } } LatexToPdfConverter.DEFAULT_TIMEOUT = 60000; LatexToPdfConverter.DEFAULT_OUTPUT_DIR = 'output'; //# sourceMappingURL=latex-converter.js.map