Created
January 16, 2023 18:44
-
-
Save marshmallowrobot/06108e75fec53408188f759beb7ed6ce to your computer and use it in GitHub Desktop.
Programmatically generate an image with custom text using a headless browser to screenshot an HTML page
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { join } = require('node:path'); | |
const { writeFileSync } = require('node:fs'); | |
const puppeteer = require('puppeteer'); | |
const imageHtmlHead = () => { | |
return ` | |
<head> | |
<link rel="preconnect" href="https://fonts.googleapis.com"> | |
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
<link href="https://fonts.googleapis.com/css2?family=Source+Serif+Pro&family=PT+Sans&display=swap" rel="stylesheet"> | |
<style> | |
@import url('https://fonts.googleapis.com/css2?family=Source+Serif+Pro:wght@400;700&family=PT+Sans:wght@400;700&display=swap'); | |
* { | |
margin: 0; | |
padding: 0; | |
box-sizing: border-box; | |
} | |
html { | |
font-family: 'PT Sans'; | |
font-size: 12px; | |
color: white; | |
} | |
body { | |
min-height: 576px; | |
min-width: 1024px; | |
} | |
.container { | |
background-image: url('https://upload.wikimedia.org/wikipedia/commons/thumb/9/9a/A_laptop_and_a_notebook_on_the_wooden_table_%28Pixabay%29.jpg/1024px-A_laptop_and_a_notebook_on_the_wooden_table_%28Pixabay%29.jpg'); | |
background-repeat: no-repeat; | |
display: flex; | |
flex-direction: row; | |
/* maintain 16:9 aspect ratio */ | |
height: 576px; | |
width: 1024px; | |
} | |
.color-field { | |
border-bottom: 576px solid rgba(0, 103, 78, 0.75); | |
border-right: 180px solid transparent; | |
position: relative; | |
width: 512px; | |
z-index: 0; | |
} | |
.title { | |
font-family: 'Source Serif Pro', serif; | |
font-size: 5rem; | |
margin: 26rem 0 0 2rem; | |
position: absolute; | |
z-index: 1; | |
} | |
.subtitle { | |
font-family: 'PT Sans', sans-serif; | |
font-size: 2.2rem; | |
position: absolute; | |
margin: 32rem 0 0 2rem; | |
z-index: 1; | |
} | |
</style> | |
</head> | |
`; | |
} | |
const imageHtmlBody = (titleText, subtitleText) => { | |
return ` | |
<body> | |
<div class="container"> | |
<div class="color-field"></div> | |
<span class="title">${titleText}</span> | |
<span class="subtitle">${subtitleText}</span> | |
</div> | |
</body> | |
`; | |
} | |
const imageMarkup = (titleText, subtitleText) => { | |
return ` | |
<!DOCTYPE html> | |
<html> | |
${imageHtmlHead()} | |
${imageHtmlBody(titleText, subtitleText)} | |
</html> | |
`; | |
} | |
/** | |
* Creates a new image with the given text values. | |
* Writes the image to the given path. | |
* Returns the file name of the newly generated image. | |
* | |
* NOTE: The given text becomes the generated file name. | |
* Dont use crazy characters, try not to duplicate. | |
* **/ | |
module.exports = generateImage = async (baseWritePath, titleText, subtitleText) => { | |
const imageName = `${titleText}-${subtitleText}.png`; | |
const browser = await puppeteer.launch(); | |
const page = await browser.newPage(); | |
try { | |
await page.setContent(imageMarkup(titleText, subtitleText)); | |
const content = await page.$('body'); | |
const imageBuffer = await content.screenshot(); | |
writeFileSync(join(baseWritePath, imageName), imageBuffer); | |
return imageName; | |
} | |
catch (error) { | |
console.error(error); | |
return ''; | |
} | |
finally { | |
await browser.close(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment