Initial commit
This commit is contained in:
commit
690d825f9a
|
@ -0,0 +1,2 @@
|
|||
node_modules
|
||||
package-lock.json
|
|
@ -0,0 +1,25 @@
|
|||
const { parseRequest } = require('./parser');
|
||||
const { getScreenshot } = require('./chromium');
|
||||
const { getHtml } = require('./template');
|
||||
const { writeTempFile, pathToFileURL } = require('./file');
|
||||
|
||||
module.exports = async function (req, res) {
|
||||
try {
|
||||
let { type = 'png', text = 'Hello' } = parseRequest(req);
|
||||
const name = decodeURIComponent(text);
|
||||
const html = getHtml(name);
|
||||
const filePath = await writeTempFile(name, html);
|
||||
const fileUrl = pathToFileURL(filePath);
|
||||
const file = await getScreenshot(fileUrl, type);
|
||||
res.statusCode = 200;
|
||||
res.setHeader('Content-Type', `image/${type}`);
|
||||
res.setHeader('Cache-Control', `public, immutable, no-transform, max-age=31536000`);
|
||||
res.end(file);
|
||||
} catch (e) {
|
||||
res.statusCode = 500;
|
||||
res.setHeader('Content-Type', 'text/html');
|
||||
res.end('<h1>Server Error</h1><p>Sorry, there was a problem</p>');
|
||||
console.error(e.message);
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
const chrome = require('chrome-aws-lambda');
|
||||
const puppeteer = require('puppeteer-core');
|
||||
|
||||
async function getScreenshot(url, type) {
|
||||
const browser = await puppeteer.launch({
|
||||
args: chrome.args,
|
||||
executablePath: await chrome.executablePath,
|
||||
headless: chrome.headless,
|
||||
});
|
||||
|
||||
const page = await browser.newPage();
|
||||
await page.setViewport({ width: 2048, height: 1170 });
|
||||
await page.goto(url);
|
||||
const file = await page.screenshot({ type });
|
||||
await browser.close();
|
||||
return file;
|
||||
}
|
||||
|
||||
module.exports = { getScreenshot };
|
|
@ -0,0 +1,5 @@
|
|||
const { createServer } = require('http');
|
||||
const PORT = 3000;
|
||||
const handleServer = require('./card');
|
||||
const handleListen = () => console.log(`Listening on ${PORT}...`);
|
||||
createServer(handleServer).listen(PORT, handleListen);
|
|
@ -0,0 +1,21 @@
|
|||
const { writeFile } = require('fs');
|
||||
const { join } = require('path');
|
||||
const { promisify } = require('util');
|
||||
const writeFileAsync = promisify(writeFile);
|
||||
const { tmpdir } = require('os');
|
||||
const { URL } = require('url');
|
||||
|
||||
async function writeTempFile(name, contents) {
|
||||
const randomPath = join(tmpdir(), `${name}.html`);
|
||||
console.log('Writing file to ' + randomPath);
|
||||
await writeFileAsync(randomPath, contents);
|
||||
return randomPath;
|
||||
}
|
||||
|
||||
function pathToFileURL(path) {
|
||||
const { href } = new URL(path, 'file:');
|
||||
console.log('File url is ' + href);
|
||||
return href;
|
||||
}
|
||||
|
||||
module.exports = { writeTempFile, pathToFileURL }
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"name": "og-image",
|
||||
"alias": "og-image.now.sh",
|
||||
"version": 2,
|
||||
"builds": [
|
||||
{ "src": "card.js", "use": "@now/node", "config": { "maxLambdaSize": "40mb" } }
|
||||
],
|
||||
"routes": [
|
||||
{ "src": "/(.*)", "dest": "/card.js" }
|
||||
]
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"name": "og-image",
|
||||
"version": "1.0.0",
|
||||
"description": "Generate an open graph image for twitter/facebook/etc",
|
||||
"main": "card.js",
|
||||
"scripts": {
|
||||
"dev": "node dev.js"
|
||||
},
|
||||
"author": "styfle",
|
||||
"repository": "github:styfle/og-image",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chrome-aws-lambda": "1.11.1",
|
||||
"puppeteer-core": "1.11.0"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
const { parse } = require('url');
|
||||
|
||||
function parseRequest(req) {
|
||||
const { pathname = '/' } = parse(req.url);
|
||||
console.log('Hit ' + pathname);
|
||||
const arr = pathname.slice(1).split('.');
|
||||
const type = arr.pop();
|
||||
const text = arr.join('.');
|
||||
return { type, text };
|
||||
}
|
||||
|
||||
module.exports = { parseRequest }
|
|
@ -0,0 +1,47 @@
|
|||
|
||||
const logo = 'https://assets.zeit.co/image/upload/front/assets/design/now-black.svg';
|
||||
|
||||
const css = `
|
||||
body {
|
||||
background: white;
|
||||
background-image: radial-gradient(lightgray 5%, transparent 0);
|
||||
background-size: 100px 100px;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 225px;
|
||||
height: 225px;
|
||||
}
|
||||
|
||||
.spacer {
|
||||
margin: 150px;
|
||||
}
|
||||
|
||||
.heading {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
||||
font-size: 75px;
|
||||
font-weight: bold;
|
||||
}`;
|
||||
|
||||
function getHtml(text) {
|
||||
return `<html>
|
||||
<style>
|
||||
${css}
|
||||
</style>
|
||||
<body>
|
||||
<div>
|
||||
<div class="spacer">
|
||||
<img class="logo" src="${logo}" />
|
||||
<div class="spacer">
|
||||
<div class="heading">${text}</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>`;
|
||||
}
|
||||
|
||||
module.exports = { getHtml }
|
Loading…
Reference in New Issue