HTML to PDF or PNG
This commit is contained in:
		
						commit
						3a5d699c9c
					
				| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
node_modules
 | 
			
		||||
.vscode
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
{
 | 
			
		||||
    // Olası öznitelikler hakkında bilgi edinmek için IntelliSense kullanın.
 | 
			
		||||
    // Mevcut özniteliklerin açıklamalarını görüntülemek için üzerine gelin.
 | 
			
		||||
    // Daha fazla bilgi için şu adresi ziyaret edin: https://go.microsoft.com/fwlink/?linkid=830387
 | 
			
		||||
    "version": "0.2.0",
 | 
			
		||||
    "configurations": [
 | 
			
		||||
        {
 | 
			
		||||
          "name": "Debug Main Process",
 | 
			
		||||
          "type": "node",
 | 
			
		||||
          "request": "launch",
 | 
			
		||||
          "cwd": "${workspaceFolder}",
 | 
			
		||||
          "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
 | 
			
		||||
          "windows": {
 | 
			
		||||
            "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
 | 
			
		||||
          },
 | 
			
		||||
          "args" : ["."],
 | 
			
		||||
          "outputCapture": "std"
 | 
			
		||||
        }
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,240 @@
 | 
			
		|||
const { app, BrowserWindow } = require('electron');
 | 
			
		||||
const {randomUUID} = require("node:crypto");
 | 
			
		||||
const { Command } = require('commander');
 | 
			
		||||
const express = require('express');
 | 
			
		||||
const multer = require('multer');
 | 
			
		||||
const path = require("path");
 | 
			
		||||
const fs = require("fs");
 | 
			
		||||
 | 
			
		||||
function writeFile(ext,data)
 | 
			
		||||
{
 | 
			
		||||
    let file = randomUUID() + "." + ext;
 | 
			
		||||
    fs.writeFileSync(
 | 
			
		||||
        path
 | 
			
		||||
            .resolve(
 | 
			
		||||
                __dirname,
 | 
			
		||||
                "./output/",
 | 
			
		||||
                file
 | 
			
		||||
            ),
 | 
			
		||||
        data
 | 
			
		||||
    );
 | 
			
		||||
    return file;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @param {{type,website,range,background,size}} options 
 | 
			
		||||
 * @returns {Promise<[Buffer,string]>}
 | 
			
		||||
 */
 | 
			
		||||
async function generatePDF(options) {
 | 
			
		||||
    const win = new BrowserWindow({
 | 
			
		||||
        webPreferences:{
 | 
			
		||||
            contextIsolation: true,
 | 
			
		||||
            nodeIntegration: false,
 | 
			
		||||
            disableDialogs: false,
 | 
			
		||||
            webSecurity: true
 | 
			
		||||
        },
 | 
			
		||||
        show: false,
 | 
			
		||||
        width: options.width,
 | 
			
		||||
        height: options.height
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    await new Promise(ok => {
 | 
			
		||||
        win.webContents.addListener("did-finish-load",()=>{
 | 
			
		||||
            ok()
 | 
			
		||||
        });
 | 
			
		||||
        win.webContents.addListener("did-fail-load",()=>{
 | 
			
		||||
            console.error("Hata oluştu")
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        if(options.htmlcontent)
 | 
			
		||||
        {
 | 
			
		||||
            win.loadURL(`data:text/html;base64,${Buffer.from(options.htmlcontent).toString("base64")}`);
 | 
			
		||||
        }else{
 | 
			
		||||
            win.loadURL(options.endpoint);
 | 
			
		||||
        }
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    let result = await new Promise(result => {
 | 
			
		||||
        switch(options.type)
 | 
			
		||||
        {
 | 
			
		||||
            case "mhtml":{
 | 
			
		||||
                win.webContents.savePage(path.resolve(__dirname, randomUUID() + ".mhtml"),"HTMLOnly");
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case "image":{
 | 
			
		||||
                win.webContents.setZoomFactor(Math.max(0, Math.min(3.0, options.zoom)))
 | 
			
		||||
                win.webContents.capturePage().then(e => {
 | 
			
		||||
                    let binary = e.toPNG();
 | 
			
		||||
                    result([binary, "png"]);
 | 
			
		||||
                });
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case "pdf":{
 | 
			
		||||
                win.webContents.printToPDF({
 | 
			
		||||
                    printBackground: true,
 | 
			
		||||
                    displayHeaderFooter: false,
 | 
			
		||||
                    scale: options.scale,
 | 
			
		||||
                    landscape: options.landscape,
 | 
			
		||||
                    pageSize: options.pageSize,
 | 
			
		||||
                    pageRanges: options.pageRanges
 | 
			
		||||
                }).then(data => {
 | 
			
		||||
                    result([data, "pdf"]);
 | 
			
		||||
                });
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
    win.destroy();
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
app.disableDomainBlockingFor3DAPIs();
 | 
			
		||||
app.disableHardwareAcceleration();
 | 
			
		||||
 | 
			
		||||
app.addListener("window-all-closed",function(){
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async function main()
 | 
			
		||||
{
 | 
			
		||||
    await new Promise(ok => {
 | 
			
		||||
        app.whenReady().then(() => {
 | 
			
		||||
            ok()
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    let port = express();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    port.use(express.static(path.resolve(__dirname,"./output/"),{
 | 
			
		||||
        acceptRanges: true,
 | 
			
		||||
        cacheControl: true,
 | 
			
		||||
        etag: true,
 | 
			
		||||
        lastModified: true
 | 
			
		||||
    }))
 | 
			
		||||
    port.use(express.static(path.resolve(__dirname,"./public/"),{
 | 
			
		||||
        acceptRanges: true,
 | 
			
		||||
        cacheControl: true,
 | 
			
		||||
        etag: true,
 | 
			
		||||
        lastModified: true
 | 
			
		||||
    }))
 | 
			
		||||
 | 
			
		||||
    port.use(function(request, response, next){
 | 
			
		||||
        response.header("Access-Control-Allow-Origin","*");
 | 
			
		||||
        response.header("Access-Control-Allow-Headers","*");
 | 
			
		||||
        response.header("Access-Control-Allow-Methods","GET, POST, OPTION");
 | 
			
		||||
        next();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    let memory = multer({storage: multer.memoryStorage()}).none();
 | 
			
		||||
 | 
			
		||||
    port.post("/pdf", memory,async (request, response) => {
 | 
			
		||||
 | 
			
		||||
        let {
 | 
			
		||||
            width,
 | 
			
		||||
            height,
 | 
			
		||||
            scale,
 | 
			
		||||
            content: htmlcontent,
 | 
			
		||||
            endpoint,
 | 
			
		||||
            isLandscape,
 | 
			
		||||
            pageSize,
 | 
			
		||||
            pageRanges,
 | 
			
		||||
            output
 | 
			
		||||
        } = request.body;
 | 
			
		||||
 | 
			
		||||
        output = output || "content";
 | 
			
		||||
 | 
			
		||||
        let [content, extension] = await generatePDF({
 | 
			
		||||
            htmlcontent,
 | 
			
		||||
            endpoint,
 | 
			
		||||
            type: "pdf",
 | 
			
		||||
            landscape: isLandscape || false,
 | 
			
		||||
            scale: scale || 1.0,
 | 
			
		||||
            width: width || 1920,
 | 
			
		||||
            height: height || 1080,
 | 
			
		||||
            pageSize: pageSize || "A4",
 | 
			
		||||
            range: pageRanges || ""
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        switch(output)
 | 
			
		||||
        {
 | 
			
		||||
            case "json":{
 | 
			
		||||
                let image = writeFile(extension,content);
 | 
			
		||||
                response.json({
 | 
			
		||||
                    status: "success",
 | 
			
		||||
                    data: image,
 | 
			
		||||
                    type: "pdf"
 | 
			
		||||
                });
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case "json+base64":{
 | 
			
		||||
                response.json({
 | 
			
		||||
                    status: "success",
 | 
			
		||||
                    data: `data:application/pdf;base64,${content.toString("base64")}`,
 | 
			
		||||
                    type: "pdf"
 | 
			
		||||
                });
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case "content":{
 | 
			
		||||
                response.contentType(extension);
 | 
			
		||||
                response.end(content);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    port.post("/image", memory,async (request, response) => {
 | 
			
		||||
        let {
 | 
			
		||||
            width,
 | 
			
		||||
            height,
 | 
			
		||||
            zoom,
 | 
			
		||||
            content: htmlcontent,
 | 
			
		||||
            endpoint,
 | 
			
		||||
            output
 | 
			
		||||
        } = request.body;
 | 
			
		||||
 | 
			
		||||
        output = output || "content";
 | 
			
		||||
 | 
			
		||||
        let [content, extension] = await generatePDF({
 | 
			
		||||
            htmlcontent,
 | 
			
		||||
            endpoint,
 | 
			
		||||
            type: "image",
 | 
			
		||||
            zoom: zoom || 1.0,
 | 
			
		||||
            width: width || 1920,
 | 
			
		||||
            height: height || 1080
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        switch(output)
 | 
			
		||||
        {
 | 
			
		||||
            case "json":{
 | 
			
		||||
                let image = writeFile(extension,content);
 | 
			
		||||
                response.json({
 | 
			
		||||
                    status: "success",
 | 
			
		||||
                    data: image,
 | 
			
		||||
                    type: "image"
 | 
			
		||||
                });
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case "json+base64":{
 | 
			
		||||
                response.json({
 | 
			
		||||
                    status: "success",
 | 
			
		||||
                    data: `data:image/png;base64,${content.toString("base64")}`,
 | 
			
		||||
                    type: "image"
 | 
			
		||||
                });
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case "content":{
 | 
			
		||||
                response.contentType(extension);
 | 
			
		||||
                response.end(content);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
    port.listen(8473);
 | 
			
		||||
}
 | 
			
		||||
process.nextTick(main);
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "pdfgenerator",
 | 
			
		||||
  "version": "1.0.0",
 | 
			
		||||
  "main": "main.js",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "start": "electron . --inspect"
 | 
			
		||||
  },
 | 
			
		||||
  "author": "",
 | 
			
		||||
  "license": "ISC",
 | 
			
		||||
  "description": "",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "commander": "^12.1.0",
 | 
			
		||||
    "electron": "^32.1.2",
 | 
			
		||||
    "express": "^4.21.0",
 | 
			
		||||
    "multer": "^1.4.5-lts.1"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
<head>
 | 
			
		||||
    <meta charset="UTF-8">
 | 
			
		||||
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
			
		||||
    <title>Document</title>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
    <script src="./script.js"></script>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,112 @@
 | 
			
		|||
/*
 | 
			
		||||
    imagé({
 | 
			
		||||
        input: "htmlcontent",
 | 
			
		||||
        content: "<meta charset=\"UTF-8\"><h1 style='background-color:red;color:White'>This is a PDF</h1>",
 | 
			
		||||
        generate: "pdf",
 | 
			
		||||
        output: "json",
 | 
			
		||||
        success: (data)=> {
 | 
			
		||||
            console.log(data)
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
*/
 | 
			
		||||
async function imagé(options)
 | 
			
		||||
{
 | 
			
		||||
    if(typeof options != "object")
 | 
			
		||||
    {
 | 
			
		||||
        throw new Error();
 | 
			
		||||
    }
 | 
			
		||||
    const {
 | 
			
		||||
        input,
 | 
			
		||||
        content,
 | 
			
		||||
        endpoint,
 | 
			
		||||
        generate,
 | 
			
		||||
        output,
 | 
			
		||||
        success,
 | 
			
		||||
        ...otheroptions
 | 
			
		||||
    } = options;
 | 
			
		||||
 | 
			
		||||
    let form = new FormData();
 | 
			
		||||
 | 
			
		||||
    if(input == "htmlcontent")
 | 
			
		||||
    {
 | 
			
		||||
        if(typeof content != "string" || !content){
 | 
			
		||||
            throw new Error();
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        form.append("content", content)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(input == "endpoint")
 | 
			
		||||
    {
 | 
			
		||||
        if(typeof endpoint != "string" || !endpoint){
 | 
			
		||||
            throw new Error();
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        form.append("endpoint", content)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(generate != "pdf" && generate == "image")
 | 
			
		||||
    {
 | 
			
		||||
        throw new Error();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    switch(output)
 | 
			
		||||
    {
 | 
			
		||||
        case "json":
 | 
			
		||||
        case "json+base64":
 | 
			
		||||
        case "content":{
 | 
			
		||||
            form.append("output", output);
 | 
			
		||||
            break;
 | 
			
		||||
        };
 | 
			
		||||
        default:{
 | 
			
		||||
            throw new Error();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (const name in otheroptions) {
 | 
			
		||||
        const value = otheroptions[name];
 | 
			
		||||
        form.append(name, value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let t = await fetch("http://localhost:8473/" + generate,{
 | 
			
		||||
        method:"post",
 | 
			
		||||
        body: form
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    if(!t.ok)
 | 
			
		||||
    {
 | 
			
		||||
        throw new Error();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(
 | 
			
		||||
        t.headers.get("content-type").indexOf("application/pdf") != -1 ||
 | 
			
		||||
        t.headers.get("content-type").indexOf("image/png") != -1
 | 
			
		||||
    )
 | 
			
		||||
    {
 | 
			
		||||
        let blob = await t.blob(), file;
 | 
			
		||||
        if(generate == "pdf")
 | 
			
		||||
        {
 | 
			
		||||
            file = new File([blob],"File.pdf",{
 | 
			
		||||
                lastModified: new Date(),
 | 
			
		||||
                type:"application/pdf"
 | 
			
		||||
            });
 | 
			
		||||
        }else if(generate == "image"){
 | 
			
		||||
            file = new File([blob],"File.png",{
 | 
			
		||||
                lastModified: new Date(),
 | 
			
		||||
                type:"image/png"
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        return (
 | 
			
		||||
            typeof options.success == "function" &&
 | 
			
		||||
            options.success(file),
 | 
			
		||||
            file
 | 
			
		||||
        );
 | 
			
		||||
    }else{
 | 
			
		||||
        let data = await t.json();
 | 
			
		||||
        return (
 | 
			
		||||
            typeof options.success == "function" &&
 | 
			
		||||
            options.success(data),
 | 
			
		||||
            data
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue