From d0ea5d1b1b95df263fc1abb4276fd2bbc66ec629 Mon Sep 17 00:00:00 2001 From: monoid Date: Fri, 29 Apr 2022 01:00:41 +0900 Subject: [PATCH] feat: print to PDF --- cli.py | 25 +++++++++++++++-- tools/printPdf.ts | 69 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 tools/printPdf.ts diff --git a/cli.py b/cli.py index edf259a..a8e47e2 100644 --- a/cli.py +++ b/cli.py @@ -40,7 +40,7 @@ def serve(args): """serve the documentation and reload on changes""" parser = argparse.ArgumentParser(description='Serve the documentation and reload changes', prog="cli.py serve") parser.add_argument('-v', '--verbose', action='store_true', help='verbose mode') - parser.add_argument('-p', '--port', default=8000, help='port') + parser.add_argument('-p', '--port', default=3000, help='port') parser.add_argument('--update_issues', action='store_true', help='update issues') outDir = "build" issuePath = os.path.join(outDir,"issues.json") @@ -68,11 +68,32 @@ def issueUpdate(args): issuePath = os.path.join(args.outDir,"issues.json") updateIssue(issuePath, args.verbose) +def buildPdf(args): + parser = argparse.ArgumentParser(description='Print to pdf', prog="cli.py buildPdf") + parser.add_argument('-v', '--verbose', action='store_true', help='verbose mode') + parser.add_argument('--outDir', default="build/doc.pdf", help='output directory') + parser.add_argument('--browser-path', help='path to the browser') + args = parser.parse_args(args) + absPath = os.path.normpath(os.path.join( os.getcwd(),'book' , 'print.html' )).replace('\\', '/') + url = f"file://{absPath}" + if args.verbose: + print("build start") + print("print url", url) + cmd = ["deno", "run","--unstable" ,"-A","tools/printPdf.ts", "--outDir", args.outDir, "--url", url] + if args.browser_path: + cmd.append("--chromeDir") + cmd.append(args.browser_path) + if args.verbose: + print("cmd: ", " ".join(cmd)) + p = subprocess.run(cmd) + p.check_returncode() + commandList = { 'build': build, 'help': help, 'issueUpdate': issueUpdate, - 'serve': serve + 'serve': serve, + 'buildPdf': buildPdf } def main(): diff --git a/tools/printPdf.ts b/tools/printPdf.ts new file mode 100644 index 0000000..1a935f0 --- /dev/null +++ b/tools/printPdf.ts @@ -0,0 +1,69 @@ +import puppeteer from "https://deno.land/x/puppeteer@9.0.2/mod.ts"; +import { parse as argParse } from "https://deno.land/std@0.136.0/flags/mod.ts"; +import {join as pathJoin} from "https://deno.land/std@0.136.0/path/mod.ts"; + +const executablePathMap = { + windows: "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + //"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe", + darwin: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", + linux: "/usr/bin/chromium-browser", +}; + +function findChromeDir(){ + const dir = executablePathMap[Deno.build.os]; + if (Deno.build.os === "linux"){ + const pathes = Deno.env.get("PATH")?.split(";"); + if(!pathes){ + return dir; + } + for (const path of pathes){ + const entries = [...Deno.readDirSync(path)]; + const chrome = entries.find((entry) => entry.name === "chrome"); + if(chrome) { + return pathJoin(path, chrome.name); + } + } + } + return dir; +} + +async function main() { + const args = argParse(Deno.args); + let { url, outDir, chromeDir } = args; + if (!url) { + console.error("No url provided."); + Deno.exit(1); + } + outDir = outDir ?? "out.pdf"; + if(!chromeDir) { + console.log("No chromeDir provided. Try to find chrome."); + chromeDir = findChromeDir(); + console.log(`chromeDir: ${chromeDir}`); + } + + const browser = await puppeteer.launch({ + product: "chrome", + headless: true, + executablePath: chromeDir, + }); + + const page = await browser.newPage(); + console.log(`goto url ${url}`); + await page.goto(url, { + waitUntil: "networkidle2", + }); + await page.pdf({ + path: outDir, + margin: { + bottom: "1cm", + left: "1cm", + right: "1cm", + top: "1cm", + } + }); + await browser.close(); +} + +if (import.meta.main) { + main(); +} \ No newline at end of file