UNPKG

makebook

Version:

📖 MakeBook - Convert Markdown into beautifully formatted PDFs.

132 lines (112 loc) • 4.51 kB
import fs from "fs"; import path from "path"; import os from "os"; import { getConfig, findFontFiles, pageBreakBefore, getTableLayouts } from "../makepdf/dist/config/index.js"; import { getFooterFn } from "../makepdf/dist/content/footer.js"; import { OutputContext } from "../makepdf/dist/parser/context.js"; import { parseMarkdownFile } from "../makepdf/dist/parser/parse.js"; const PdfPrinter = (await import("pdfmake")).default; class MakeBook { constructor(config) { this.config = getConfig(config); const PROGRAM_NAME = "MakeBook" if (!this.config.output.info.creator) this.config.output.info.creator = PROGRAM_NAME; if (!this.config.output.info.producer) this.config.output.info.producer = PROGRAM_NAME; if (!this.config.output.info.author) { console.log("Warning: Missing author field in config (output.info.author)"); } if (!this.config.output.info.title) { console.log("Warning: Missing title field in config (output.info.title)"); } if (!this.config.output.info.subject) { console.log("Warning: Missing subject field in config (output.info.subject)"); } } async generate() { const context = new OutputContext(this.config); let content; try { let fileName = this.config.input.entry; if (this.config.input.baseDir) { fileName = path.resolve(this.config.input.baseDir, fileName); } content = await parseMarkdownFile(fileName, context); context.updateRefs(); } catch (err) { if (err.code === "PARSE_ERROR") { console.error(`*** Parse error (${err.fileName}:${err.line})\n${err.message}`); } else { console.error(err); } return process.exit(1); } return this.writePdf(content, context); } writePdf(content, context) { const fonts = findFontFiles(context.config.fonts); const printer = new PdfPrinter(fonts); const pdfDoc = printer.createPdfKitDocument({ info: context.config.output.info, pageSize: context.config.output.pageSize, pageOrientation: context.config.output.pageOrientation, pageMargins: context.config.output.pageMargins, defaultStyle: context.config.styles.default, styles: context.config.styles, pageBreakBefore: pageBreakBefore, content: content, footer: getFooterFn(context.config), }, { tableLayouts: getTableLayouts(context.config), }); return pdfDoc; } font(font, lineHeight = null) { if (typeof font === 'string') { font = { normal: '**/' + font + '-Regular.ttf', bold: '**/' + font + '-Bold.ttf', italics: '**/' + font + '-Italic.ttf' } } // this.config.fonts["Monospaced"] = font; this.config.fonts["Body"] = font; this.config.fonts["Body Bold"] = font; this.config.fonts["Body Light"] = font; this.config.fonts["Headings"] = font; this.config.fonts["Headings Bold"] = font; this.config.fonts["Headings Light"] = font; if (lineHeight !== null) { this.fontLineHeight(lineHeight); } return this; } fontLineHeight(lineHeight) { this.config.styles.default.lineHeight = lineHeight; this.config.styles.toc.lineHeight = lineHeight; // this.config.styles.code.lineHeight = lineHeight; return this; } async save(fileName) { const pdfDoc = await this.generate(); const dirName = path.dirname(fileName); if (!fs.existsSync(dirName)) fs.mkdirSync(dirName, { recursive: true }); return new Promise((resolve, reject) => { const stream = fs.createWriteStream(fileName); pdfDoc.pipe(stream); pdfDoc.end(); stream.on('finish', resolve); stream.on('error', reject); }); } content(markdownContent) { const tmpDir = os.tmpdir(); const tmpFile = path.join(tmpDir, `makebook_${Date.now()}.md`); fs.writeFileSync(tmpFile, markdownContent, 'utf8'); this.config.input.entry = tmpFile; this.config.input.baseDir = tmpDir; return this; } } export default MakeBook;