UNPKG

@argdown/node

Version:

Async Argdown application for node.js

145 lines 5.82 kB
import PDFDocument from "pdfkit"; import { promises as fs, createWriteStream } from "fs"; let path = require("path"); let mkdirp = require("mkdirp"); import SVGtoPDF from "svg-to-pdfkit"; import defaultsDeep from "lodash.defaultsdeep"; import isFunction from "lodash.isfunction"; import isString from "lodash.isstring"; import { checkResponseFields, ensure, mergeDefaults, ArgdownPluginError } from "@argdown/core"; const defaultSettings = { outputDir: "./pdf", format: "svg", width: 612, height: 792, padding: 10, pdf: ensure.object({ compress: false }), svg: ensure.object({ useCss: true, assumePt: true, preserveAspectRatio: "xMidYMid meet" }) }; export class SvgToPdfExportPlugin { constructor(config) { this.name = "SvgToPdfExportPlugin"; this.prepare = (request, response) => { checkResponseFields(this, response, ["svg"]); mergeDefaults(this.getSettings(request), this.defaults); }; this.runAsync = async (request, response) => { const settings = this.getSettings(request); let fileName = "default"; let outputDir = settings.outputDir; if (request.outputPath) { outputDir = path.dirname(request.outputPath); } else if (request.pdf && request.pdf.outputDir) { outputDir = path.dirname(request.pdf.outputDir); } if (request.outputPath) { fileName = this.getFileName(request.outputPath); } else if (isFunction(settings.fileName)) { fileName = settings.fileName.call(this, settings, request, response); } else if (isString(settings.fileName)) { fileName = settings.fileName; } else if (request.inputPath) { fileName = this.getFileName(request.inputPath); } if (request.outputSuffix) { fileName = fileName + request.outputSuffix; } const absoluteOutputDir = path.resolve(process.cwd(), outputDir); const filePath = absoluteOutputDir + "/" + fileName + ".pdf"; await mkdirp(absoluteOutputDir); const doc = new PDFDocument({ size: [settings.width || 0, settings.height || 0], ...settings.pdf }); if (settings.fonts) { for (let font of settings.fonts) { try { const baseDir = request.inputPath && !!path.extname(request.inputPath) ? path.dirname(request.inputPath) : request.inputPath || ""; const fontPath = path.resolve(baseDir || process.cwd(), font.path); const buffer = await fs.readFile(fontPath); const arrayBuffer = this.toArrayBuffer(buffer); doc.registerFont(font.name, arrayBuffer); } catch (e) { if (e instanceof ArgdownPluginError) { throw new ArgdownPluginError(this.name, "pdf-custom-font-load-failed", `Could not register custom font ${font.name}.\n` + e.message); } } } } const fontCallback = settings.fonts ? (family, bold, italic, _fontOptions) => { let face = family.replace(/["']/g, "").replace(/-/g, " "); if (bold && italic) face = `${face} Bold Italic`; if (bold) face = `${face} Bold`; if (italic) face = `${face} Italic`; const re = new RegExp(`${face}( Regular)?$`); let match = settings.fonts.find(fontObj => { return re.test(fontObj.name); }); if (match !== undefined) { return match.name; } else { throw new ArgdownPluginError(this.name, "pdf-custom-font-not-found", `Could not find custom pdf font: ${face}`); } } : null; SVGtoPDF(doc, response.svg, settings.padding, settings.padding, { width: settings.width - settings.padding * 2, height: settings.height - settings.padding * 2, fontCallback, ...settings.svg }); await this.savePdfToFile(doc, filePath); }; this.defaults = defaultsDeep({}, config, defaultSettings); } getSettings(request) { request.svgToPdf = request.svgToPdf || {}; return request.svgToPdf; } async savePdfToFile(pdf, fileName) { return new Promise(resolve => { let pendingStepCount = 2; const stepFinished = () => { if (--pendingStepCount == 0) { resolve(); } }; const writeStream = createWriteStream(fileName); writeStream.on("close", stepFinished); pdf.pipe(writeStream); pdf.end(); stepFinished(); }); } getFileName(file) { let extension = path.extname(file); return path.basename(file, extension); } toArrayBuffer(buf) { var ab = new ArrayBuffer(buf.length); var view = new Uint8Array(ab); for (var i = 0; i < buf.length; ++i) { view[i] = buf[i]; } return ab; } } //# sourceMappingURL=SvgToPdfExportPlugin.js.map