|
|
@ -5,6 +5,7 @@ import logging from '../lib/logging.js'; |
|
|
|
import glob from "fast-glob"; |
|
|
|
import glob from "fast-glob"; |
|
|
|
import path from "path"; |
|
|
|
import path from "path"; |
|
|
|
import template from "lodash/template.js"; |
|
|
|
import template from "lodash/template.js"; |
|
|
|
|
|
|
|
import { defer } from "../lib/api.js"; |
|
|
|
import PDFDocument from "pdfkit"; |
|
|
|
import PDFDocument from "pdfkit"; |
|
|
|
|
|
|
|
|
|
|
|
const log = logging.create(import.meta.url); |
|
|
|
const log = logging.create(import.meta.url); |
|
|
@ -21,12 +22,12 @@ export const description = "Generates a PDF presentation from an input .md file |
|
|
|
export const options = [ |
|
|
|
export const options = [ |
|
|
|
["--heading-font <path>", "Font file to use for headings.", "static/fonts/VictorMono-Bold.ttf"], |
|
|
|
["--heading-font <path>", "Font file to use for headings.", "static/fonts/VictorMono-Bold.ttf"], |
|
|
|
["--body-font <path>", "Font file to use for body text.", "static/fonts/VictorMono-Medium.ttf"], |
|
|
|
["--body-font <path>", "Font file to use for body text.", "static/fonts/VictorMono-Medium.ttf"], |
|
|
|
|
|
|
|
["--output <path>", "The output .pdf file to write. Defaults to <input>.pdf"], |
|
|
|
] |
|
|
|
] |
|
|
|
|
|
|
|
|
|
|
|
// put required options in the required variable
|
|
|
|
// put required options in the required variable
|
|
|
|
export const required = [ |
|
|
|
export const required = [ |
|
|
|
["--input <path>", "The input .md file for the generated presentation."], |
|
|
|
["--input <path>", "The input .md file for the generated presentation."], |
|
|
|
["--output <path>", "The output .pdf file to write."], |
|
|
|
|
|
|
|
["--template <path>", "The background template image to use."], |
|
|
|
["--template <path>", "The background template image to use."], |
|
|
|
] |
|
|
|
] |
|
|
|
|
|
|
|
|
|
|
@ -69,7 +70,7 @@ const write_page = (doc, template, content) => { |
|
|
|
// create the left side constant summary
|
|
|
|
// create the left side constant summary
|
|
|
|
doc.fontSize(40); |
|
|
|
doc.fontSize(40); |
|
|
|
doc.font("heading").text(content.title, title_box.x, title_box.y, title_box); |
|
|
|
doc.font("heading").text(content.title, title_box.x, title_box.y, title_box); |
|
|
|
doc.fontSize(20); |
|
|
|
doc.fontSize(30); |
|
|
|
doc.moveDown(); |
|
|
|
doc.moveDown(); |
|
|
|
// the lesson summary
|
|
|
|
// the lesson summary
|
|
|
|
doc.font("body").text(content.summary, summary_box); |
|
|
|
doc.font("body").text(content.summary, summary_box); |
|
|
@ -165,18 +166,27 @@ const parse_input = (input) => { |
|
|
|
return result; |
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export const main = async (opts) => { |
|
|
|
const make_pdf_path = (input) => { |
|
|
|
|
|
|
|
const result = path.parse(input); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return path.join(result.dir, `${result.name}.pdf`); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const generate_presentation = (opts, waiting) => { |
|
|
|
try { |
|
|
|
try { |
|
|
|
|
|
|
|
if(!opts.output) { |
|
|
|
|
|
|
|
opts.output = make_pdf_path(opts.input); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const [doc, out_stream] = start_pdf(opts); |
|
|
|
const [doc, out_stream] = start_pdf(opts); |
|
|
|
|
|
|
|
|
|
|
|
out_stream.on("finish", () => process.exit(0)); |
|
|
|
out_stream.on("finish", () => waiting.resolve()); |
|
|
|
|
|
|
|
|
|
|
|
const pages = parse_input(opts.input); |
|
|
|
const pages = parse_input(opts.input); |
|
|
|
|
|
|
|
|
|
|
|
for(let i = 0; i < pages.length; i++) { |
|
|
|
for(let i = 0; i < pages.length; i++) { |
|
|
|
const page = pages[i]; |
|
|
|
const page = pages[i]; |
|
|
|
|
|
|
|
|
|
|
|
console.log("PAGE", page); |
|
|
|
|
|
|
|
write_page(doc, opts.template, page); |
|
|
|
write_page(doc, opts.template, page); |
|
|
|
|
|
|
|
|
|
|
|
// don't add a page when at the end
|
|
|
|
// don't add a page when at the end
|
|
|
@ -188,5 +198,21 @@ export const main = async (opts) => { |
|
|
|
end_pdf(doc); |
|
|
|
end_pdf(doc); |
|
|
|
} catch(error) { |
|
|
|
} catch(error) { |
|
|
|
console.error(error); |
|
|
|
console.error(error); |
|
|
|
|
|
|
|
waiting.resolve(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export const main = async (opts) => { |
|
|
|
|
|
|
|
const in_files = glob.sync(opts.input); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(let file of in_files) { |
|
|
|
|
|
|
|
console.log(file); |
|
|
|
|
|
|
|
const waiting = defer(file); |
|
|
|
|
|
|
|
const settings = {...opts}; |
|
|
|
|
|
|
|
settings.input = file; |
|
|
|
|
|
|
|
generate_presentation(settings, waiting); |
|
|
|
|
|
|
|
await waiting; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
process.exit(0); |
|
|
|
|
|
|
|
} |
|
|
|