commit 690d825f9a6014cba758575df000fdcaacd201bb Author: Steven Date: Tue Jan 1 19:19:25 2019 -0500 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..25c8fdb --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +package-lock.json \ No newline at end of file diff --git a/card.js b/card.js new file mode 100644 index 0000000..f929e26 --- /dev/null +++ b/card.js @@ -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('

Server Error

Sorry, there was a problem

'); + console.error(e.message); + } +}; + diff --git a/chromium.js b/chromium.js new file mode 100644 index 0000000..870a1c7 --- /dev/null +++ b/chromium.js @@ -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 }; \ No newline at end of file diff --git a/dev.js b/dev.js new file mode 100644 index 0000000..c863d0c --- /dev/null +++ b/dev.js @@ -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); \ No newline at end of file diff --git a/file.js b/file.js new file mode 100644 index 0000000..94833ed --- /dev/null +++ b/file.js @@ -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 } \ No newline at end of file diff --git a/now.json b/now.json new file mode 100644 index 0000000..a498354 --- /dev/null +++ b/now.json @@ -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" } + ] +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..cc03941 --- /dev/null +++ b/package.json @@ -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" + } +} diff --git a/parser.js b/parser.js new file mode 100644 index 0000000..9c63d3d --- /dev/null +++ b/parser.js @@ -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 } \ No newline at end of file diff --git a/template.js b/template.js new file mode 100644 index 0000000..fccf1c0 --- /dev/null +++ b/template.js @@ -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 ` + + +
+
+ +
+
${text}
+
+ +`; +} + +module.exports = { getHtml } \ No newline at end of file