Initial commit

This commit is contained in:
Steven 2019-01-01 19:19:25 -05:00
commit 690d825f9a
9 changed files with 158 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
node_modules
package-lock.json

25
card.js Normal file
View File

@ -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);
}
};

19
chromium.js Normal file
View File

@ -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 };

5
dev.js Normal file
View File

@ -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);

21
file.js Normal file
View File

@ -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 }

11
now.json Normal file
View File

@ -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" }
]
}

16
package.json Normal file
View File

@ -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"
}
}

12
parser.js Normal file
View File

@ -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 }

47
template.js Normal file
View File

@ -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 }