diff --git a/package.json b/package.json index 00bd151..cfbd746 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,8 @@ "license": "CC-BY-NC-SA-4.0", "dependencies": { "@odit/class-validator-jsonschema": "^2.1.1", + "axios": "^0.21.1", + "cheerio": "^1.0.0-rc.5", "class-transformer": "0.3.1", "class-validator": "^0.13.1", "consola": "^2.15.0", @@ -48,6 +50,7 @@ "handlebars": "^4.7.6", "i18next": "^19.8.7", "i18next-fs-backend": "^1.0.8", + "mime-types": "^2.1.28", "puppeteer": "^7.0.1", "reflect-metadata": "^0.1.13", "routing-controllers": "^0.9.0-alpha.6", @@ -77,4 +80,4 @@ "publish": false } } -} \ No newline at end of file +} diff --git a/src/PdfCreator.ts b/src/PdfCreator.ts index 97bb157..6b81587 100644 --- a/src/PdfCreator.ts +++ b/src/PdfCreator.ts @@ -1,11 +1,13 @@ +import axios from 'axios'; +import cheerio from "cheerio"; import fs from "fs"; import Handlebars from 'handlebars'; import i18next from "i18next"; import Backend from 'i18next-fs-backend'; +import mime from "mime-types"; import path from 'path'; import puppeteer from "puppeteer"; import { Runner } from './models/Runner'; - /** * This class is responsible for all things pdf creation. * This uses the html templates from src/templates. @@ -58,12 +60,47 @@ export class PdfCreator { return await this.renderPdf(result, { format: "A5", landscape: true }); } + /** + * Converts all images in html to base64. + * Works with image files in the template directory or images from urls. + * @param html The html string whoms images shall get replaced. + */ + public async imgToBase64(html): Promise { + const $ = cheerio.load(html) + $('img').each(async (index, element) => { + let imgsrc = $(element).attr("src"); + const img_type = mime.lookup(imgsrc); + + if (!(img_type.includes("image"))) { + throw new Error("File is not image mime type"); + } + + let image; + if (imgsrc.startsWith("http")) { + image = (await axios.get(imgsrc)).data; + image = Buffer.from(image).toString('base64'); + } + else { + if (imgsrc.startsWith("./")) { + imgsrc = imgsrc.replace("./", ""); + } + image = fs.readFileSync(`${this.templateDir}/${imgsrc}`, { encoding: "base64" }); + } + + image = `data:${img_type};base64,${image}` + $(element).attr("src", image) + }) + + return $.html(); + } + /** * This method manages the creation of pdfs via puppeteer. * @param html The HTML that should get rendered. * @param options Puppeteer PDF option (eg: {format: "A4"}) */ public async renderPdf(html: string, options): Promise { + html = await this.imgToBase64(html); let page = await this.browser.newPage(); await page.setContent(html); const pdf = await page.pdf(options);