diff --git a/libs/html-templates-lib.ts b/libs/html-templates-lib.ts index 43a3fdd..af1a9eb 100644 --- a/libs/html-templates-lib.ts +++ b/libs/html-templates-lib.ts @@ -3,19 +3,19 @@ export const htmlTemplateRoute = express.Router() import { mimeToExtension, templateOption } from "./report-template" // import fs from "fs" //import { chromium } from 'playwright' -import puppeteer,{PDFOptions} from 'puppeteer' -import Handlebars from 'handlebars' +import puppeteer, { PDFOptions } from "puppeteer" +import Handlebars from "handlebars" import e from "express" //import { createReport } from "docx-templates" // แก้ package.json ของ LibreOfficeFileConverter // https://github.com/microsoft/TypeScript/issues/52363#issuecomment-1659179354 //import { LibreOfficeFileConverter } from "libreoffice-file-converter" const TEMPLATE_FOLDER_NAME = "templates/html" -const width_px = 1200; //TODO read from htmlOption +const width_px = 1200 //TODO read from htmlOption /** * docxTemplate Uses docx-template to convert input data and template to output buffer. - * SPA and lazy load page may not fully render(eg. pantip.com). + * SPA and lazy load page may not fully render(eg. pantip.com). * You have to handle exception throw by function * handlebars template support only content from Buffer * @param {Buffer|String} t template in buffer format or url to web page @@ -25,32 +25,31 @@ const width_px = 1200; //TODO read from htmlOption */ export async function htmlTemplateX(t: Buffer | String, tdata: templateOption, outputMediaType: string = "pdf"): Promise { try { - if (!["pdf", "jpeg", "png"].find((e) => e === outputMediaType)) { + if (!["pdf", "jpeg", "png"].find(e => e === outputMediaType)) { throw "FormatError" } - const browser = await puppeteer.launch({ headless: true,args: ['--no-sandbox'] }); - const page = await browser.newPage(); - page.setDefaultNavigationTimeout(120000); + const browser = await puppeteer.launch({ headless: true, args: ["--no-sandbox"] }) + const page = await browser.newPage() + // page.setDefaultNavigationTimeout(120000); await page.setViewport({ width: width_px, height: 800, deviceScaleFactor: 2, - isMobile: false - }); - if (typeof t === 'string') { - await page.goto(t, { waitUntil: 'networkidle0' }); + isMobile: false, + }) + if (typeof t === "string") { + await page.goto(t, { waitUntil: "networkidle0" }) } else { if (tdata.data) { - const template = Handlebars.compile(t.toString()); - const html = template(tdata.data); - await page.setContent(html); + const template = Handlebars.compile(t.toString()) + const html = template(tdata.data) + await page.setContent(html) } else { await page.setContent(t.toString()) } } - -/* + /* // try to load whole page let x = await page.evaluate(async (tdata) => { const scrollableSection = @@ -74,30 +73,29 @@ export async function htmlTemplateX(t: Buffer | String, tdata: templateOption, o */ //find real page height - const totalHeight = await page.evaluate(async (tdata) => { + const totalHeight = await page.evaluate(async tdata => { let scrollableSection = - (tdata.htmlOption?.querySelector && - document.querySelector(tdata.htmlOption.querySelector) && document.querySelector(tdata.htmlOption.querySelector)) ? - document.querySelector(tdata.htmlOption.querySelector) : null + tdata.htmlOption?.querySelector && document.querySelector(tdata.htmlOption.querySelector) && document.querySelector(tdata.htmlOption.querySelector) + ? document.querySelector(tdata.htmlOption.querySelector) + : null - const childElement = scrollableSection? scrollableSection: document.body - if(scrollableSection ==null) - scrollableSection = document.body - //const childElement = scrollableSection.firstElementChild; - let scrollPosition = 0; - let viewportHeight = window.innerHeight; - while (scrollPosition < childElement.scrollHeight) { - scrollableSection.scrollBy(0, viewportHeight); - await new Promise(resolve => setTimeout(resolve, 500)); - scrollPosition += viewportHeight; - } - return childElement.scrollHeight - }, tdata); + const childElement = scrollableSection ? scrollableSection : document.body + if (scrollableSection == null) scrollableSection = document.body + //const childElement = scrollableSection.firstElementChild; + let scrollPosition = 0 + let viewportHeight = window.innerHeight + while (scrollPosition < childElement.scrollHeight) { + scrollableSection.scrollBy(0, viewportHeight) + // await new Promise(resolve => setTimeout(resolve, 500)); + scrollPosition += viewportHeight + } + return childElement.scrollHeight + }, tdata) if (!totalHeight) { - throw new Error(`Unable to determine the page height ${totalHeight}. The selector may not correct or no body tag`); + throw new Error(`Unable to determine the page height ${totalHeight}. The selector may not correct or no body tag`) } else { - console.log("Page height adjusted to:", totalHeight); + console.log("Page height adjusted to:", totalHeight) } console.log("set viewport ") @@ -105,22 +103,22 @@ export async function htmlTemplateX(t: Buffer | String, tdata: templateOption, o width: width_px, height: totalHeight, deviceScaleFactor: 2, - isMobile: false - }); + isMobile: false, + }) ///// output to photo end here if (outputMediaType === "png" || outputMediaType === "jpeg") { - const photoBuffer = await page.screenshot({ + const photoBuffer = await page.screenshot({ // path: 'url_pup.png', fullPage: true, - type: outputMediaType // 'webp' + type: outputMediaType, // 'webp' }) - await browser.close(); + await browser.close() return photoBuffer } ///// output to PDF //TODO overide option from htmlTemplateOption - let pdfOption:PDFOptions = { + let pdfOption: PDFOptions = { // path: './url_prop.pdf', // format:"A4", width: width_px, @@ -128,10 +126,10 @@ export async function htmlTemplateX(t: Buffer | String, tdata: templateOption, o printBackground: true, scale: 1, displayHeaderFooter: false, - margin: { top: 5, right: 5, bottom: 5, left: 5 } + margin: { top: 5, right: 5, bottom: 5, left: 5 }, } - const buffer = await page.pdf(pdfOption); - await browser.close(); + const buffer = await page.pdf(pdfOption) + await browser.close() return buffer } catch (e) { //console.log(e) @@ -180,7 +178,7 @@ export async function htmlTemplateX(t: Buffer | String, tdata: templateOption, o htmlTemplateRoute.post("/", async function (req, res) { try { if (!req.headers["content-type"] || !req.headers["accept"]) throw new Error("Require header content-type, accept") - let inputType = mimeToExtension(req.headers["content-type"])// application/json + let inputType = mimeToExtension(req.headers["content-type"]) // application/json let outputMediaType = mimeToExtension(req.headers["accept"]) let buffer = await htmlTemplateX(req.body.template, req.body, outputMediaType) res.statusCode = 201 @@ -189,12 +187,12 @@ htmlTemplateRoute.post("/", async function (req, res) { res.setHeader("Content-Length", buffer.length) res.end(buffer) } catch (ex) { - if(ex instanceof SyntaxError){ + if (ex instanceof SyntaxError) { res.statusCode = 400 res.statusMessage = ex.message res.end(res.statusMessage) console.error("report-template/html: ", ex) - }else{ + } else { res.statusCode = 500 res.statusMessage = "Internal Server Error during POST report-template/html" res.end(res.statusMessage) @@ -202,4 +200,3 @@ htmlTemplateRoute.post("/", async function (req, res) { } } }) -